Pagination
Keyset paging, list direction, dates and minor-unit amounts.
Paged list endpoints use keyset pagination, with the same two parameters:
limit— page size, 1–100 (default 20).cursor— where to continue from. Omit it (or pass0) for the first page.
Each page reports how to continue:
{
"invoices": [ ... ],
"hasMore": true,
"nextCursor": 4177
}
Pass nextCursor back as cursor until hasMore is false. That loop is
the same code on every list in this API.
Keyset paging is stable under concurrent inserts: new rows appear on the first page of a fresh iteration and never shift the pages of an iteration already in flight.
Direction is a property of the list, not of the parameter
The lists do not all walk the same way, and that part is deliberate:
| List | Order | A cursor means |
|---|---|---|
/invoices, /subscriptions |
Newest first | ids below the cursor |
The credit ledger on /contracts/{contractId}/credits |
Newest first | ids below the cursor |
/contracts |
Ascending contract id | ids above the cursor |
Contracts walk forward because the id is a stable identity to iterate, not a
recency ranking. What used to differ as well was the parameter NAME —
beforeId on some lists, afterId on others — so anyone who wrote a working
loop for invoices wrote a broken one for contracts. cursor and nextCursor
are the same on all of them; only the documented order changes.
The credit ledger pages the entries array only: the balances in the same
response are always complete. Seller-wide credit balances are one row per
currency and credit type, so that list is genuinely bounded and does not page.
The following bounded registry/operational listings are deliberately unpaged; their endpoint descriptions state their ordering explicitly:
| List | Order | Why it is unpaged |
|---|---|---|
/usage/metrics |
Metric name ascending | One row per current metric name; bounded by the seller's registry |
/usage/dead-letters |
Oldest first (receivedAt, then id) |
Bounded operational queue response |
/usage/webhook-endpoints |
Endpoint id descending (newest first) | Bounded by the seller's registered endpoints |
The original parameter names
beforeId / nextBeforeId and afterId / nextAfterId still work,
unchanged, on the lists that had them, and every response still carries the
original field beside nextCursor with the same value. Existing integrations
need no change. Sending both cursor and the original name with different
values is a 400 rather than a silent choice between them.
Dates
issuedFrom and issuedTo accept a calendar date (2026-08-01) or a full
RFC 3339 timestamp. A bare date is read as midnight in the seller's
timezone (the one on the organization profile, UTC when none is set), the
same calendar the invoices are dated on, and the range is half-open —
issuedFrom inclusive, issuedTo exclusive — so adjacent months never
double-count a document. Send the timestamp form to filter on any other
boundary.
Amounts
All monetary amounts are integers in the currency's minor units
(grandTotalMinor: 12050 is €120.50 for a EUR document). Quantities and tax
rates are decimal strings. Never parse amounts as floating point.