# Reports

> No — build them on ledger data, then use the reports endpoints to prove you got the same answer. Report output is presentation, with no stable row identity to drill from.

Source: https://lopifi.com/apis/reports
Part of: Lopifi — US GAAP books on autopilot, reviewed by a CPA (https://lopifi.com)

---

**Should you build statements on the reports endpoints?** Reports are for tie-out, not for rendering. Show the variance between our number and theirs; a controller trusts that line more than any chart.

## Divergences between Xero, QuickBooks Online and NetSuite

### Report rows are presentation, not data

Header, section and summary rows are interleaved with data rows, nesting depth carries meaning, and identity is inconsistent. Parsing is possible; drilling from a parsed row back to the transactions behind it generally is not.

**Handling:** Build interactive statements from ledger data. Use the report endpoint on a schedule, assert equality, and surface a variance when it appears.

### Xero's aged reports are per contact

AgedReceivablesByContact takes one contact. Building a full aging report means one call per customer, against a 60-call-per-minute limit — a hundred customers is close to two full minutes of the organisation's budget, and a tenth of a Starter-tier app's 1,000-call day.

**Handling:** Compute aging ourselves from invoices plus unapplied cash, and tie to the ledger's own report for a sample of contacts rather than all of them.
