Pagination & caching
Cursors
List endpoints use cursor-based pagination. The cursor is opaque — the server may change its encoding at any time. Treat it as a round-trip token.
?limit=<n>— page size. Default 50, maximum 200.?cursor=<opaque>— start position. Omit on the first call.
Response envelope
{
"data": [ /* ...entities... */ ],
"pageInfo": {
"nextCursor": "eyJrIjoiMjAyNi0wNS0wMVQxMDowMDowMC4wMDBaIiwiaSI6IjY1ZjBhZSJ9",
"hasMore": true
}
} Stop calling when hasMore is false or nextCursor is null.
Incremental sync
For polling, combine cursors with ?updatedSince=<iso8601>:
GET /v1/participants?updatedSince=2026-05-15T00:00:00Z Only participants updated after that instant are returned. Save the max updatedAt you saw and pass it on the next poll.
Caching with ETag
Every read response carries a weak ETag header and Cache-Control: private, max-age=0, must-revalidate. Cache responses locally; revalidate by sending the ETag back in If-None-Match:
GET /v1/participants/65f0ae12ab34cd5678ef9012
If-None-Match: W/"r42"
# When unchanged:
HTTP/1.1 304 Not Modified
ETag: W/"r42"
# (empty body) For single-entity reads the ETag is the document's revision counter — extremely cheap to compute. For list pages it's a hash of the filter, cursor, page size, and the maximum updatedAt in the returned rows.
Rate limits
Every authenticated response carries three rate-limit headers so you can pace your client without guessing:
X-RateLimit-Limit— your account's max requests per minute.X-RateLimit-Remaining— what's left in the current 60-second window.X-RateLimit-Reset— unix-seconds when the window rolls over.
Default limit is 60 req/min per account, shared across every token issued under that account. Exceeding the limit returns 429 Too Many Requests with a Retry-After header naming the seconds until the next window. Ask your administrator to raise the limit if your integration needs higher throughput.