Skip to main content

Pagination

All list endpoints in the Invoice AI API use cursor-based pagination. Cursors are more reliable than offset-based pagination (?page=2) for live data — a new invoice created while you are walking a list does not shift rows across page boundaries, so your integration never silently skips a record.

Why Cursors Instead of Offsets

With offset pagination, fetching page 2 re-runs the full query and skips the first N rows. If an invoice is created between your first and second requests, every subsequent invoice shifts down one position. The invoice that was at position N is now at position N+1, and it falls in the gap between pages — your integration never sees it. For a sync job, that is a missing invoice discovered months later during a reconciliation. A cursor names a position in the ordered result set. New invoices appear at the front of the list, where a client walking backwards never was. The page you already fetched stays exactly where it was.

Query Parameters

string
An opaque string returned as next_cursor in the previous response. Omit this parameter (or pass an empty value) to start from the beginning of the list — the most recently created resources first.
integer
default:"25"
Number of items to return per page. Minimum 1, maximum 100. Requests above the maximum are clamped to 100.

Response Fields

Every list response includes these fields at the top level alongside data:
array
required
The page of results. May be an empty array if there are no resources or no resources match your filters. An empty array does not mean an error.
string | null
required
Opaque cursor pointing to the position after the last item in this page. Pass it as the cursor query parameter in your next request to fetch the following page. null means you have reached the last page — there are no more items.

Treating the Cursor as Opaque

Never parse, construct, or store the cursor as anything other than a string. Its internal encoding is an implementation detail that may change without notice. Code that reverse-engineers the cursor format will break silently when the encoding changes.
The cursor is intentionally opaque — treat it as a black-box token. Pass it back as-is in the cursor query parameter; never attempt to construct or modify one. If you hand-craft cursors, your integration will break whenever the cursor format evolves.

Fetching a Single Page

Response
To fetch the next page, pass next_cursor back as cursor:
When next_cursor is null in the response, you have consumed the entire list.

Iterating All Pages

The following JavaScript async generator transparently walks every page and yields individual invoice objects. Use it to build data exports, reconciliation jobs, or initial syncs.
Usage:
Use limit=100 (the maximum) when you intend to iterate all pages. Fewer, larger pages means fewer round-trips and lower total latency for a full sync. Use a smaller limit only when you want to display incremental results to a user as each page arrives.

Combining Pagination with Filters

All list endpoints accept filter parameters alongside cursor and limit. Filters are applied server-side before the cursor position is evaluated — they are stable across pages as long as the filter values stay the same.
Do not change filter parameters between pages of the same list traversal. Changing status or customer mid-walk is equivalent to starting a new query from the beginning — you may see duplicates or miss records.

Invoice list filters

string
Filter by invoice status. Accepted values: draft, open, paid, overdue, void. overdue is a derived status — invoices are not stored as overdue, but the API identifies open invoices past their due date and returns them when you filter by overdue.
string
Filter by customer. Accepts a cus_… prefixed ID or a raw UUID.
string (ISO 8601 date)
Return only invoices created on or after this date. Example: 2024-01-01.
string (ISO 8601 date)
Return only invoices created on or before this date. Example: 2024-12-31.

Ordering

All list endpoints return results in reverse chronological order — the most recently created resource is always first. There is no sort parameter; the ordering is fixed to ensure cursors remain stable and unambiguous.