Reference

API Error Codes — Claude, KIMI, OpenAI-compatible & Gemini

Every API error explained: Anthropic 401 invalid x-api-key, 402 billing_error, 429 rate_limit_error and 529 Overloaded; KIMI kimi/* 400 documented_limitation (mcp_servers, provider tools) and count_tokens unsupported_parameter; OpenAI 401 invalid_api_key, 402 insufficient_quota; Gemini 400 API_KEY_INVALID and 402 FAILED_PRECONDITION. Exact response text, cause and fix for each.

Every protocol keeps its official envelope. Anthropic lanes return Anthropic JSON so you can branch on error.type. Gateway limitations add error.details.error_code (documented_limitation or unsupported_parameter) and error.details.param — official SDKs ignore unknown fields:

{"type":"error","error":{"type":"authentication_error","message":"invalid x-api-key"}}

Match on the HTTP status and the branch field (Anthropic error.type, OpenAI error.code, Gemini error.status / ErrorInfo reason), never on the message string — messages are prose and can be reworded, while those fields are the contract. In the official SDKs this means catching the typed exception classes rather than inspecting text. This page is written the other way round only because the message is what you have in front of you when something breaks. HTTP 402 is prepaid balance on every lane; do not retry it as a 429.

Official Anthropic uses one error.type for every client-fault 400: invalid_request_error. Different 400s are different messages, plus error.details.error_code for gateway limitations. Rows are grouped by HTTP status, then type.

Anthropic lane — all codes

Open a row for the exact response body and the fix. You do not need to scroll past the other errors.

400invalid_request_errorassistant message prefill not supportedNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"This model does not support assistant message prefill. The conversation must end with a user message."}}

Why it happens

  • The conversation ends on an assistant message used to force the opening of the reply. That is rejected on Claude Opus 4.6 and later, Sonnet 4.6 and later, and Fable 5.
  • Assistant messages elsewhere in the history — few-shot examples, for instance — are still fine. Only a trailing one is rejected.
  • Many frameworks prefill internally, so the code may never do it explicitly.

How to fix it

  • To force a JSON shape, use structured outputs via output_config.format instead of prefilling an opening brace.
  • To force a label, define a tool with an enum field listing the valid labels.
  • To suppress a preamble, instruct it in the system prompt: respond directly, with no opening phrases.
  • To continue an interrupted response, move the continuation into the user turn and quote where it stopped.

Other forms of the same failure

  • This model does not support assistant message prefill
  • claude prefill trailing whitespace error

Short link: https://apitoken.sale/e/prefill-not-supported · Identical on api.anthropic.com and on this gateway.

400invalid_request_errorcould not parse request bodyNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"Could not parse request body."}}

Why it happens

  • The body is not valid JSON — a trailing comma, a single-quoted string, or a shell variable that expanded into an unescaped quote.
  • A missing or non-JSON Content-Type header.

How to fix it

  • Validate the body before sending. Most of these never reach the API in a working state.
  • In shell scripts, build the body with a heredoc or jq rather than string interpolation.

Other forms of the same failure

  • claude api could not parse request body

Short link: https://apitoken.sale/e/invalid-request-body · This response is specific to this gateway — the Anthropic API has no equivalent.

400invalid_request_errorcredit balance is too lowNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits."}}

Why it happens

  • The Anthropic organization behind the key has no API credits left on api.anthropic.com.
  • The tool is talking to Anthropic's own API, not this gateway. On this gateway the equivalent condition is HTTP 402 billing_error.
  • Auto-reload is off, or the card on file was declined.

How to fix it

  • Check whether the failing tool is talking to api.anthropic.com. This error always concerns Anthropic API credits.
  • Add credits to the organization, or enable auto-reload so long jobs do not stop mid-run.
  • On this gateway the equivalent condition is a 402 with a different message — see the insufficient-balance entry.

Other forms of the same failure

  • claude credit balance is too low but I have credits
  • claude pro credit balance too low
  • your credit balance is too low to access the anthropic api

Short link: https://apitoken.sale/e/credit-balance-too-low · Identical on api.anthropic.com and on this gateway.

400invalid_request_errorinvalid anthropic-beta headerNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"invalid anthropic-beta header"}}

Why it happens

  • The anthropic-beta header carries a flag this gateway does not accept, or the value is malformed.
  • Several flags joined by something other than a comma.
  • A flag copied from documentation for a feature that has since gone GA and no longer takes a header.

How to fix it

  • Send multiple flags as one comma-separated value.
  • Drop flags for features that are now GA — effort, fine-grained tool streaming and the 128K output header among them.
  • If the SDK sets the header for you, do not also set it by hand.

Other forms of the same failure

  • anthropic-beta header error

Short link: https://apitoken.sale/e/invalid-beta-header · This response is specific to this gateway — the Anthropic API has no equivalent.

400invalid_request_errormax_tokens above the model's output ceilingNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"max_tokens: 128001 > 128000, which is the maximum allowed number of output tokens for claude-opus-4-6"}}

Why it happens

  • max_tokens exceeds the output ceiling for that specific model. The ceiling is per model and is not the same as the context window.
  • A configuration written for one model reused with another that has a lower ceiling.

How to fix it

  • Look up the ceiling for the model you are calling rather than assuming a shared value.
  • Above roughly 16K output tokens, stream the response — a large non-streaming request can exceed the SDK's HTTP timeout even when max_tokens is legal.

Other forms of the same failure

  • which is the maximum allowed number of output tokens
  • claude max_tokens too large

Short link: https://apitoken.sale/e/max-tokens-too-large · Identical on api.anthropic.com and on this gateway.

400invalid_request_errormax_tokens must exceed thinking.budget_tokensNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"`max_tokens` must be greater than `thinking.budget_tokens`"}}

Why it happens

  • On models that still accept a fixed thinking budget, that budget must be strictly smaller than max_tokens, since thinking and the reply share the same output allowance.
  • On Claude Opus 4.7 and later and on Sonnet 5 the fixed budget was removed altogether, which surfaces as a different 400 telling you to use adaptive thinking and the effort setting instead.

How to fix it

  • Raise max_tokens above the budget, or lower the budget.
  • On current models, switch to adaptive thinking and control depth with output_config.effort (low, medium, high, xhigh, max). Effort goes inside output_config, not at the top level.
  • With thinking enabled, max_tokens caps thinking plus reply together — a budget sized for the answer alone can truncate mid-response.

Current form

thinking={"type": "adaptive"},
output_config={"effort": "high"}

Other forms of the same failure

  • max_tokens must be greater than thinking.budget_tokens
  • "thinking.type.enabled" is not supported for this model
  • "thinking.type.disabled" is not supported for this model
  • budget_tokens removed claude

Short link: https://apitoken.sale/e/thinking-budget-tokens · Identical on api.anthropic.com and on this gateway.

400invalid_request_errorprompt is too longNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"prompt is too long: 212164 tokens > 199999 maximum"}}

Why it happens

  • The request exceeds the model's context window. The two numbers are your prompt size and the ceiling for that model.
  • An agent loop that appends every tool result to the history without ever pruning it.
  • Large files or documents pasted inline rather than referenced.

How to fix it

  • Count before sending: the count_tokens endpoint gives an exact, model-specific number. Do not estimate with a tokenizer built for another vendor — it undercounts Claude noticeably.
  • Prune old tool results from the history, or enable server-side compaction so earlier turns are summarized instead of resent verbatim.
  • Upload large documents once via the Files API and reference them by file_id.

Other forms of the same failure

  • claude prompt is too long tokens > maximum
  • claude 200k context limit error

Short link: https://apitoken.sale/e/prompt-too-long · Identical on api.anthropic.com and on this gateway.

400invalid_request_errorprompt is too long for this modelNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"prompt is too long: exceeds the 200000 token maximum for claude-sonnet-4-6"}}

Why it happens

  • claude-sonnet-4-6 serves 200 000 input tokens on this endpoint. Measured 2026-08-29: 202 098 tokens are answered, 206 146 are refused.
  • Anthropic itself refuses the same request with a rate-limit shape naming usage credits, which reads like a temporary limit. It is not temporary, and no retry clears it, so the endpoint restates it as the over-window error every other Claude model returns for the same condition.
  • Other Claude models on the same key take far more: claude-sonnet-5 and the Opus family answer documents of 256 000-345 000 tokens.

How to fix it

  • Send the document to claude-sonnet-5 or claude-opus-4-6 — same key, same endpoint, only the model id changes.
  • Expect a larger token count on the newer generation: the same text measures about 35% more tokens on Sonnet 5 and the 4.7/4.8 models than on Sonnet 4.6, because the tokenizer changed.
  • Count before sending with the count_tokens endpoint against the model you will actually use.
  • Prune tool history or reference large documents instead of pasting them inline.

Other forms of the same failure

  • usage credits are required for long context requests
  • claude sonnet 4.6 200k context limit
  • claude sonnet 4.6 long context 429

Short link: https://apitoken.sale/e/prompt-too-long-model-ceiling · This response is specific to this gateway — the Anthropic API has no equivalent.

400invalid_request_errortemperature and top_p cannot both be specifiedNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"`temperature` and `top_p` cannot both be specified for this model. Please use only one."}}

Why it happens

  • Both sampling parameters were sent to a Claude 4 model. Frameworks commonly set defaults for both, so the code may never have set them explicitly.
  • On Claude Opus 4.7 and later — including Opus 4.8, Opus 5 and Fable 5 — the parameters were removed entirely, so sending either one returns a 400.
  • On Claude Sonnet 5 a non-default value is rejected while the default is accepted, so the same code can pass on one route and fail on another.

How to fix it

  • On Claude 4.x, send at most one of the two.
  • On Opus 4.7 and later, delete both, plus top_k. There is no replacement parameter — behaviour is steered by prompting and by the effort setting.
  • If temperature=0 was there for determinism, note it never guaranteed identical output on any model.

Before and after

# Before — 400
client.messages.create(model="claude-opus-5", temperature=0.7, top_p=0.9, …)

# After
client.messages.create(model="claude-opus-5", …)

Other forms of the same failure

  • temperature and top_p cannot both be specified
  • claude opus temperature removed
  • bedrock claude temperature and topP error

Short link: https://apitoken.sale/e/temperature-and-top-p · Identical on api.anthropic.com and on this gateway.

400invalid_request_errortool_use without a matching tool_resultNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"`tool_use` ids were found without `tool_result` blocks immediately after: toolu_… Each `tool_use` block must have a corresponding `tool_result` block in the next message."}}

Why it happens

  • The assistant turn requested one or more tools, and the next message did not return a result for every one of them.
  • Only the text was appended to the history instead of the full response content, so the tool_use blocks were silently dropped.
  • Several tools were requested in parallel and the results were split across multiple user messages instead of batched into one.
  • A tool threw, and the code skipped sending a result rather than sending an error result.

How to fix it

  • Append the entire response content to the history, not just the text.
  • Return every tool_result for a turn inside a single user message. Splitting them also trains the model to stop making parallel tool calls.
  • On failure, still return a tool_result with is_error set — never omit it.

Other forms of the same failure

  • tool_use ids were found without tool_result blocks
  • claude code tool_result error

Short link: https://apitoken.sale/e/tool-result-missing · Identical on api.anthropic.com and on this gateway.

400invalid_request_errorStreaming required for long operationsNo
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"Streaming is strongly recommended for operations that may take longer than 10 minutes"}}

Why it happens

  • A non-streaming request was made with a max_tokens large enough that the response could exceed the request timeout.
  • It shows up most in no-code and workflow tools, where the node sets a large max_tokens but does not expose a streaming toggle.

How to fix it

  • Stream the request and collect the final message from the stream helper.
  • If streaming is not available in your tool, lower max_tokens to something the timeout can accommodate — roughly 16K output tokens is a safe non-streaming ceiling.

Stream and take the final message

with client.messages.stream(model="claude-opus-5", max_tokens=64000, …) as stream:
    message = stream.get_final_message()

Other forms of the same failure

  • Streaming is required for operations that may take longer than 10 minutes

Short link: https://apitoken.sale/e/streaming-required · Identical on api.anthropic.com and on this gateway.

401authentication_errorinvalid x-api-keyNo
HTTP 401
{"type":"error","error":{"type":"authentication_error","message":"invalid x-api-key"}}

Why it happens

  • The x-api-key header is missing or empty — often because the environment variable is unset in the shell that actually runs the process.
  • The key is sent in the wrong header. ANTHROPIC_API_KEY becomes x-api-key; ANTHROPIC_AUTH_TOKEN becomes Authorization: Bearer. A valid key in the wrong header still returns this error.
  • Both ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN are set, so both headers go out and the request is rejected. An empty string still counts as set.
  • The key was revoked, or expired if it was issued with an expiry date.
  • The key is fine but the base URL points somewhere that has never seen it.

How to fix it

  • Print the first few characters of the variable inside the same process that fails. Most 401s are an environment or quoting problem rather than a bad key.
  • Pick one variable and unset the other. This is the single most common cause when a custom base URL is involved.
  • Confirm the key is active in your dashboard, and that the base URL matches the key's issuer.

Check what is actually being sent

# Is the variable set in THIS shell?
echo "${ANTHROPIC_API_KEY:0:12}…"
# Is a competing variable also set?
env | grep -E 'ANTHROPIC_(API_KEY|AUTH_TOKEN|BASE_URL)'

curl https://router.apitoken.sale/v1/models \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01"

Other forms of the same failure

  • 401 - {'type': 'error', 'error': {'type': 'authentication_error', 'message': 'invalid x-api-key'}}
  • litellm.AuthenticationError: AnthropicException - invalid x-api-key
  • anthropic.AuthenticationError
  • claude code 401 custom ANTHROPIC_BASE_URL
  • cursor bad user api key unauthorized anthropic

Short link: https://apitoken.sale/e/invalid-api-key · Identical on api.anthropic.com and on this gateway.

402billing_errorinsufficient balance or key spending limit reachedNo
HTTP 402
{"type":"error","error":{"type":"billing_error","message":"insufficient balance or key spending limit reached for this request"}}

Why it happens

  • The prepaid balance does not cover the request just submitted.
  • The key carries its own spending limit and has reached it, even though the account still has balance.
  • error.type is billing_error, matching Anthropic Platform. It is not invalid_request_error and it is not a 429 — SDKs retry 429.

How to fix it

  • Top up the balance, or raise the spending limit on that key.
  • Confirm the live balance after the payment is credited. A pending top-up is not spendable yet.
  • Read the live balance with the same key you use for inference. Branch on HTTP 402 and error.type billing_error, not on the message string.

Check the balance for a key

curl https://api.apitoken.sale/balance \
  -H "x-api-key: $ANTHROPIC_API_KEY"

Other forms of the same failure

  • claude api 402
  • api key spending limit reached
  • {"type":"error","error":{"type":"billing_error","message":"insufficient balance or key spending limit reached for this request"}}

Short link: https://apitoken.sale/e/insufficient-balance · This response is specific to this gateway — the Anthropic API has no equivalent.

403permission_errorpermission deniedNo
HTTP 403
{"type":"error","error":{"type":"permission_error","message":"Your API key does not have permission to use the specified resource."}}

Why it happens

  • The key is valid but not entitled to the model or feature requested.
  • A regional restriction. This variant often arrives with a terser body such as 'Request not allowed' and is about where the request originates, not about the key.
  • On the official Anthropic API a billing problem can also surface as 403, distinguished by the error type rather than the status. On this gateway prepaid money is HTTP 402 with error.type billing_error.

How to fix it

  • Branch on error.type, not on the status alone — billing_error is money; permission_error is entitlement.
  • Try a model you know the key can reach, to establish whether the key itself is healthy.
  • For a regional block, the fix is where the request egresses from, not the key. This gateway accepts requests from regions where the upstream API is not directly reachable.

Other forms of the same failure

  • anthropic 403 Request not allowed
  • claude api 403 forbidden country

Short link: https://apitoken.sale/e/permission-denied · Identical on api.anthropic.com and on this gateway.

404not_found_errormodel or endpoint not foundNo
HTTP 404
{"type":"error","error":{"type":"not_found_error","message":"model: claude-opus-4-5-20251101"}}

Why it happens

  • A model id that does not exist: a typo, a date suffix appended to an alias, or an id retired in a deprecation wave.
  • Model ids use hyphens throughout — claude-sonnet-4-6, never claude-sonnet-4.6.
  • A base URL that already ends in /v1, so the SDK produced /v1/v1/messages.

How to fix it

  • Set the base URL to the origin only and let the SDK append /v1 itself.
  • List the models the key can actually reach instead of guessing an id.
  • Replace retired ids: Claude 3.7 Sonnet and Claude 3.5 Sonnet map to claude-sonnet-5, Claude 3.5 Haiku to claude-haiku-4-5, Claude 3 Opus to claude-opus-5.

List the models this key can use

curl https://router.apitoken.sale/v1/models \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01"

Other forms of the same failure

  • claude api 404 not_found_error model
  • cursor model not found anthropic api key
  • claude-3-5-sonnet 404

Short link: https://apitoken.sale/e/not-found · Identical on api.anthropic.com and on this gateway.

404not_found_errorthis Anthropic surface is not served hereNo
HTTP 404
{"type":"error","error":{"type":"not_found_error","message":"The Message Batches API is not available on this endpoint. This endpoint serves POST /v1/messages, POST /v1/messages/count_tokens, GET /v1/models and GET /v1/models/{model_id}."}}

Why it happens

  • The endpoint serves the Messages API, token counting and model discovery. Message Batches, the Files API, legacy Text Completions, the Admin API, Managed Agents and Skills are not served, and the error names which one you hit.
  • An SDK helper reached for one of those surfaces on its own — for example uploading a document through the Files API before referencing it in a message.

How to fix it

  • Send document and image content inline in the message instead of uploading it first.
  • Replace a legacy /v1/complete call with POST /v1/messages.
  • Read usage and spend from the account dashboard rather than the organization Admin API.

Other forms of the same failure

  • anthropic files api 404
  • message batches not available
  • v1/complete 404 claude

Short link: https://apitoken.sale/e/endpoint-not-available · This response is specific to this gateway — the Anthropic API has no equivalent.

413request_too_largerequest too largeNo
HTTP 413
{"type":"error","error":{"type":"request_too_large","message":"Request exceeds the maximum size"}}

Why it happens

  • The serialized body exceeds the size ceiling. Base64-encoded images and PDFs are the usual reason.
  • Base64 inflates binary data by roughly a third, so a file that looks safe on disk can be over the limit on the wire.
  • Requests can hit an intermediate ceiling below the documented maximum when many files are attached at once.

How to fix it

  • Resize or recompress images before encoding — most vision tasks do not need the original resolution.
  • Upload large documents once via the Files API and reference them by file_id rather than resending bytes each turn.
  • Trim the message history instead of replaying every turn verbatim.

Other forms of the same failure

  • claude api 413 request_too_large
  • claude request exceeds the maximum size
  • Request exceeds the maximum allowed number of bytes.

Short link: https://apitoken.sale/e/request-too-large · Identical on api.anthropic.com and on this gateway.

429rate_limit_errorrate limit exceededYes, back off
HTTP 429
{"type":"error","error":{"type":"rate_limit_error","message":"This request would exceed your organization's rate limit of 80,000 input tokens per minute. Please reduce the prompt length or the maximum tokens requested, or try again later."}}

Why it happens

  • The per-minute token or request ceiling was exceeded. The number in the message is your own limit, so it differs between accounts.
  • A burst with no concurrency ceiling — a parallel map over a large list is the usual culprit.
  • Retries piling on top of the requests that caused the first 429, which enlarges the burst instead of draining it.
  • A single very large prompt can exceed a per-minute token budget on its own, which is why the message suggests shortening the prompt as well as waiting.

How to fix it

  • Honour the Retry-After header rather than guessing an interval.
  • The official SDKs already retry 429 and 5xx with exponential backoff (twice by default) — raise max_retries instead of hand-rolling a loop.
  • Cap concurrency at the call site. A semaphore fixes more 429s than any retry policy.
  • Do not confuse this with HTTP 402 billing_error — that is empty prepaid balance. 429 is retryable throughput. Top up for 402; honour Retry-After for 429.

Let the SDK back off for you

import anthropic

client = anthropic.Anthropic(max_retries=5)  # retries 429 and 5xx with backoff

Other forms of the same failure

  • Number of request tokens has exceeded your per-minute rate limit
  • Number of requests has exceeded your rate limit. Please try again later.
  • anthropic.RateLimitError
  • claude api 429 too many requests

Short link: https://apitoken.sale/e/rate-limit · Identical on api.anthropic.com and on this gateway.

500api_errorinternal server errorYes, back off
HTTP 500
{"type":"error","error":{"type":"api_error","message":"Internal server error"}}

Why it happens

  • An unexpected failure while processing the request. Nothing in your payload caused it.

How to fix it

  • Retry with exponential backoff — the SDKs do this for 5xx automatically.
  • If it persists for one request while others succeed, capture the request id and send it to support.

Other forms of the same failure

  • anthropic api_error internal server error

Short link: https://apitoken.sale/e/api-error · Identical on api.anthropic.com and on this gateway.

529overloaded_errorOverloadedYes, back off
HTTP 529
{"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}}

Why it happens

  • Upstream capacity is temporarily saturated. 529 describes the service, not your request.
  • It clusters during incidents: the same request typically succeeds minutes later with no change.

How to fix it

  • Retry with exponential backoff and jitter. Never in a tight loop — that is what produced the pile-up.
  • Note the status is 529, not 503. Some HTTP clients and proxies only treat a hardcoded set of codes as retryable and omit 529, so the retry you think you have may not fire.
  • For latency-sensitive paths, fall back to a smaller model, which is generally less contended.

Other forms of the same failure

  • API Error: 529 {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}}
  • anthropic api overloaded error repeated 529
  • claude 529 vs 429

Short link: https://apitoken.sale/e/overloaded · Identical on api.anthropic.com and on this gateway.

KIMI lane — all codes

kimi/* uses the same Anthropic JSON envelope, so 401, 402 billing_error, 429 and 529 are the Anthropic rows above. These extra 400s are the KIMI-only limitations — official Kimi API fields this endpoint cannot honour, plus count_tokens which kimi/* does not serve:

Open a row for the exact response body and the fix. You do not need to scroll past the other errors.

400invalid_request_error / documented_limitationdocumented limitation (mcp_servers)No
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"mcp_servers cannot be honoured on this endpoint. The official Kimi API accepts it; omit 'mcp_servers' or declare client-side tools in tools[].","details":{"error_code":"documented_limitation","param":"mcp_servers"}}}

Why it happens

  • The official Kimi API accepts mcp_servers. This endpoint cannot honour that field on kimi/*, so it fails closed before dispatch.
  • error.type stays invalid_request_error so Anthropic SDKs keep parsing. The class is in error.details.error_code.

How to fix it

  • Omit mcp_servers. Declare the same capability as a client-side tool in tools[] and handle tool_use / tool_result yourself.
  • Do not retry the identical body — the refusal is not a rate limit.

Other forms of the same failure

  • documented_limitation mcp_servers
  • cannot be honoured on this endpoint

Short link: https://apitoken.sale/e/documented-limitation-kimi-mcp · Returned on kimi/*. Auth, money, rate limit and overload use the Anthropic rows above.

400invalid_request_error / documented_limitationdocumented limitation (provider tools)No
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"tools cannot be honoured on this endpoint. The official Kimi API accepts it; omit this tool or declare it as a client-side tool.","details":{"error_code":"documented_limitation","param":"tools"}}}

Why it happens

  • The official Kimi API accepts provider-executed search, computer and code_execution tools. This endpoint does not run them on kimi/*.
  • Client-side tools[] with tool_use / tool_result stay accepted. Only a tool the provider would execute is refused.
  • error.type stays invalid_request_error. The class is in error.details.error_code.

How to fix it

  • Omit that tool, or declare it as a client-side tool in tools[] and handle tool_use / tool_result yourself.
  • Do not retry the identical body.

Other forms of the same failure

  • documented_limitation tools
  • omit this tool or declare it as a client-side tool

Short link: https://apitoken.sale/e/documented-limitation-kimi-tools · Returned on kimi/*. Auth, money, rate limit and overload use the Anthropic rows above.

400invalid_request_error / unsupported_parameterunsupported parameter (count_tokens on kimi/*)No
HTTP 400
{"type":"error","error":{"type":"invalid_request_error","message":"Unsupported parameter: '/v1/messages/count_tokens' is not supported with this endpoint. The official Anthropic API accepts it; Use POST /v1/messages; token counting is not available for kimi/* on this endpoint.","details":{"error_code":"unsupported_parameter","param":"/v1/messages/count_tokens"}}}

Why it happens

  • POST /v1/messages/count_tokens exists on the Anthropic lane for Claude models. kimi/* has no count_tokens sibling on this endpoint.
  • error.type stays invalid_request_error. The class is in error.details.error_code.

How to fix it

  • Send the same body to POST /v1/messages. Usage in the response is the billed token count.
  • Do not retry count_tokens against a kimi/* model id.

Other forms of the same failure

  • token counting is not available for kimi/*
  • count_tokens kimi

Short link: https://apitoken.sale/e/unsupported-parameter-kimi-count-tokens · Returned on kimi/*. Auth, money, rate limit and overload use the Anthropic rows above.

OpenAI lanes — all codes

The OpenAI lanes return the OpenAI error envelope instead — branch on error.code and the HTTP status. A field this endpoint cannot honour is 400 with code documented_limitation or unsupported_parameter, a named param, and a workaround in the message. These are the exact responses of router.apitoken.sale/v1:

{"error":{"message":"Incorrect API key provided.","type":"invalid_request_error","param":null,"code":"invalid_api_key"}}

Open a row for the exact response body and the fix. You do not need to scroll past the other errors.

400invalid_request_error / documented_limitationdocumented limitation (hosted tool)No
HTTP 400
{"error":{"message":"tools.0.type cannot be honoured on this endpoint. The official OpenAI API accepts it; omit this 'hosted_shell' tool or use a client-side custom tool.","type":"invalid_request_error","param":"tools.0.type","code":"documented_limitation"}}

Why it happens

  • The official OpenAI API accepts this field or tool type. This endpoint cannot honour it, so the request is refused before dispatch — never a silent 200 that dropped the field.
  • The same class covers hosted_shell, code_interpreter, apply_patch, skills, file_search, computer, mcp, prompt_cache_retention, reasoning.mode, native max_output_tokens on the Codex wire, and store / previous_response_id / item_reference on a non-openai/* model.
  • error.type stays invalid_request_error. Branch on error.code documented_limitation and error.param.

How to fix it

  • Omit the named field, or follow the workaround in the message (client-side custom tool, PNG data URL, openai/* model for stored responses).
  • Do not retry the identical body. Switch to the model's native lane only when that lane actually honours the field.

Other forms of the same failure

  • store cannot be honoured on this endpoint. The official OpenAI API accepts it; omit 'store' or use an openai/* model.
  • prompt_cache_retention cannot be honoured on this endpoint. The official OpenAI API accepts it; omit 'prompt_cache_retention'.
  • reasoning.mode cannot be honoured on this endpoint. The official OpenAI API accepts it; omit 'reasoning.mode'.
  • documented_limitation OpenAI

Short link: https://apitoken.sale/e/openai-documented-limitation · Returned by the OpenAI lanes of the unified endpoint (router.apitoken.sale/v1).

400invalid_request_error / unsupported_parameterunsupported parameterNo
HTTP 400
{"error":{"message":"Unsupported parameter: 'n' is not supported with this endpoint. The official OpenAI API accepts it; omit 'n' or send n=1.","type":"invalid_request_error","param":"n","code":"unsupported_parameter"}}

Why it happens

  • This HTTP path never accepts the named field. Chat n other than 1 on the Anthropic Messages adapter is the usual case.
  • Distinct from documented_limitation: unsupported_parameter is the wrong shape for this endpoint; documented_limitation is a gap versus the official API of the capacity provider.
  • Default or omitted or JSON null is not a refusal. Only a present non-null value that cannot be honoured returns 400.

How to fix it

  • Omit the named parameter, or send the value the message names (n=1).
  • If you need the official behaviour, call the native lane that actually accepts the field.

Other forms of the same failure

  • Unsupported parameter: 'n' is not supported with this endpoint.
  • 400 unsupported_parameter

Short link: https://apitoken.sale/e/openai-unsupported-parameter · Returned by the OpenAI lanes of the unified endpoint (router.apitoken.sale/v1).

401invalid_request_error / invalid_api_keyIncorrect API key providedNo
HTTP 401
{"error":{"message":"Incorrect API key provided.","type":"invalid_request_error","param":null,"code":"invalid_api_key"}}

Why it happens

  • The key was sent in the x-api-key header. The OpenAI lanes authenticate with Authorization: Bearer — x-api-key is only for the Anthropic lane.
  • The Authorization header is missing the Bearer prefix, or the environment variable it was built from is empty in the shell that runs the process.
  • The key was revoked, or expired if it was issued with an expiry date.
  • The key is valid but the base URL points at an Anthropic-lane address (router.apitoken.sale without /v1, or the legacy api.apitoken.sale) instead of router.apitoken.sale/v1.

How to fix it

  • Send the same sk-pool key as Authorization: Bearer sk-pool-… to https://router.apitoken.sale/v1.
  • With the official OpenAI SDK, set api_key (or OPENAI_API_KEY) and base_url — the SDK adds the Bearer header for you.
  • Confirm the key is active in your dashboard and that the host is the OpenAI lane of the unified endpoint.

Reproduce outside your tool

curl https://router.apitoken.sale/v1/models \
  -H "Authorization: Bearer $APITOKEN_API_KEY"

Other forms of the same failure

  • {"error":{"message":"Incorrect API key provided.","type":"invalid_request_error","param":null,"code":"invalid_api_key"}}
  • openai.AuthenticationError
  • codex stream error: unexpected status 401

Short link: https://apitoken.sale/e/openai-invalid-api-key · Returned by the OpenAI lanes of the unified endpoint (router.apitoken.sale/v1).

402insufficient_quota / insufficient_quotaaccount balance is insufficientNo
HTTP 402
{"error":{"message":"Your account balance is insufficient for this request.","type":"insufficient_quota","param":null,"code":"insufficient_quota"}}

Why it happens

  • The prepaid balance shared by every lane of the unified endpoint is too low to cover the request.
  • Spend on one lane empties the same balance for the others.
  • HTTP status is 402, not 429. Official OpenAI Platform puts money on 429 insufficient_quota; this product does not, because OpenAI SDKs retry 429. type and code stay insufficient_quota so you can still branch on the field.

How to fix it

  • Top up any whole-dollar amount and retry after the payment is credited. Backoff alone never resolves a 402.
  • Confirm the live balance with the same key before retrying.
  • Treat 429 as retryable capacity. Treat 402 insufficient_quota as empty prepaid balance.

Other forms of the same failure

  • openai insufficient_quota
  • codex 402 insufficient balance

Short link: https://apitoken.sale/e/openai-insufficient-quota · Returned by the OpenAI lanes of the unified endpoint (router.apitoken.sale/v1).

404invalid_request_error / model_not_foundmodel does not existNo
HTTP 404
{"error":{"message":"The model \"gpt-9.9\" does not exist or you do not have access to it.","type":"invalid_request_error","param":null,"code":"model_not_found"}}

Why it happens

  • The model ID is misspelled, or it needs the namespaced form: on the shared lanes the catalog publishes anthropic/claude-*, openai/gpt-* and google/gemini-*, and a bare native ID fails once it becomes ambiguous.
  • The model is not in the currently enabled catalog — the served set changes as models are admitted.

How to fix it

  • List the models your key can actually use: GET https://router.apitoken.sale/v1/models with Authorization: Bearer.
  • Check the ID character for character — gpt-5.6-sol, not gpt5.6 or gpt-5.6.sol. gpt-5.6 is a valid alias of gpt-5.6-sol.

Discover the enabled models

curl https://router.apitoken.sale/v1/models \
  -H "Authorization: Bearer $APITOKEN_API_KEY"

Other forms of the same failure

  • openai model_not_found
  • codex stream error: unexpected status 404
  • The model does not exist or you do not have access to it

Short link: https://apitoken.sale/e/openai-model-not-found · Returned by the OpenAI lanes of the unified endpoint (router.apitoken.sale/v1).

429rate_limit_error / rate_limit_exceededrate limit reachedYes, back off
HTTP 429
{"error":{"message":"Rate limit reached. Please retry shortly.","type":"rate_limit_error","param":null,"code":"rate_limit_exceeded"}}

Why it happens

  • The account's concurrency or rate ceiling was exceeded — a parallel burst with no cap is the usual cause.
  • Retries piling on top of the requests that caused the first 429 enlarge the burst instead of draining it.

How to fix it

  • Honor the Retry-After header — the response carries one.
  • Retry with capped exponential backoff and jitter, and cap concurrency at the call site.

Other forms of the same failure

  • openai rate_limit_error
  • codex stream error: unexpected status 429

Short link: https://apitoken.sale/e/openai-rate-limit · Returned by the OpenAI lanes of the unified endpoint (router.apitoken.sale/v1).

503server_error / service_unavailablemodel temporarily unavailableYes, back off
HTTP 503
{"error":{"message":"The requested model is temporarily unavailable. Please retry.","type":"server_error","param":null,"code":"service_unavailable"}}

Why it happens

  • Upstream capacity for the requested model is temporarily saturated. 503 describes the service, not your request.
  • It clusters during incidents: the same request typically succeeds minutes later with no change.

How to fix it

  • Retry with exponential backoff and jitter — the response carries a Retry-After hint.
  • For latency-sensitive paths, fall back to another enabled model tier, which is generally less contended.

Other forms of the same failure

  • openai service_unavailable server_error

Short link: https://apitoken.sale/e/openai-service-unavailable · Returned by the OpenAI lanes of the unified endpoint (router.apitoken.sale/v1).

Gemini lane — all codes

The native Gemini lane returns the Google error envelope — branch on error.status and ErrorInfo reason. Invalid customer keys are 400 INVALID_ARGUMENT / API_KEY_INVALID. Prepaid money is 402 FAILED_PRECONDITION. A field the official Gemini API accepts and this endpoint cannot honour is 400 INVALID_ARGUMENT with a stable *_UNSUPPORTED reason:

{"error":{"code":400,"message":"API key not valid. Please pass a valid API key.","status":"INVALID_ARGUMENT","details":[{"@type":"type.googleapis.com/google.rpc.ErrorInfo","reason":"API_KEY_INVALID","domain":"googleapis.com"}]}}

Open a row for the exact response body and the fix. You do not need to scroll past the other errors.

400INVALID_ARGUMENT / API_KEY_INVALIDAPI_KEY_INVALIDNo
HTTP 400
{"error":{"code":400,"message":"API key not valid. Please pass a valid API key.","status":"INVALID_ARGUMENT","details":[{"@type":"type.googleapis.com/google.rpc.ErrorInfo","reason":"API_KEY_INVALID","domain":"googleapis.com","metadata":{"service":"generativelanguage.googleapis.com"}}]}}

Why it happens

  • The native Gemini lane answers 400 INVALID_ARGUMENT with ErrorInfo reason API_KEY_INVALID — the official Google API does the same. Other lanes answer 401.
  • The x-goog-api-key header is missing, empty, mistyped, or carries a revoked key.
  • x-api-key or Authorization: Bearer was sent instead. Those headers belong to the Anthropic and OpenAI lanes.

How to fix it

  • Send an active sk-pool key in x-goog-api-key. Treat this 400 exactly like a 401: do not retry the same key.
  • If the key was revoked, create a replacement in the dashboard.

Other forms of the same failure

  • API_KEY_INVALID
  • API key not valid. Please pass a valid API key.

Short link: https://apitoken.sale/e/gemini-invalid-api-key · Returned by the native Gemini lane (router.apitoken.sale/v1beta and gemini.api.apitoken.sale).

400INVALID_ARGUMENT / FILE_URI_UNSUPPORTEDFILE_URI_UNSUPPORTEDNo
HTTP 400
{"error":{"code":400,"message":"fileData cannot be honoured on this endpoint. The official Gemini API accepts it; send the file as inlineData with mimeType and base64 data.","status":"INVALID_ARGUMENT","details":[{"@type":"type.googleapis.com/google.rpc.ErrorInfo","reason":"FILE_URI_UNSUPPORTED","domain":"googleapis.com","metadata":{"service":"generativelanguage.googleapis.com","param":"fileData"}}]}}

Why it happens

  • The official Gemini API accepts fileData / file_uri. This endpoint cannot honour a Google-project Files API reference on synchronous generateContent, so it fails closed with a stable ErrorInfo reason.
  • The same class covers cachedContent (CACHED_CONTENT_UNSUPPORTED), explicit serviceTier, explicit store logging controls, and audio on a model this gateway does not serve audio for.

How to fix it

  • Send the file inline as inlineData with its mimeType and base64 data.
  • For large Gemini Batch input, upload an account-scoped JSONL file to this gateway and pass the returned name as inputConfig.fileName.
  • Do not retry the identical body.

Other forms of the same failure

  • cachedContent cannot be honoured on this endpoint. The official Gemini API accepts it; omit 'cachedContent' or send the content inline.
  • CACHED_CONTENT_UNSUPPORTED
  • FILE_URI_UNSUPPORTED

Short link: https://apitoken.sale/e/gemini-file-uri-unsupported · Returned by the native Gemini lane (router.apitoken.sale/v1beta and gemini.api.apitoken.sale).

402FAILED_PRECONDITIONFAILED_PRECONDITION (prepaid balance)No
HTTP 402
{"error":{"code":402,"message":"The account balance is insufficient for this request.","status":"FAILED_PRECONDITION"}}

Why it happens

  • The shared prepaid balance cannot cover the request. Gemini has no money 402 on the official API; this gateway still sends HTTP 402 so clients do not retry it as capacity.
  • error.status is FAILED_PRECONDITION. It is not RESOURCE_EXHAUSTED and it is not 429.

How to fix it

  • Top up any whole-dollar amount and retry after the payment is credited.
  • Do not treat 402 as a rate limit. Backoff never restores an empty balance.

Other forms of the same failure

  • The account balance is insufficient for this request.
  • gemini 402 FAILED_PRECONDITION

Short link: https://apitoken.sale/e/gemini-insufficient-balance · Returned by the native Gemini lane (router.apitoken.sale/v1beta and gemini.api.apitoken.sale).

Still stuck?

If a request fails in a way this page does not cover, send us the endpoint, the masked key id, the HTTP status and the response body. Never send the full key.

apiToken.sale serves the native Anthropic Messages (including the KIMI lane on kimi/*), OpenAI Responses and Gemini APIs plus an OpenAI-compatible route through one unified router endpoint, so every non-gateway error on this page behaves exactly as it does against the official endpoints. See also the rate limits guide and how to point an SDK at a custom base URL.