# Journals and the general ledger

> Xero yes, through a read-only append-only feed that is the best endpoint in any of these APIs. NetSuite yes, through SQL. QuickBooks no — there is no GL endpoint, and that absence shapes every statement you build on it.

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

---

**Can you get the actual general ledger out?** Store debits and credits as two columns. Converting a signed amount to two columns is lossless; the reverse is not.

## Divergences between Xero, QuickBooks Online and NetSuite

### Xero's Journals endpoint is the crown jewel and is easy to miss

It emits the actual general ledger — every posting from invoices, payments, bills, bank transactions and manual journals — as immutable, sequentially numbered records. Paginate by offset on JournalNumber and you have an append-only, gapless, perfectly replayable ledger feed.

**Handling:** Anything that reconciles or re-derives statements builds on /Journals, not on /Invoices. Store the highest JournalNumber seen as the sync cursor; it never goes backwards. Since 2 March 2026 Xero reserves the endpoint for apps on its Advanced partner tier that have passed a security assessment and had the use case approved — so make hasGlFeed a capability you discover, and keep a reconstruct-from-documents fallback for apps without it.

### The Xero GL feed now sits behind a partner tier

From 2 March 2026 the Journals endpoint is available only from the Advanced tier of Xero's developer pricing, and only after an initial and annual security assessment and use-case approval. ManualJournals stays open on every tier, but it holds only the journals people typed — not the postings that invoices, payments and bank transactions generate.

**Handling:** Treat Journals access as a per-app capability, not a property of Xero. Without it, statements are reconstructed from documents and tied to the Reports endpoints, exactly as on QBO, and the provenance label says so.

### QuickBooks has no general ledger endpoint

There is no way to ask QBO for postings. Your three options are the Reports API (correct totals, presentation-shaped rows, no stable ids), reconstructing postings from every transaction entity (you then own the correctness of Intuit's tax and FX posting rules, forever), or mirroring entities via change data capture and deriving statements from the mirror.

**Handling:** Reports API for tie-out, an entity mirror for detail. Display which one produced the number; the two will occasionally disagree.

### NetSuite requires you to pick the right line table and book

transactionline is the transaction's lines; transactionaccountingline carries the debit and credit amounts, per accounting book. Query the wrong one and you get quantities without postings, or every book summed together.

**Handling:** Always filter posting = 'T' and accountingbook explicitly. Never rely on the default book being 1 without checking the account's configuration.

## Canonical shape

```ts
type JournalLine = {
  accountId: string;
  /** Two columns. Exactly one is non-zero. Never a single signed amount. */
  debit: Money;
  credit: Money;
  dimensions: LineDimension[];
  partyId?: string;      // absent on Xero's GL feed
  memo?: string;
};

type Journal = {
  id: string;
  /** Xero's JournalNumber, NetSuite's internal id. Gapless where the source is. */
  sequence?: number;
  date: string;
  periodId?: string;
  /** What created this posting: an invoice, a payment, a manual entry. */
  origin: { type: string; documentId?: string };
  lines: JournalLine[];        // >= 2, and they balance
  book?: string;               // NetSuite accounting book
  source: SourceRef;
};
```
