Skip to content
youbot
Docs menu

API reference

Errors

Errors use standard HTTP status codes. Every error body carries a human-readable error sentence and a stable code you can branch on — branch on code, never on the wording of error, which may be reworded at any time.

json
{
  "error": "Insufficient credits: this call costs 24, balance is 7.8.",
  "code": "insufficient_credits",
  "need": 24,
  "have": 7.8,
  "topup_url": "https://you.bot/dashboard/billing"
}

On chat models, image input is refused rather than ignored: attaching an image to a chat model whose reference has no images parameter comes back 400 with image_input_not_supported and is not charged — we do not answer a question about a picture the model never received. On media models (image, video, audio), an images key is not part of the schema and is dropped like any other unknown field; send media through the input fields that model documents.

need and have are credits and appear only on a shortfall; topup_url appears only where topping up is the remedy, and it is a signed-in page, so send a person to it rather than a script. A 402 whose code is spend_cap_daily or spend_cap_monthly is your own key's limit, and pricing_unavailable is a fault on our side — neither is fixed by topping up, so do not retry those.

We tell the model who it is — unless you send your own system instruction. When you omit system, we add one that names the model you called and instructs it to answer with that name if asked, rather than deflecting or naming another. This was measured: without that clause a model answers with a generic description of itself, and sometimes invents a version that does not exist.

If you send your own system, it REPLACES ours entirely — the model then knows only what your instruction tells it. Include your own identity line if you want it to answer "which model are you?" correctly. This is the most common reason a caller sees an assistant deny being the model they requested.

What a model says about OTHER versions is still not evidence either way: asked about a version that does not exist, a model will often confirm it exists and even give a release date, then contradict itself later in the same conversation. The record is the model field returned on every call — read from the model's own reply — together with your usage log, where each row also shows which API key it arrived on. If either ever shows a model you did not request, send us the task id and we will trace it.

