limit or a cursor and you get a paginated envelope; send neither and the
endpoint returns the same unpaginated body it always has.
Unpaginated list responses are supported but not recommended — they grow
without bound as your workspace does. New integrations should paginate.
Requesting a page
integer
default:"25"
Rows per page, between 1 and 100. Out-of-range values are rejected
with
invalid_pagination rather than silently clamped — a request for 500
rows that quietly returns 100 would leave you believing you had the whole
list.string
Opaque position marker. Pass the
next_cursor from the previous response
verbatim. starting_after is accepted as an alias.The response
boolean
Whether more rows exist after this page. Stop when it is
false.string | null
Position to resume from.
null on the final page.{ "status": "success", … }).
Where they do, the pagination fields are merged in alongside — data still
holds the rows.
Walking a full list
Loop untilhas_more is false. Do not construct cursors yourself; they
encode a sort position, not an offset, and their format is not part of the
public contract.
Why cursors, not page numbers
Lists are ordered newest-first. With?page=2&per_page=25, any record created
between your first and second request shifts everything down by one — so page
2 repeats a row you already saw, and eventually a row is skipped entirely.
That is not a rare race; for a resource ordered by creation time it is the
normal case.
A cursor encodes where you stopped, not how far in you were, so
concurrent writes cannot make you skip or repeat a record. It also stays fast
at depth: there is no growing offset for the database to count past.
Errors
A malformed or foreign cursor, or alimit outside 1–100, returns a 400
with error.code of invalid_pagination and error.param naming the
offending parameter. See Errors.

