Pagination, filtering, and conditional requests
Envelope
Single resource:
{ "data": { "object": "product", "id": "prd_12", "name": "Sales course" } }Collection:
{
"data": [ { "object": "product", "id": "prd_12" } ],
"page": { "limit": 50, "next_cursor": "eyJ2IjoxLCJ...", "prev_cursor": null }
}Every resource includes object and id. A related resource appears as a reference ({ "object": "product", "id": "prd_12" }) or as the related public ID. To get the full related resource, retrieve it with its own operation.
Cursor pagination
GET /api/v3/users?limit=100&cursor=eyJ2IjoxLCJ...limitranges from 1 to 200 and defaults to 50.- To read the next page, send the
next_cursorvalue in thecursorparameter. Anullnext_cursormeans you have reached the end of the collection. There is no total page count and nooffset. - The cursor is opaque and signed, and it is valid for 24 hours. A cursor that is malformed, altered, or expired returns
400 invalid_cursor. - Reuse a cursor only with the same filters and
sortvalue that produced it. Changing them while you page through a collection does not produce consistent results.
Not every collection paginates. Some operations return all matching items in a single response, using the same collection envelope with next_cursor set to null. If you always follow next_cursor until it is null, your code handles both cases.
Filtering and sorting
Each operation in the reference declares the parameters it accepts. Pagination, sorting, and filters are not universal: check the operation before you rely on limit, cursor, sort, or a specific filter.
- Filters are plain query parameters documented per operation, for example
status=published,external_id=erp-1001,created_after=2026-09-01T00:00:00Z, orq=for text search. sort=accepts only the values the operation declares. The-prefix reverses the order (sort=-created_at). An unsupportedlimitorsortvalue returns422 validation_failed.- Dates and times use RFC 3339. Responses always return UTC with
Zand milliseconds. Requests accept any offset. - A parameter the operation does not declare returns
400 unknown_parameter. The API never silently ignores an unknown parameter. - Collections that support the trash accept
deleted=trueto list items in the trash. To restore an item, send aPATCHwithdeleted: false. - Collections return only what the current credentials can see. Access rules are applied before pagination, so every page contains only accessible items.
For the full list of error codes, see Errors.
Conditional reads and writes
A GET for a single resource returns an ETag:
ETag: W/"product:prd_12:2026-09-21T15:53:20.123456Z"Treat the value as opaque. Store it and send it back in If-Match when you write:
PATCH /api/v3/products/prd_12
If-Match: W/"product:prd_12:2026-09-21T15:53:20.123456Z"If the resource changed after you read it, the response is 412 revision_mismatch and nothing is saved. If-Match is optional: without it, the write applies to the current version of the resource, and you lose this protection. Send it on every PATCH and PUT .../order that accepts it, especially on content resources.
Fields
PATCHis partial: an omitted field is left unchanged, andnullclears the field when it accepts null.PUTon a set sub-resource (/order,/tags,/content) replaces the entire set.- Responses include every field in the schema, with explicit
nullvalues. A request body field that is not in the schema returns422 unknown_field. - Monetary amounts are strings, returned with a
currencyfield alongside. Booleans are never0or1. Enum values are stable English strings.