Skip to main content
Every list endpoint in v2 uses cursor pagination with the same response shape. No exceptions, no offset/skip/page parameters anywhere.

Response shape

  • data - array of rows. Empty array on the last page if it lined up.
  • page.cursor - opaque token. Pass it as ?cursor=... to fetch the next page. null on the final page.
  • page.has_more - false when there is nothing else to fetch. Use this as your loop condition.
  • page.limit - the effective page size we used.

Parameters

Cursors are stable across mutations. New rows that arrive mid-pagination won’t shift your offset and cause skips or duplicates - the cursor encodes the sort key directly.

Sort

Every list sorts by created_at DESC, id DESC. There’s no sort parameter - if you need a different order, fetch and sort client-side.

Fetching a single page

Fetching the next page

Take page.cursor from the previous response and pass it as ?cursor=...:

Looping through all pages

A few things this snippet does right and that you should keep:
  • Loops on has_more, not on data.length.
  • Reads the cursor from the previous response - never builds one.
  • Re-uses the same limit on every page.

Counts

There’s no total_count. Counting an unbounded resource is expensive and most callers don’t need it - has_more answers “are there more?” cheaply. If you need an exact count for a specific resource, let us know and we’ll add a /count endpoint.

Filtering and pagination together

Filters apply before pagination. Pass them on the first request only - every subsequent request only needs cursor (and optionally limit):
You can re-send the filters on every page if you prefer; we ignore them when a cursor is present.

Common pitfalls

  • Don’t build cursors yourself. They’re opaque and the format will change. Always read them from a response.
  • Don’t reuse a cursor across filters. A cursor from ?status=open is meaningless against ?status=done. If you change filters, start over.
  • Don’t loop forever. Always loop on has_more. If you’re polling for new rows, see Webhooks - pull-based polling will hit rate limits before it hits real-time freshness.