Skip to main content
BeaconLife Sciences

Pagination

List endpoints use cursor pagination, updates use ETag-based optimistic concurrency, and creates accept idempotency keys — the three mechanics every integration needs to get right.

Cursor pagination

List endpoints never return unbounded arrays. Each list response is a page; the request takes a cursor and a page size, and the envelope tells you whether more pages exist:

List request parameters
ParameterMeaning
cursorOpaque continuation token from the previous page (omit it for the first page).
limitPage size, bounded by a server-side maximum.

The response envelope for every list endpoint:

{
  "data": [
    { "id": "STUDY_ID_1", "name": "Study A" },
    { "id": "STUDY_ID_2", "name": "Study B" }
  ],
  "nextCursor": "NEXT_CURSOR",
  "hasMore": true
}

Treat cursors as opaque: never parse them or construct them yourself. To iterate a full collection, keep calling with the latest nextCursor while hasMore is true, then stop. Filters and the cursor are combined in the same request; changing filters mid-iteration starts a new iteration.

ETag / If-Match on detail updates

Detail resources return an ETag response header identifying the current revision. Send it back as If-Match when updating, so concurrent editors cannot silently overwrite each other:

GET /api/v1/studies/STUDY_ID
← ETag: "v3"

PATCH /api/v1/studies/STUDY_ID
If-Match: "v3"
→ succeeds only if the resource is still at revision v3

If the resource changed underneath you, the API returns 409 with the conflict_etag error code — re-read the resource, reapply your change to the new revision, and retry with the new ETag. This is standard optimistic concurrency control; see errors for the response format.

Idempotency keys on POST

Sending the same create request twice — a network retry, a crashed worker retrying — must not create two of something. POST endpoints accept an Idempotency-Key header. If the same key arrives with the same body, the API returns the original result instead of creating a duplicate; if the same key arrives with a different body, you get 409 with idempotency_replayed.

  • Generate a unique key per logical operation (a UUID is fine) and keep it stable across retries of that operation.
  • Keys are scoped to the API client, so two clients can never collide.
  • Treat the idempotency mechanism as insurance, not as a queue — the request still has to succeed once.