The envelope
Every failure, whatever the status, is one JSON object:codeis stable and machine-readable. Branch on it, not onmessage.messageis a human-readable explanation and may change.request_idis the UUID of the request. It is also returned as theX-Request-IDheader on every response, success or failure. Quote it when reporting a problem.
error event with the same three fields; see Streaming.
Codes
What to retry
Retry after Retry-After, same Idempotency-Key
Retry after Retry-After, same Idempotency-Key
idempotency_in_progress, conversation_busy, rate_limit_exceeded, api_rate_limit_unavailable, service_unavailable. Reusing the key guarantees you never pay twice for the same message.Fix the request first
Fix the request first
validation_error (read message; it names the offending field), idempotency_conflict (use a new key for the new body), permission_denied (use a full key), agent_mismatch (use the agent the key belongs to).Do not retry automatically
Do not retry automatically
invalid_api_key (the key was deleted or the secret is wrong), agent_disabled, agent_not_found, insufficient_balance (top up the balance first). A retry loop on these only burns the rate limit.Report with the request id
Report with the request id
internal_error. Retrying once with the same Idempotency-Key is safe; if it persists, send us the request_id.A note on 401
The API does not distinguish a deleted key from one that never existed: both areinvalid_api_key. If a key that used to work starts returning 401, check the API access card in the app; it was probably rotated or deleted.