Skip to main content

Errors

The API uses standard HTTP status codes and OpenAI-compatible JSON error responses. Use the HTTP status for broad handling and error.code when you need to distinguish errors that share a status, such as the two 429 responses.

Error envelope​

Celeris API errors use this shape:

{
"error": {
"message": "Invalid or missing API key.",
"type": "authentication_error",
"code": "invalid_api_key"
}
}
  • message: a human-readable description.
  • type: a broad error class, such as authentication_error or rate_limit_exceeded.
  • code: a stable, machine-readable code. Use it to distinguish errors that share an HTTP status. See 429.

Some 5xx responses may not include a JSON body. Retry all 5xx responses by status rather than requiring an error.code value.

If you send an X-Client-Trace-Id header, Celeris echoes it in API responses so you can correlate failures with application logs and support cases.

StatuscodeRetry?
400max_output_tokens_exceeded or another validation codeAfter fixing the request
401invalid_api_keyAfter fixing credentials
402insufficient_quotaAfter adding credit
404not_foundAfter fixing the URL
408request_timeoutYes
413payload_too_largeAfter reducing the request body
422NoneAfter fixing the request
429rate_limit_exceeded / service_busyYes; honor Retry-After
502upstream_errorYes, with backoff
503service_unavailableYes, with backoff

400 Bad Request​

The request is invalid. The response body describes the validation error.

Common causes:

  • Malformed JSON, or a messages array that doesn't match the chat format. The System One endpoint returns a 422 for malformed JSON.
  • An explicit max_tokens, max_completion_tokens, or max_output_tokens above the model's output limit returns max_output_tokens_exceeded. Reduce that value before retrying, or contact support if you need a higher limit.
  • max_tokens is zero or negative, or prompt tokens plus max_tokens exceed 131,072. Requests are not silently truncated; see Models.
  • On /v1/responses, an image part missing its required detail, or one written with the chat spellings (text, image_url) instead of input_text / input_image. The 400 body carries a schema error for every input shape the request was checked against, rather than naming the missing detail; see Image input.
  • A JSON-mode request with an invalid json_schema, or whose output could not be produced as conforming JSON. Streaming a response_format or a forced tool_choice request also returns 400.
  • On celeris-1-decision, request_rejected means the input exceeds the model's context window or an image cannot be read. Shorten the state or questions, or check the image data before resending.

What to do: correct the request before retrying.

Decisions validation​

On POST /v1/decisions, malformed JSON, invalid fields, a model name other than celeris-1-decision, or exceeded request limits return 400 with code invalid_request and type invalid_request_error.

message describes the problem. param names the top-level field at fault, or is null when the problem applies to the whole body. For example, a choice question with fewer than two choices returns:

{
"error": {
"message": "questions[0].choices: must hold at least two choices",
"type": "invalid_request_error",
"param": "questions",
"code": "invalid_request",
"ref": "q-d3"
}
}

Correct the request before retrying. For a limit on the number of questions, split them across requests. For a limit on JSON values, send fewer questions, choices, or levels per request.

401 Unauthorized​

Code: invalid_api_key (type authentication_error). The Authorization header is missing, malformed, or carries a key that is unknown or revoked.

{"error": {"message": "Invalid or missing API key.", "type": "authentication_error", "code": "invalid_api_key"}}

Common causes:

  • No Authorization: Bearer ck_... header, or a typo in it.
  • A revoked or rotated key still deployed somewhere.
  • A recently created key that is still within the documented activation window.

What to do: check the header and the key's status in the Console. Don't retry unchanged requests. If the key was just created or rotated, wait up to one minute before trying again.

402 Payment Required​

Code: insufficient_quota (type insufficient_quota). Your workspace has no prepaid credit remaining.

{"error": {"message": "Your prepaid credit balance is exhausted. Add credit to continue.", "type": "insufficient_quota", "code": "insufficient_quota"}}

What to do: top up credits under Settings → Billing, then retry. Do not retry until credit is available. Because the balance is shared by all keys in the workspace, production systems should alert on this response.

