ZapAPI Docs
Get StartedConceptsAI GatewayGuidesPayment GatewaySDKAPI ReferenceResources
Concepts

Pagination

Cursor-based pagination for every ZapAPI list endpoint — how to page through large result sets reliably.

Every list endpoint in the ZapAPI API uses cursor-based pagination. Cursor pagination is stable under concurrent writes — you will never see the same record twice or skip a record because another one was inserted while you were paging.

The shape of a list response

{
  "status": "success",
  "statusCode": 200,
  "data": {
    "invoices": [ … ],
    "total": 137,
    "limit": 50,
    "nextCursor": "aWQ6MTIzNDU2Nzg5MA==",
    "hasMore": true
  }
}
  • data.<resource> — the page of results (array).
  • data.total — the total number of matching records (when cheap to compute).
  • data.nextCursor — opaque cursor for the next page, or null when there is no next page.
  • data.hasMore — convenience boolean.

Paging with cursors

Pass nextCursor back as the cursor query parameter:

curl "https://api.zapapi.com/api/v1/invoices?limit=50&cursor=aWQ6MTIzNDU2Nzg5MA==" \
  -H "Authorization: Bearer zap_live_…"

Continue until hasMore is false (or nextCursor is null).

Paginate through every invoice
let cursor: string | undefined;
do {
  const page = await zap.invoices.list({ limit: 100, cursor });
  for (const invoice of page.invoices) {
    // process invoice
  }
  cursor = page.nextCursor ?? undefined;
} while (cursor);

Page size

  • limit defaults to 50 and is capped at 100 on most endpoints.
  • Larger pages reduce round-trips but increase response size and latency — 50–100 is the sweet spot for most workloads.

Filters and sorting

Cursors are opaque — they encode the filters and sort order of the original query. You cannot meaningfully modify a cursor, and you should not cache a cursor across filter changes. To change filters, start a new pagination sequence without a cursor.

Common filters available on most list endpoints:

  • status — filter by lifecycle state (pending, paid, expired, …).
  • from / to — ISO-8601 date range on createdAt.
  • projectId — scope to a project (implicit when using a project-scoped key).
  • q — free-text search where supported (customers, payment links).

Why cursor, not offset

Offset pagination (?page=3&limit=50) is simple but breaks under concurrent writes: a row inserted on page 1 shifts every subsequent page, causing duplicates and missed rows. Cursor pagination is stable because the cursor pins the query to a specific row — inserts and deletes before the cursor do not affect the pages after it.

On this page