Skip to content
Errors & limits
  1. Docs
  2. API
  3. Errors & limits

Errors & limits

Every failure has the same shape, a machine-readable type and a message written for a person. Branch on the type; show the message.

#The error shape

Response400
{
  "error": {
    "type": "invalid_request",
    "message": "Invalid request body.",
    "details": {
      "properties": {
        "message": {
          "errors": [
            "Required"
          ]
        }
      }
    }
  },
  "request_id": "9b2f0c1e-5d47-4a8e-b3a6-2c1d0e9f8a77"
}
FieldWhat it is
error.typeOne of the types below. Stable — branch on this.
error.messageA sentence for a person. Safe to show; may change wording.
error.detailsPresent when the body or query failed validation: which field, and why.
request_idAlso sent as the X-Request-Id header on every response.

#Error types

typeStatusMeansDo
invalid_request400 · 405 · 422The request doesn't match the schema, or a value was refused (a record field, an agent plan that isn't ready).Fix the field named in details; don't retry unchanged.
authentication401The key is missing, malformed or revoked.Check the Authorization header.
insufficient_credits402The workspace is out of credits.Stop; someone tops up in Settings → Billing.
permission403The key may not do this.Don't retry.
not_found404No such id in this key's workspace.Re-list to find the right one.
conflict409The state changed, or an Idempotency-Key was reused with a different body.Re-read, then retry with a new key.
rate_limited429Too many requests.Wait (Retry-After seconds when present), then retry with the same key.
server_error5xxSomething failed on Attria's side.Retry with backoff and the same Idempotency-Key.

#Failed turns

Refusals before any work starts — a bad body, an unknown id, no credits — are ordinary HTTP errors. Once a turn has been claimed, a failure comes back as the turn itself, with status: "failed" and an error. Handle both: HTTP errors for work that never started, failed for work that did.

In a stream, a failure arrives as an error event with message and request_id, and the stream ends.

#Rate limits

Past the rate limit you'll get 429 with type rate_limited. Wait — at least Retry-After seconds when the header is present — then retry with the same Idempotency-Key.

Long work doesn't need many requests. One stream: true call replaces a polling loop; Jobs & streaming shows both.

#Credits

API calls spend the workspace's credits exactly as the same work in the app does — no separate plan. When they run out, calls that make something return 402 insufficient_credits until the workspace is topped up.

#Request ids

Every response carries an X-Request-Id header, and errors repeat it as request_id. Log it, and quote it when something looks wrong. You may send your own X-Request-Id to tie a call to your logs.

Response headers
HTTP/2 404
content-type: application/json
x-request-id: 9b2f0c1e-5d47-4a8e-b3a6-2c1d0e9f8a77