Skip to main content
← API reference

Errors

Branch on the error code, never on the message. The table is generated from the OpenAPI document.

Errors

StatusCodeMeaning
400invalid_requestSchema error. details.path points at the offending field.
401unauthorizedMissing or unknown API key.
402quota_exceededRetry-AfterMonthly quota reached. Retry-After gives the seconds until the month rolls over.
403key_revokedThe key exists but may not be used: it has been revoked, or the account Engine API subscription is no longer active. The message says which.
404not_foundNo such route — also what you get for the right path with the wrong method.
409idempotency_conflictRetry-AfterOnly with an Idempotency-Key header: the key was already used for a different request (idempotency_conflict — use a new key), or the first request with it is still running (idempotency_in_progress — retry after Retry-After to receive its answer). Never charged.
409idempotency_in_progressRetry-AfterOnly with an Idempotency-Key header: the key was already used for a different request (idempotency_conflict — use a new key), or the first request with it is still running (idempotency_in_progress — retry after Retry-After to receive its answer). Never charged.
413too_largeInput above a limit (see Limits).
429busyRetry-AfterMomentarily at capacity, or — on any key-authenticated path — your address sent too many unknown API keys within a minute. Retry-After in seconds; this never counts against your quota.
500internalUnexpected error, or the auth backend is unreachable (requests fail closed).
503service_unavailableAn engine you asked for cannot be served right now — the nesting engine, or the async max engine. Two causes for max, and the message says which: the tier is not built into this deployment, or it is built in but the worker that solves the jobs is not responding. Fail-closed before a call is reserved, so it never costs you anything.
504solve_timeoutThe solve exceeded its hard time bound. On the rectangular paths the proxy enforces it; on /v1/optimize/nest the engine enforces its own, shorter budget and answers solve_timeout in the normal envelope. A call the proxy gave up on is not charged.

Error body

Every error the engine itself produces uses the same envelope. Branch on error, which is a stable code; never on message, whose wording can change between releases. details is present on invalid_request, where path names the offending field, and on too_large, where max and got give the cap and what you sent.

The exception is a request body over the size cap: it carries maxBytes instead. An unknown engine adds available, the engine ids this deployment accepts.

HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8

{
  "error": "invalid_request",
  "message": "parts[0].h: must be greater than 0",
  "details": { "path": "parts[0].h" }
}
HTTP/1.1 402 Payment Required
Retry-After: 41400
Content-Type: application/json; charset=utf-8

{ "error": "quota_exceeded", "message": "monthly quota exhausted" }
  • 402 and 429 both carry a Retry-After header in seconds. On 402 it counts down to the quota reset at 00:00 UTC on the 1st of next month; on 429 it is a short back-off, and a 429 never consumes quota — the reserved call is handed back.
  • The public demo key's refusals use the same envelope: outside its scope (nesting, the max engine, usage, jobs, import, a job above its size caps) a 403 key_revoked with details.reason "demo_scope"; at its rate limit a 429 busy with details.reason "demo_rate_limit" and details.limit. Both carry details.testKeyUrl, where a free test key is created, and every demo answer has the header X-CutOptim-Demo: true.
  • A routing failure answers with not_found, a code deliberately outside the list above because the router produces it rather than the API contract. You get 404 and not 405 when the path is right but the method is wrong: all four optimize endpoints are POST-only.
  • On the rectangular paths 504 comes from the reverse proxy, not from the engine, so its body belongs to the proxy and is not this JSON envelope; a single job within the input limits below solves well inside it, but several of the heaviest jobs arriving together can queue past it — and a call the proxy gave up on is not charged. /v1/optimize/nest is the exception: that solve is a subprocess with its own budget, deliberately kept below the proxy bound, so a timeout there does use this envelope, with the code solve_timeout.

Is an engine down? The status page shows the live state of the website, the Engine API, the nesting engine and the async max engine: Service status ↗