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. Both 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 hopscotch/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
Nothing. There is no request schema of ours in front of the provider’s, no allowlist of parameters, and no list of fields to strip.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.
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 same is true of a request on POST /v1/responses, with one addition. That
endpoint reads one field of your body before forwarding it: store. This
platform stores no response, so store: true is refused with 400, the code
unsupported_value and param set to store, before anything is held and
before any provider is called. Sending store: false, or leaving the field out
entirely, is served. Every other field of a Responses body, 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.
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.