codeWhen
insufficient_credits402 — the account balance will not cover the call.
spend_cap_daily / spend_cap_monthly402 — this API key's own spend limit was reached.
trial_shared_network402 — trial credits cannot be spent through the API from a network where another free account already uses the API. Nothing ran and nothing was charged. Top up to keep using the API from there; the response carries topup_url. Accounts that have topped up, and the Playground, are not affected.
trial_linked_account402 — trial credits on this account cannot be used, because it is linked to another free account: a request from it used a task ID or file that belongs to another free account, or the account continues another free account's trial. Nothing ran and nothing was charged. Top up to keep generating; the response carries topup_url. Accounts that have topped up are not affected.
model_not_allowed403 — this API key is restricted to a list of models and the requested model is not on it. Nothing ran and nothing was charged.
pricing_unavailable402 — the model is misconfigured on our side. Nothing ran and nothing was charged.
invalid_request400 — parameters the model will not accept.
unauthorized401 — missing or invalid API key.
forbidden403 — the request IP is not on this API key's IP allowlist. The message names the IP we saw, so you can add that exact address or a CIDR range that covers it (an IPv6 address is listed separately from an IPv4 one; for IPv6 its /64 survives address changes).
model_unavailable403 — the model is not on sale right now (closed, or coming soon). Nothing ran and nothing was charged; pick another model.
account_suspended403 — this account is suspended. Nothing ran and nothing was charged; contact support.
account_restricted403 — this account is restricted while a payment dispute is reviewed. Nothing ran and nothing was charged; contact support.
rate_limited429 — retry after the Retry-After header.
search_not_performed422 — web_search was requested but the reply came back without an answer, so the turn is refused rather than handed to you as an answer. The model still read your input and produced tokens before we could tell, and those tokens are charged at its ordinary rates; when it reports none, nothing is charged. Retry without web_search.
duplicate_request409 — an identical submit arrived moments ago. Nothing was charged; retry is safe.
payload_too_large413 — the prompt, an attachment, or the account's upload quota is over the limit.
not_found404 — the task or file was not found, or it has expired.
timeout504 — the upstream took too long. Nothing was delivered; retry is safe.
upstream_error / unavailable / internal_error502 / 503 / 500 — a media task that produced no result is refunded.
image_input_not_supported400 — this model takes text only. A model that accepts images lists an images parameter in its own reference; one that does not, refuses here rather than answering about a picture it never received.
too_many_images400 — more images than that model's images parameter allows in one message, or more than 8 across the whole request.
image_too_large400 — one attachment is over the per-image size limit.
image_format_unsupported400 — not JPEG, PNG, GIF or WebP. Read from the file's own bytes, so a data: URL that names the wrong type is refused on its content, not its label.
image_unreadable400 — the image, or its pixel size, could not be read. Send a data: URL, an https URL we can fetch, or an upload from this account.
capability_not_supported400 — a capability was requested that the model does not offer (for example web_search: true on a model whose API reference lists no web_search parameter, or tools on one that lists no tools). Refused with nothing charged, rather than answered as if the capability had run. Web search and function calling are available only where the model's own reference lists them.
tools_invalid400 — tools is malformed: not an array, a tool that is not a function, a name that breaks the naming rule or repeats, parameters that is not an object schema, more functions than allowed, or the older functions key. Also when a conversation carrying function calls arrives without tools. Nothing is charged.
tool_choice_invalid400 — tool_choice is malformed, names a function that is not in tools, forces a call while tools is empty, or forces a call together with thinking on a model that cannot combine them. Nothing is charged.
message_tool_call_invalid400 — an assistant message's tool_calls or a tool message is malformed (a call without an id or name, a result without tool_call_id), or a call and its result do not pair up: every call needs its result right after the assistant message that made it. Nothing is charged.
message_tool_block_unsupported400 — a tool_use or tool_result content block was sent inside content. Send calls as tool_calls on the assistant message and each result as a message with role tool.
image_not_received422 — the model answered that it did not receive the attached image. A confident answer about a picture the model never saw is worse than an error, so the turn is refused rather than delivered. The tokens the model reported for the turn are charged at its ordinary rates; when it reports none, nothing is charged. Retry.
empty_reply422 — the model returned no answer text (reasoning only, a call to a tool you did not declare, or an empty response; a call to one of your own tools is an answer, returned in toolCalls). If the model reported token counts for the turn, those tokens are charged at the model's ordinary rates — it read your input and spent output on reasoning; if it reported none, nothing is charged. Retry, and see usage on your log row for the figure.
unknown_image_field400 — images were sent under a key the model has no parameter for (input_urls, image_urls, imageUrl, …). Chat models that accept images take them as images; the request is refused rather than answered without them, and nothing is charged.
image_placement_unsupported400 — an image is attached to a message we do not send to the model as an image (a system message, an assistant message or a tool result). Attach images to a user message; they are refused rather than silently dropped.
prompt_and_messages400 — both prompt and messages were sent. Pick one; we do not choose for you, because the other one would disappear without a word.
messages_unsupported400 — messages was sent to a model that is not a chat model. Media models take a single prompt.
messages_not_array400 — messages is not an array of { "role", "content" } objects. A conversation flattened into one string is not a conversation; send real turns.
messages_empty400 — messages is an empty array. Send at least one message, or use prompt.
message_not_object400 — one entry of messages is not an object. The error names its index.
message_role_unknown400 — a message role is missing or is not user, assistant, system or tool (a function result, accepted on models that list tools). An unrecognised role is refused rather than treated as the user speaking.
message_content_type400 — a message content is neither a string nor an array of content blocks.
message_empty400 — a message carries neither text nor images. Leave it out instead; an empty turn would otherwise vanish on the way upstream.
Chat messages and a caller-supplied system prompt are capped at 10,000,000 characters each; over that the call is refused with 413 and nothing is charged. Anything under it is sent in full — if it exceeds the model's own context window, the model's own error comes back to you.
StatusMeaning
400Invalid or missing parameters for the model.
401Missing or invalid API key.
402Insufficient credits — top up in Billing.
403Refused before anything ran: the request IP is not allowed for this key (forbidden), the key may not use this model (model_not_allowed), the model is not on sale (model_unavailable), or the account is suspended or restricted. The code says which.
404Task or file not found, or expired.
409Duplicate submit inside a short window — nothing was charged.
413Payload too large — prompt, attachment or upload quota.
422The model answered, but the answer was not usable (no text, an image it did not receive, or search results instead of an answer). The body names which. In all three the turn is refused rather than delivered, and the token counts the model reported for it are charged at the model's ordinary rates — when it reports none, nothing is charged. A 4xx because the body must reach you — a 5xx body can be replaced by the CDN in front of us.
429Rate limited — slow down and retry after the Retry-After header.
504Upstream timed out — nothing was delivered; retry is safe.
5xxUpstream or gateway error — a media task that produced no result is refunded.