What is read
Admission reads two things out of your body, both to work out what the request could cost before it is sent:
Neither read changes the field, and the two fields answer differently when the
value cannot be made sense of.
A ceiling this cannot read falls back to being treated as absent rather than
being corrected, so credit is held at the model’s published maximum output and
the provider answers for its own body.
model has no such fallback: it is the
one field admission cannot proceed without, so a missing model and a model id in
a shape this does not accept are both refused here, before any provider is
called. Both refusals are in The refusals that are ours
below, and both name a param, which is how you tell them from the provider’s.
What is rewritten
Two rewrites exist on every key, and two more on the platform’s own provider keys, listed below: an omittedstore on Responses is sent as false, and three routing fields a
reseller provider reads are removed from a chat body. All are named here because a body that arrives different
from the one you sent should never be something you discover from a provider’s
error message.
model, when you asked for a route rather than a model. A request naming
profile/{identifier} or unirouter/auto is a request for a list of models
tried in order, so the body that reaches a provider carries the id of the model
being tried on that attempt. See Routing profiles.
max_tokens, when the provider’s own API refuses a request without one. Some
providers require the field. If your body carries neither max_tokens nor
max_completion_tokens and the provider is one of those, the field is added,
and the value used is the model’s published max_output_tokens, which is the
figure credit was already being held against. Nothing else in the body is
touched, and a body that already names a ceiling is sent unchanged. Every other
provider is sent your body without the field, exactly as you wrote it.
What happens to everything else
Almost nothing. There is no request schema of ours in front of the provider’s and no allowlist of parameters.temperature,
top_p, stop, seed, logprobs, tools, tool_choice, response_format,
and any parameter a provider adds next month all reach the provider as sent.
This cuts both ways, and the second half is the half worth planning for:
- A parameter is never refused here for being unfamiliar. You do not wait for us to add support for something your client already sends.
-
A parameter is never validated here either. If a model will not take the
parameter, or will not take the value, the answer you get is the provider’s own
refusal relayed with its own status and its own sentence. We do not pre-empt it
with a refusal of our own, and we do not translate it.
There is one exception, and it is a single value rather than a field: an empty
or whitespace-only
reasoning_effortis refused here with a400,codeinvalid_valueandparamset toreasoning_effort. It is the one value no provider accepts, so relaying it would spend a round trip to be told the same thing. Any otherreasoning_effortyou send, string or otherwise, is forwarded. See Reasoning models. The other is a short list of fields refused on the platform’s own provider keys and forwarded on yours, in the next section.
400 on a chat completion has two possible authors. Ours name a param and
come from the short list below. Everything else on that status came from the
provider and reads like the provider.
The fields refused on the platform’s own provider keys
A request served on the platform’s own provider keys is refused, before anything is held and before any provider is called, when it carries a field that buys something this platform cannot bill yet or asks the provider to keep the conversation under our account:- a
service_tierother than the provider’s standard one (auto,defaultoron_demandon chat completions,autoordefaulton Responses), web_search_options, or a hosted tool the provider charges for per call (web search, web fetch, code execution, and on a Gemini model a grounding tool such asgoogle_search),- audio in (an
input_audiopart) or out (audio, or audio inmodalities), - a
cache_controlmarker with a1httl, store: true, and onPOST /v1/responsesalsoprevious_response_id,conversation, anitem_referenceinput item andbackground: true.
400 with code null and param naming the field, never its value,
and the message says to remove it or send the request on your own provider key.
On POST /v1/responses an omitted store is sent to the provider as false.
A request served on your own provider key keeps every one of them and goes
out as you sent it, because the provider bills and stores it against your own
account. See Bring your own key.
On chat completions, the routing fields provider, models and transforms,
which a reseller provider reads, are removed from the body rather than refused, so a client that
sends them keeps working and the model you named is the one you are charged for.
Every other field, including the reasoning and verbosity parameters a client may
send, travels to the provider untouched and is answered by the provider.
The refusals that are ours
Each of these is decided before any provider is called, and none of them charges you anything. No model named. The one field admission cannot do without.400
400
with the code model_id_not_pinned. See Models.
A prompt too large to hold credit against. 400 with
context_length_exceeded and param set to messages. This is a refusal about
sizing the hold, and it happens before the model’s own context window is ever
consulted, so it is not the same thing as a provider telling you the prompt does
not fit.
No ceiling can be worked out. 503 with model_not_priceable, when your
body names no output ceiling and the model publishes no maximum output either.
The message says what to do, and it is worth reading rather than retrying:
model_not_priceable that a retry does not fix. The others on
that code clear on their own. See Errors.
max_tokens and what it holds
The credit held while a request runs is sized from an output ceiling, and the
ceiling is the smaller of two figures: the one you sent, and the model’s own
published max_output_tokens.
A body asking for more than one completion, with
n or best_of, holds that many
output ceilings (the larger of the two when both are sent), because the provider bills each completion its own output. The
prompt is held once. A balance that cannot cover the larger hold is refused with the
ordinary 402.
The hold is returned in full at settlement and you are charged for what the
request actually produced, so sending max_tokens never costs you the
difference. What it changes is how much of your account spend rate cap one
request occupies while it is in flight. See
Rate limits and spend controls.
The parameters a given model takes
GET /v1/models/{id} returns a parameters array for that model: the request
controls it accepts, with their bounds and defaults. It is served only on the
single-model call, never on the list, because a list is scanned and a detail is
read.
One entry
The three bounds are in thousandths. A temperature ceiling of two arrives as
2000, and a default of nought point seven as 700. They are integers on
purpose: a bound that drifted in its last decimal place would be a contract about
nothing. Divide by a thousand before you show one to a person.
Two things this list is and is not. It is a description of a model, useful for
building a form or validating input before you spend a request finding out. It is
not a filter on the API: a parameter absent from the list is still forwarded if
you send it, and the provider still answers for it.