404 Not Found​

Code: not_found (type invalid_request_error). The URL does not identify an available model, usually because of a typo in the model segment of the base URL.

{"error": {"message": "No model is served at this path. Check the URL path segment.", "type": "invalid_request_error", "code": "not_found"}}

What to do: compare the URL and request-body model field with the values in Models.

408 Request Timeout​

Code: request_timeout (type invalid_request_error). The request body was still arriving when the request's deadline passed.

{"error": {"message": "The request body did not arrive in time. Send the request again.", "type": "invalid_request_error", "code": "request_timeout"}}

What to do: send the request again. If it recurs, check the client's upload bandwidth and reduce the body size.

413 Payload Too Large​

Code: payload_too_large (type invalid_request_error). The request body exceeds the endpoint's 64 MiB (67,108,864-byte) maximum size, or 8 MiB for celeris-1-decision.

{"error": {"message": "The request body exceeds the maximum allowed size for this model.", "type": "invalid_request_error", "code": "payload_too_large"}}

What to do: reduce the request body before retrying. A prompt that fits the byte limit but exceeds the input headroom left by max_tokens returns a 400.

422 Unprocessable Entity​

Returned by POST /v1/systemone, for a request body that is not a valid decision request or exceeds a request limit. The body does not use the error envelope. It is a detail array with one entry, where loc is the path to the field at fault, msg says what is wrong with it, and type is value_error, or json_invalid for malformed JSON:

{"detail": [{"loc": ["body", "questions", "team", "criteria"], "msg": "field required", "type": "value_error"}]}

What to do: correct the field named by loc before retrying. If msg says the answers do not fit in one response, shorten the question names. If msg names a limit on questions or reads, split the questions across requests. For a limit on JSON values, reduce the data in the request body.

429 Too Many Requests​

Two codes share this status. Both are retriable and include a Retry-After header in seconds:

  • rate_limit_exceeded: the workspace exceeded its request-rate limit for the requested model.
  • service_busy: the service is temporarily unable to accept more work.
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 1

{"error": {"message": "You have exceeded your workspace's request rate. Slow down and retry, or contact support for a higher sustained limit.", "type": "rate_limit_exceeded", "code": "rate_limit_exceeded"}}
{"error": {"message": "The service is busy. Please retry in a moment.", "type": "rate_limit_exceeded", "code": "service_busy"}}

Requests that return 429 are not charged.

What to do: wait at least as long as Retry-After, then retry with exponential backoff and jitter. If rate_limit_exceeded persists, reduce concurrency or contact support about a higher sustained rate. Report persistent service_busy responses to support.

502 Bad Gateway​

Code: upstream_error (type api_error). The model service is temporarily unavailable.

{"error": {"message": "The model service is temporarily unavailable. Please retry with backoff.", "type": "api_error", "code": "upstream_error"}}

A decision request that returns 502 carries no usage and is not charged.

What to do: retry with backoff.

503 Service Unavailable​

Code: service_unavailable (type api_error). The service is temporarily unavailable.

{"error": {"message": "The service is temporarily unavailable. Please retry shortly.", "type": "api_error", "code": "service_unavailable"}}

What to do: retry with backoff. If the error persists, check the Console or contact support. Retry any 5xx by status; do not require a JSON body or a specific error code.

Retries and timeouts​

  • Retry 408, 429, 502, and 503, with exponential backoff and jitter, honoring Retry-After when present.
  • Don't retry 400, 401, 402, 404, or 422 without changing something first.
  • Set client timeouts. Choose a timeout that matches your workload and latency objective. Treat timeouts as transient and retry with backoff.

A note for OpenAI SDK users​

OpenAI SDKs expose Celeris errors as HTTP exceptions. Branch on the HTTP status, or inspect error.code when you need to distinguish the two 429 responses:

from openai import APIStatusError

try:
response = client.chat.completions.create(...)
except APIStatusError as err:
if err.status_code == 429:
... # back off and retry
elif err.status_code == 401:
... # fix credentials; do not retry
else:
raise