Docs

Pagination and errors

Page through list responses, filter them, decode the response envelope, and avoid creating duplicates when you retry

Every list endpoint on the Amdahl Platform API pages the same way, and every successful JSON response is wrapped the same way. Code once against the conventions on this page and you will not have to special-case individual endpoints. The error shapes and codes are on Errors.

The response envelope

Every successful JSON response is wrapped in a data envelope: the body is { "data": { … } }, so the field you want is always one level in (.data.results, not .results). Response samples on these pages show the envelope.

Four kinds of response are not enveloped, because they are not a single JSON document:

  • the file downloads GET /evals/export.csv and GET /evals/export.jsonl (a streamed file body under Content-Disposition);
  • event streams (any stream_url, and any endpoint you call with Accept: text/event-stream);
  • GET /openapi.json, the raw OpenAPI document;
  • errors, which have their own shapes. See Errors.

List endpoint conventions

GET /chats and GET /routines share the same paging parameters:

ParameterTypeDefaultMaxPurpose
limitinteger50200Page size
offsetinteger0n/aZero-indexed offset

And the same envelope shape: a named collection array plus the paging facts (values are echoed back clamped if you overshot):

json
{
  "data": {
    "chats": [ ... ],
    "total": 147,
    "limit": 50,
    "offset": 0
  }
}
  • The collection key matches the resource: chats on /chats, routines on /routines.
  • total: total matching rows across all pages. Authoritative; safe for UI pagers.
  • There is no has_more field. Derive it client-side: offset + rows.length < total.

GET /agents takes no paging parameters. It returns the merged roster (Amdahl library agents plus your workspace's agents) in one response, bounded small by construction.

Paging example

bash
# First page
curl -s "$AMDAHL_BASE/chats?limit=50&offset=0" \
  -H "X-API-Key: $AMDAHL_KEY"

# Next page
curl -s "$AMDAHL_BASE/chats?limit=50&offset=50" \
  -H "X-API-Key: $AMDAHL_KEY"

A client-side pager can walk offset by limit while offset + rows.length < total.

Filtering and sorting

Filters are per-endpoint, not a generic vocabulary:

EndpointFilters
GET /chatsstatus (active or archived), agent_ref (an agent's slug or uuid; both forms match), routine_id, subscription_id
GET /routinesenabled (e.g. ?enabled=true)

Ordering is fixed per endpoint (Chats list newest activity first, Routines newest first). There is no order_by parameter on the public surface.

GET /chats?status= is not validated against its two values. A value outside active / archived (for example complete, which is a run status, not a Chat status) does not return an error; it filters on a status no Chat has. A run's complete / error / canceled lives on the run read, not on the Chat list.

Error envelope

The short version, for writing a handler: branch on the HTTP status before you read the body, because error is an object on some failures and a string on others; then branch on error.code, never on message. The three shapes, every code, and which ones are worth retrying are on Errors.

Idempotency

POST endpoints that create resources (POST /chat, POST /routines, POST /agents) are not idempotent at the server level, and there is no Idempotency-Key header. A successful-but-timed-out first attempt plus a retry can create two records (two Chats, two routines). Deduplicate on the client:

  • For Chats: name the Chat deterministically and list with GET /chats before retrying a START; if the named Chat already has a fresh run, poll it instead of starting another.
  • For agents: pass an explicit slug on create. A retry that raced a success returns a typed slug_conflict instead of creating a duplicate, which makes create effectively idempotent per slug.
  • For routines: list GET /routines and match on name before re-creating.

PATCH updates, DELETEs, resume and cancel are safe to retry. A repeat resume against a run that already resumed returns invalid_state, not a double-apply.

Reference