code tells you exactly
which one, and it is the field your client should branch on.
Error shape
Responses may gain fields over time. Ignore fields you do not recognize.
Error codes
The list of codes only grows: a code is never renamed or removed within
v1.
Treat a code you do not recognize by its HTTP status.
Codes that share a status
Several codes share a status but call for opposite responses — the reason to branch oncode rather than on the status:
402—insufficient_creditsclears when you top up;budget_cappeddoes not.503—upstream_unavailableis worth retrying;capability_unavailablenever is.403—forbiddenis about the key;origin_not_allowedis about where the request came from.
Handling errors
Validation details
Aninvalid_request caused by a schema failure carries field-level detail in
details, so you can point at the offending field instead of diffing your
payload against the reference:
Retrying safely with idempotency keys
Send anIdempotency-Key header on every call that spends credits or creates
something. Use a value that identifies the logical operation in your system — a
UUID you store alongside the work is ideal — and reuse it when you retry.
A call that failed does not hold its key: it delivered nothing and charged
nothing, so retrying it with the same key genuinely retries.
Some operations require the header and answer
400 invalid_request without it —
including POST /v1/projects, POST /v1/autopilot-runs, POST /v1/assets/import
and POST /v1/webhook-subscriptions. The API reference
marks the header as required on each of them.
Retry unchanged only on
rate_limited and upstream_unavailable, and on
network failures where you still hold the idempotency key. A failure to verify
your credential against a store we could not reach is reported as
upstream_unavailable with Retry-After, never as unauthorized — the fault
is ours and it clears.Request IDs
Every response carries anx-request-id header. Log it, and include it when you
contact support about a specific call.