error.code to decide what to do: it is stable, while error.message is written for people and can change. error.retryable (also sent as the x-should-retry header) says whether sending the same request again can succeed. error.request_id identifies the call; include it when you contact us.
The error object
On OpenAI-compatible endpoints (/v1/chat/completions, /v1/completions, /v1/embeddings and the rest):
Some errors add fields next to
error: need_usd, have_usd, topup_url and topup on a 402, did_you_mean and suggested_models on an unknown model. On route_refused, suggested_models is inside error.
On /v1/messages
/v1/messages answers in Anthropic’s error envelope, so Anthropic SDKs and Claude Code handle Kyma errors unchanged. error.type is an Anthropic error type, the Kyma code sits next to it, and request_id is also at the top level:
upstream_error type becomes overloaded_error on a 503 and api_error on a 502.
Media jobs and kyma-gen
A failed image or audio job still answersGET /v1/jobs/{id} with HTTP 200; the job carries status: "failed" and error: { code, message }. Job codes describe what happened to the job: content_policy, content_policy_likeness, content_policy_nsfw, content_policy_unsafe, moderation_blocked, input_too_large, input_invalid, invalid_input, prompt_too_long, provider_timeout, timeout, provider_rate_limited, provider_unavailable, insufficient_credits. A failed job is refunded.
/v1/genmedia/* (used by the kyma-gen CLI) keeps its own shape: { "error": "<message>", "details": { "error_type": "...", ... } }.
Request IDs
Every response carries anx-request-id header, errors and successes alike, and every error body repeats it as error.request_id. Include it when you email hello@kymaapi.com; it lets us find the exact call.
Should I retry?
- Read
x-should-retryorerror.retryablefirst. The official OpenAI and Anthropic SDKs already honorx-should-retryand retry twice by default. - If it is retryable, wait
Retry-Afterseconds when the header is present, then retry with exponential backoff and jitter. - Statuses that can be retried: 408, 429, 502, 503, 504, and a stream that ended with
stream_interrupted. - Do not retry 400, 401, 402, 403, 404 or 413 unchanged: they fail the same way until you change the request, the key or the balance.
Error types
Error codes
Codes are stable: new ones are added, existing ones are never renamed or given a new meaning. Codes marked Not returned yet are reserved; endpoints send the older value listed under Older values until then. Some image, audio, embedding and rerank errors still use older values too.Authentication and access
The request
Models
Billing
Rate limits
Model availability
Kyma
Media jobs
Account and sign-in
Older values
Billing errors (402)
A 402 is always about money or free-tier access, never about your payload. Every 402 haserror.type: "billing_error" and names the rule in error.code:
model_requires_paid: the account has never added credits and this model is outside the free tier (free_tieronGET /v1/modelssays which models a new key can call).requiredis 0, because no top-up amount turns a paid model into a free one: add credits once, then the model is available.insufficient_credits: the balance does not cover this request.need_usdis the most the request can cost as sent (prompt plusmax_tokens) andhave_usdis your balance. Add at least the difference, or lowermax_tokens.
topup_url is the billing page for a person, and topup is the endpoint an agent with a wallet can pay without a person. Only POST /v1/topup itself answers with a payment challenge.
Rate limit errors (429)
rate_limit_exceeded means too many requests, or tokens, in the current minute for your tier. On /v1/chat/completions and /v1/messages the response carries Retry-After and the x-ratelimit-limit-requests, x-ratelimit-remaining-requests and x-ratelimit-reset-requests headers. Limits per tier are on Limits and tiers.
Errors while streaming
Once a stream has started, the HTTP status is already 200. If the model fails mid-answer:- On
/v1/chat/completionsthe last chunk hasfinish_reason: "error"and anerrorobject withcode: "stream_interrupted", followed bydata: [DONE]. - On
/v1/messagesthe stream ends withevent: errorand{"type":"error","error":{"type":"overloaded_error","code":"stream_interrupted",...}}, which Anthropic SDKs raise as an error.
Responses that succeeded but need attention
x-kyma-max-tokens-clamped: your balance covered fewer output tokens thanmax_tokensasked for, so the request ran with this lower limit.x-kyma-served-modeldiffers from the model you asked for: another model answered.finish_reason: "length"with empty content on a reasoning model: reasoning used the wholemax_tokens. Raise it.