Errors
Errors use the OpenAI envelope:
{ "error": { "message": "…", "type": "insufficient_quota", "code": "insufficient_quota", "param": null, "request_id": "req_…" } }Branch on code. The message is for people and may change. Every response, success or error, has an x-katara-request-id header, repeated as x-request-id and request-id so the OpenAI and Anthropic SDKs pick it up; error bodies carry it as request_id. Include it when you write to support.
The statuses follow the SDKs’ retry rules. The OpenAI and Anthropic SDKs retry 408, 409, 429 and every 5xx, and obey an x-should-retry header. Katara answers with a 429 or a 5xx only when waiting can help, and sends x-should-retry: false on the answers a retry cannot change. Katara never answers 502 or 504: a failure behind Katara is a 500 and a slow model a 503, so the error body always reaches you. A 402 with an error body is a refusal; a 402 that carries accepts is an x402 payment challenge.
| HTTP | code | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_request | The body is malformed. | Fix the request. |
| 400 | model_requires_x402 | The request names katara/cortex-genius or katara/cortex-smart with a key or from a Katara app. Those models are sold only per request with x402. param is model. | Name katara/cortex, or send the request without a key and pay with x402. |
| 400 | model_requires_usdc | The key pays with account credits, and the request can only be served for USDC. | Use a key that pays with USDC. |
| 400 | context_length_exceeded | The request is longer than the context window of every model that could read it; nothing was sent to a model. The message names the largest window. param is messages. | Shorten or summarise the conversation. |
| 400 | invalid_web_search | katara_web_search is malformed, or names both allowed_domains and blocked_domains. param is katara_web_search. | Send one domain list. |
| 400 | invalid_value | A field has a value Katara cannot serve, such as a malformed custom tool. param names the field. | Fix the field. |
| 400 | feature_not_supported | The model does not support what the request asks for: tools, structured output, reasoning, a tool_choice outside its contract, or a parameter it does not act on (param names the field). A parameter left at its default is accepted and dropped. | Check capabilities, tool_contract and supported_params on /v1/models. |
| 401 | invalid_api_key | Missing or unknown key. | Create a key in the portal. |
| 402 | insufficient_credits | The key pays with account credits, and the available credits cannot cover the request’s maximum cost. Not retried: the answer carries x-should-retry: false. | Add credits in Billing in the portal, or lower max_tokens. |
| 402 | insufficient_quota | The key pays with USDC, and its spendable balance is below the request’s maximum cost. Not retried: the answer carries x-should-retry: false. spendable_usdc and max_charge_usdc say how far short it is. | Add USDC, raise the budget cap, or lower max_tokens. |
| 403 | account_suspended | The account behind the key is suspended. | Contact support. |
| 403 | billing_suspended | Credit billing is paused for the account. | Contact support. |
| 403 | community_off | Only Katara Community could serve the request, and it is turned off by the request (param is katara.community), the key or the account. | Turn Katara Community on, or send a request a managed model can serve. |
| 403 | wrong_environment | A Live key was sent to the Test network’s address under https://api.katara.com/test. | Send it to https://api.katara.com/v1: the key decides the network. |
| 404 | model_not_found | An embeddings request named a model Katara does not serve. Chat, Messages, Responses and image requests accept any model name. | Use the model named in Embeddings. |
| 404 | not_found | No API route at that path. | Check the path against the API reference. |
| 405 | method_not_allowed | The path exists but not for that HTTP method. | Use the documented method. |
| 413 | request_too_large | The body is over 32 MB, or 4 MB for a request paid per call. | Upload large files through /v1/files and refer to them by id. |
| 413 | media_too_large | The images, recordings and documents in one request add up to more than 20 MB decoded. | Send fewer or smaller files, or upload them through /v1/files. |
| 429 | provider_rate_limited | Every vendor that could serve the request is rate limiting. Nothing was charged. | Retry after Retry-After, which repeats the vendor’s own wait, up to 60 seconds. |
| 500 | internal_error | Something failed on our side. | Retry; report the request id if it persists. |
| 500 | provider_output_invalid | Every provider tried answered with something Katara refused to deliver: a reply with no text and no tool call, a malformed tool call, tool syntax left in the text, a runtime fault, a reply stuck repeating itself, or a stop the runtime did not mean. Managed models are held to the same rule. Nothing was charged. A web search request whose model searched and wrote no answer ends the same way; its katara object lists the searches that ran, and only a Katara Community reply that asked for the search is charged. | Retry after Retry-After. |
| 500 | provider_rejected_request | Every provider tried refused the request body itself: a conversation history its runtime will not render, or a field it cannot take. Nothing was charged and a retry of the same request will fail the same way, so the answer carries x-should-retry: false. | Check the history and parameters, then send a corrected request. |
| 503 | provider_overloaded | Every vendor that could serve the request is overloaded or unavailable, some perhaps rate limiting. Nothing was charged. | Retry after Retry-After. |
| 503 | funding_pending | Your USDC is still being moved into your prepaid balance. Nothing was charged. | Retry after Retry-After. |
| 503 | no_capacity | No candidate could serve the request right now. | Retry after Retry-After. |
| 503 | storage_unavailable | File storage for /v1/files is unavailable. | Retry later. |
| 503 | test_network_unavailable | A Test key’s request did not reach the Test network. Nothing was charged. | Retry after Retry-After. |
| 503 | upstream_timeout | No candidate started its reply within its time limit, as a hard question sometimes does. Nothing was charged. | Retry after Retry-After. |
Streams
Section titled “Streams”A stream that fails after content was sent ends with an error chunk, then [DONE]:
data: {"error":{"message":"stream interrupted by provider failure; delivered tokens are not billed without a verified receipt","type":"server_error","code":"stream_interrupted"}}Two codes can appear there. stream_interrupted means the provider stopped or disconnected. provider_output_invalid means the provider’s reply failed validation, for example a tool call that could not be delivered, a reply that kept repeating itself, or a reply that ended with nothing delivered. In both cases nothing is charged for that attempt. Send the request again.
A reasoning model’s thinking arrives under reasoning_content in the message or the delta, before the answer. It is shown and it counts as output tokens at the model’s output price, but it is never the answer: a reply that only reasoned and never answered is refused like an empty one.
Agent runs paid from a wallet
Section titled “Agent runs paid from a wallet”The product API refuses a budget or a run when the wallet paying for it cannot: wallet_required, wallet_insufficient_funds, wallet_unpaid_limit, wallet_payment_failed and wallet_unavailable. Pay for runs from your wallet says what each means. A run paid per run with x402 has its own refusals, listed under run errors.
Wallet-paid requests
Section titled “Wallet-paid requests”If the model quoted for a Cortex request paid per call fails before delivering anything, the next model answers under the same payment. When that model costs more than the payment covers, the answer is a fresh 402 for it instead: sign it and retry, the first authorization expires unused. Each address may hold a limited number of unpaid quotes; past it the answer is 429 quote_rate_limited with Retry-After. Pay per request with x402 lists the payment errors and those of the Responses API.