Errors and rate limits
/ API docs← API quickstartView as Markdown
Errors come back as an HTTP status with a JSON body in the format of the endpoint you called.
Every message starts with 🧀, so you can tell an OpenCheese message from the model's text, and
every response carries an x-request-id header: quote it when you contact support.
Error shapes
OpenAI endpoints (/v1/chat/completions, /v1/responses, /v1/images/*, /v1/models and
the account endpoints):
{
"error": {
"message": "🧀 Invalid or disabled OpenCheese API key.",
"type": "authentication_error",
"code": "invalid_api_key"
}
}
The Anthropic endpoint (/v1/messages) wraps the same fields in Anthropic's envelope:
{
"type": "error",
"error": {
"message": "🧀 Invalid or disabled OpenCheese API key.",
"type": "authentication_error",
"code": "invalid_api_key"
}
}
Errors worth waiting for add retry_after (seconds) to the body and a Retry-After header.
Errors after a stream has started
Once a streaming answer has begun, the HTTP status is already 200, so a failure arrives in
the stream:
/v1/chat/completions: the message arrives as assistant text, then a final chunk anddata: [DONE]./v1/responses: aresponse.failedevent, withresponse.error.codeandresponse.error.message./v1/messages: anerrorevent with the Anthropic error object.
Chat Completions answers some errors as a reply
On /v1/chat/completions, problems you need to act on arrive as the assistant's reply, in a
200 response streamed as text/event-stream, even when stream is false:
data: {"object":"chat.completion.chunk","model":"opencheese","choices":[{"index":0,"delta":{"role":"assistant","content":"🧀 Invalid or disabled OpenCheese API key."},"finish_reason":"stop"}]}
data: [DONE]
That covers an invalid or disabled key, a blocked account, an invalid session header, a body
that is not a valid request, a request the content policy blocks, and every balance or plan
limit. Chat apps show the message to you that way. In your own code, check the
Content-Type: text/event-stream on a non-streaming request means the reply is such a
message. Every other error on this endpoint is a normal status with a JSON body.
Codes
| Code | Status | What happened | Retry? |
|---|---|---|---|
invalid_api_key |
401 | The key is wrong, revoked or disabled. | No |
account_banned, account_frozen, account_disabled |
403 | The account cannot make requests; the dashboard says why. | No |
invalid_request_error |
400 | The body is not a valid request for this endpoint. | No |
invalid_session_header |
400 | opencheese-session-uuid is not a valid id; see Sessions. |
No |
model_not_found |
404 | No model has this ID. Read /v1/models. |
No |
model_access_denied |
403 | The model is switched off on your Prices page, or the key's model list leaves it out. | No |
model_disabled, model_pricing_disabled |
400 | The model is not offered right now. | No |
unsupported_model |
400 | Wrong endpoint for the model, such as a text model on /v1/images/generations. |
No |
streaming_unsupported |
400 | The model does not stream; send the request without stream. |
No |
unsupported_reasoning_effort |
400 | The model has no such effort level; supported_reasoning_levels lists its levels. |
No |
context_length_exceeded |
400 | The prompt is longer than the model's context window. | No |
request_blocked_by_guard |
403 | The content policy blocked the request. | No |
provider_refusal |
400 | The model declined to answer. | Only with a changed request |
moderation_blocked, moderation_blocked_billed |
400 | The model's content policy declined the prompt or the image. | Only with a changed request |
plan_limit_reached |
429 | The balance, a plan window, a key's spending cap or a monthly limit is used up, or the model is outside your plan. | After it resets or you top up |
rate_limit_exceeded |
429 | Too many requests; see below. | After Retry-After |
requested_effort_unavailable |
429 | The effort level is temporarily unavailable; the error lists the other levels. | After Retry-After, or another level |
provider_unavailable |
429 | The model is temporarily unavailable. | After Retry-After |
provider_overloaded |
5xx | The model is overloaded. | Yes, with backoff, or another model |
request_timeout |
504 | The answer took too long. | Yes |
service_unavailable |
503 | The gateway is briefly busy. | Yes, shortly |
On /v1/chat/completions, the errors that arrive as a reply (see above) come with status 200
instead of the one shown here.
On /v1/messages, plan_limit_reached also sends x-should-retry: false, so the Anthropic
SDKs do not resend it.
An effort the model does not offer
{
"error": {
"message": "🧀 Example Model is not available for Ultra effort. Choose one of these efforts: low, medium, high.",
"type": "invalid_request_error",
"code": "unsupported_reasoning_effort",
"supported_reasoning_levels": ["low", "medium", "high"]
}
}
The levels run from the weakest to the strongest and are the same ones /v1/models lists for
the model. A model without levels answers that it takes no effort setting: leave the field
out. If you don't send an effort at all, the model's default is used and this error never
occurs.
Rate limits
Each account has request limits per minute, hour, day and month. A request over a limit is
answered 429 rate_limit_exceeded with these headers:
| Header | Meaning |
|---|---|
Retry-After |
Seconds until you may try again. |
x-ratelimit-limit |
The limit you reached. |
x-ratelimit-remaining |
0. |
x-ratelimit-reset |
When the window resets, as an ISO 8601 time. |
A very short burst of requests can also answer 429 without these headers: wait a few seconds
before retrying. The account endpoints (/v1/key, /v1/plan, /v1/balance) and
/v1/messages/count_tokens do not count toward the limits.
Retrying
- Retry
429,5xxandrequest_timeout, honouringRetry-Afterwhen it is present, with exponential backoff otherwise. - Do not retry
400,401,403and404unchanged: the same request fails the same way. plan_limit_reachedclears when the window resets, when you top up, or when you switch on Use balance for Credit Models on the dashboard's Overview.
Notices next to an answer
A successful answer can carry opencheese_notifications, a list of notices about your
account, such as a plan window that is about to run out. They do not change the answer.