Skip to main content
Every list endpoint under /v1/ — category and raw — uses the same cursor pagination. The pagination fields are part of the response body. There are no pagination headers and no offset parameter; a request with offset returns 400 Bad Request.

Request

integer
default:"1000"
Rows per page. Maximum 100,000 on category endpoints, 10,000 on raw endpoints.
string
The next_cursor value from the previous response, passed unchanged. Omit it for the first page.
Keep the same filter parameters on every page of one run.

Response

array
The rows of this page.
integer
Number of rows in data.
string | null
Opaque cursor for the next page. null on the last page.
integer
Rows matching the query from the cursor position onward. On the first page: all matching rows.
Raw endpoints (/v1/raw/{table_name}) add table_name to the body and send an X-Snapshot-At header with the timestamp of the last successful sync for the table.

Example

Repeat until next_cursor is null. Incremental Sync has a complete Python loop.

Order and stability

Rows are ordered by the table’s sort column (or primary key), NULL values last, with the internal row position as tiebreaker — rows with equal values are neither skipped nor repeated. Tables without a sort column or primary key are paged by row position alone.
A cursor is only valid within one sync run. The tables are reloaded daily (see Sync cycle); after a reload, row positions can shift. Do not store next_cursor between runs — start each run from the first page. An altered cursor or one from an older format returns 400 Bad Request; restart from the first page in that case.