What each model supports
Requesting a capability a model does not have returns400 with error.code hosted_capability_not_supported and param naming the field. You find out at the call, not in the output.
Give reasoning models room
Every live model except DeepSeek V4 Pro reasons before it answers by default; DeepSeek V4 Pro returns its answer directly. Reasoning tokens are billed output and they count towardmax_tokens, ahead of the visible answer. A small budget can be spent entirely on thinking and return a completion whose content is empty, billed for the tokens it generated.
Measured on this endpoint on 2026-08-14 by sending the prompt “Write a TypeScript retry helper.” and recording how often a complete answer came back:
The budget is a ceiling, not a spend. At 16,384 DeepSeek V4 Flash still stopped on its own after roughly 7,500 output tokens, and raising the ceiling further did not make it generate more. Setting the ceiling too low is what costs money, because the request is billed for the reasoning and returns nothing to show for it.
How to detect an exhausted budget in code
How to detect an exhausted budget in code
RunInfra preserves Branch on
finish_reason: "length" and adds choices[].runinfra.output_status when a choice reaches its generation limit before producing final answer content.choices[].runinfra.output_status.code. generation_limit_reached_before_answer means the choice ended for length. If another terminal finish_reason produced no answer content, the code is no_answer_content and you should inspect finish_reason before retrying.The aggregate usage annotation appears only when every choice lacks a final answer. RunInfra does not estimate a reasoning-token count: completion_tokens stays the provider-reported total that settlement uses, and non_answer_completion_tokens records that those tokens produced no answer. The annotation changes no pricing.Turning reasoning off
reasoning_effort: "none" turns reasoning off for one request. The completion then carries the answer and no reasoning stream. Measured on this endpoint on 2026-08-16 with an identical prompt at temperature 0, the completion fell from 35 tokens to 3 on deepseek-v4-flash, from 335 to 5 on nemotron-3-5-lightning-30b, and from 67 to 5 on qwen3-8-27b. Because reasoning bills at the output rate, this is the largest per-request cost lever on short tasks.
qwen3-8-2-4t-a95b is the one model that cannot turn reasoning off. It refuses with 400 and the message “Disabling thinking is not supported.”, never silently ignored.
How the effort levels behave between none and the ceiling
How the effort levels behave between none and the ceiling
Measured on 2026-08-16 at temperature 0 with repeated runs per level.
deepseek-v4-flashappliesmaxwhen you send noreasoning_effort, and sendshighandxhighupstream asmax.mediumis reproducibly distinct from the default.qwen3-8-2-4t-a95bproduces reproducibly distinct reasoning atlow,mediumandxhigh(113, 140 and 89 completion tokens on the probe, withxhighequal to the omitted default).qwen3-8-27bmeasurably alters its reasoning atmedium, against a twice-identical baseline.nemotron-3-5-lightning-30blevel deltas stayed inside the model’s own run-to-run variance, so treat effort there as the off switch only.
enable_thinking, chat_template_kwargs.enable_thinking, thinking_budget and thinking are accepted for request-shape compatibility and have no effect on any listed model: a request relying on them still reasons and still bills for it. reasoning_effort is the one honored spelling.What the gateway does with a field you send
Every field lands in one of three dispositions. These are checked against the contract below, then forwarded:
A message needs a non-empty string
role. content may be a string, an array, or null. An assistant message needs content or a non-empty tool_calls. A tool message needs content and a non-empty string tool_call_id. Every other role needs content.
Sent untouched: the forwarding allowlist
Sent untouched: the forwarding allowlist
The gateway accepts any JSON value on these, applies no default, and forwards it unchanged. The model can still reject the value, which comes back as
400 invalid_request_error.audio, frequency_penalty, function_call, functions, logit_bias, logprobs, metadata, modalities, moderation, parallel_tool_calls, prediction, presence_penalty, safety_identifier, seed, service_tier, store, tool_choice, top_logprobs, user, verbosity, web_search_options.Four of them do carry gateway behavior:Removed before the request leaves the gateway
Removed before the request leaves the gateway
The allowlist is exhaustive: every other top-level field is dropped. Common examples are
max_output_tokens, reasoning, text, include, truncation and previous_response_id (Responses API fields on the Chat route); top_k, min_p, repetition_penalty, length_penalty and use_beam_search; guided_json, guided_regex, guided_choice and guided_grammar; and num_return_sequences, num_beams and beam_width, which the gateway reads for the four-choice safety check and then removes.An unknown field can pass request validation and still be removed here, so never rely on silent pass-through for a field that is not on the allowlist.Output limits
Omit both output-token fields and the gateway forwards no output limit at all, so the model generates until it stops on its own or reaches the remaining context. Send an oversized
max_tokens and the gateway clamps it to what the context allows rather than refusing the request: the response carries X-RunInfra-Output-Clamped: true and X-RunInfra-Output-Token-Ceiling with the value used.
Two bounds apply at once and the smaller one wins. Tokens are bounded by the remaining context above; wall-clock is bounded by the 240 second response limit, which at typical decode rates is the binding limit for very long generations. /v1/models publishes both, max_output_tokens beside response_time_ceiling_seconds, so size a long generation against the pair rather than the token figure alone.
The 504 message names the budget that was exceeded and carries Retry-After: 1. For a non-streaming request, error.runinfra.remedies suggests stream: true, because response headers arrive with the first token, and a smaller max_tokens value. An already-streaming first-token timeout does not repeat the streaming remedy.
A model’s context window is a separate per-model limit, published on that model’s page in the Model Library. Served context is a property of the deployment rather than of the weights, so read it there rather than assuming a figure from a model card.
Three things a request can be refused for
Each one is refused up front with a400 naming the field, rather than answered with output you cannot use.
A JSON format the model cannot hold while reasoning
A JSON format the model cannot hold while reasoning
response_format of json_schema or json_object is enforced during generation, and on some models that enforcement cannot start until the model has finished reasoning. Those models return 400 with code hosted_parameter_not_supported and param: "response_format", so you pay for a parameter edit instead of for output your parser rejects.deepseek-v4-flash and nemotron-3-5-lightning-30b are affected today. On each, the fix is reasoning_effort: "none" sent alongside response_format:response_format: {"type": "text"} constrains nothing and is never refused. On /v1/responses the same remedy is a top-level reasoning_effort beside text.format. Working snippets are in Structured output.An image, audio, or video content part
An image, audio, or video content part
Accepted input is a per-model fact, stated on each model page as the Accepted input row. Qwen3.8 27B accepts
image_url and input_image content parts as inline data URLs, up to 8 images per request: {"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}} with png, jpeg, webp or gif. Remote image URLs are not fetched; download the image, base64-encode it, and send the data URL. Image tokens are counted by the server inside prompt_tokens and bill at the model’s input rate.On every other live model, and for audio and video everywhere, a non-text content part inside messages returns 400 with param: "messages" and code: "hosted_parameter_not_supported", naming the model and the part to remove. The part is refused rather than stripped, so a request carrying media is never billed as if it were text.A prompt-cache control field
A prompt-cache control field
prompt_cache_key, prompt_cache_options and prompt_cache_retention are rejected with 400 hosted_parameter_not_supported. Prefix caching, where a model has it, is automatic server behavior and is not controllable per request.Calling a paused model
A hosted model can be temporarily paused. The request returns503 with code hosted_model_paused, error.paused_until carrying the scheduled return, and a Retry-After header in seconds capped at 60. Nothing is charged. The model id stays valid and stays listed by GET /v1/models with availability: "paused", so retry rather than re-resolving your configuration.
Related
Streaming
Read deltas and ask for the usage frame.
Rate limits
The three layers that can refuse you, and how to back off.
Errors
Every status, code, and caller action.