Skip to navigation

Status codes

What each status means, and whether a retry can help.

Statuses here are never collapsed. An authentication failure is 401, a permission failure 403, an exhausted balance 402, a limit 429 and a dependency 503 — none of them is reported as a generic 400, because the action each one needs is different and a single status would hide it.

StatusRetry?MeansDo
400 Bad Requestnothe request is wrong and will stay wrongfix the request; a retry repeats the same mistake at the same cost
401 Unauthorizednowe could not authenticate the key presentedcheck the header and the value; a missing, unknown, revoked or expired key, or a disabled account, all answer this; do not retry
402 Payment Requirednothe account is out of creditsalert an operator; this clears when someone tops up, not on a retry
403 Forbiddennothe key is real and is not allowed to do thisadd the scope to the key, or call from an address its allowlist names
404 Not Foundnono such job or asset for this account — including one that expiredtreat as terminal; it also answers a job belonging to another account
409 Conflictone code onlyan idempotency key conflicts with an earlier requestretry IDEMPOTENCY_IN_PROGRESS after Retry-After; never retry the reuse
410 Gonenoan input asset this request names has expiredupload the image again and submit with the new asset id and a new key
413 Content Too Largenothe image exceeds the accepted sizedownscale before sending; full-resolution capture is not needed
415 Unsupported Media Typenothe image is not JPEG, PNG or WebP, or is not the type it declaressend a supported image with a Content-Type that matches its bytes
422 Unprocessable Contentnothe image is a supported type but is too large in pixels or cannot be decodedsend a smaller or re-encoded image; the same bytes fail the same way
429 Too Many Requestsyesa rate, quota or queue limit of yours is fullhonour Retry-After, then back off; sustained 429 wants concurrency control
500 Internal Server Erroryeswe failed in a way we did not classifyretry with backoff, keep the idempotency key, record request_id
503 Service Unavailableyesa dependency of ours is not readyretry with backoff; on a poll this never means the job is gone

Which codes arrive under each status

400 Bad Request — IDEMPOTENCY_KEY_REQUIRED, INVALID_CURSOR, INVALID_IDEMPOTENCY_KEY, INVALID_REQUEST, INVALID_USAGE_RANGE

401 Unauthorized — INVALID_API_KEY

402 Payment Required — INSUFFICIENT_CREDITS

403 Forbidden — API_KEY_IP_NOT_ALLOWED, INSUFFICIENT_SCOPE

404 Not Found — ASSET_CONTENT_UNAVAILABLE, ASSET_NOT_FOUND, JOB_NOT_FOUND

409 Conflict — ASSET_OWNED_BY_JOB, IDEMPOTENCY_IN_PROGRESS, IDEMPOTENCY_KEY_REUSED, JOB_IN_PROGRESS, JOB_NOT_CANCELLABLE

410 Gone — ASSET_EXPIRED, JOB_DELETED

413 Content Too Large — PAYLOAD_TOO_LARGE

415 Unsupported Media Type — UNSUPPORTED_MEDIA_TYPE

422 Unprocessable Content — UNPROCESSABLE_IMAGE

429 Too Many Requests — QUOTA_EXCEEDED, RATE_LIMITED, TENANT_QUEUE_LIMIT_EXCEEDED

500 Internal Server Error — INTERNAL_ERROR

503 Service Unavailable — MAINTENANCE_MODE, QUEUE_CAPACITY_EXCEEDED, SERVICE_UNAVAILABLE

Statuses that are not errors

StatusWhen
200a poll, a result fetch, a usage report — and a failed job
202a submission accepted; the body is the job, id included, and Location names it
304your If-None-Match matched; the job has not changed

The 200 row is the one that costs people a day. A failed analysis is a successful request — the HTTP layer did its job and the work did not. Asynchronous jobs, Error reference.

What a status never tells you

It does not tell you whether you were charged: an accepted submission that fails during analysis is a 202 followed by a 200, and Credits and usage is where that is written down. It also does not tell you whether the job survived — a 503 on a poll is about the poll, never about the job.