Provider Routing
A model is often served by several providers, and provider.type pins a request to one of them. Which providers exist and why you would pin one are covered in Provider routing; this page is the per-protocol field contract.
Where the field goes
The field is not in the same place on every protocol:
| Protocol / endpoint | Request body | Request header |
|---|---|---|
OpenAI Chat Completions · POST /v1/chat/completions | extra_body.provider.type | X-OfoxAI-Provider-Type |
OpenAI Responses · POST /v1/responses | extra_body.provider.type | X-OfoxAI-Provider-Type |
OpenAI Images · POST /v1/images/generations | extra_body.provider.type | X-OfoxAI-Provider-Type |
Anthropic Messages · POST /anthropic/v1/messages | extra_body.provider.type | X-OfoxAI-Provider-Type |
Gemini generateContent · POST /gemini/v1beta/… | silently ignored | X-OfoxAI-Provider-Type |
Video API · POST /v1/videos | top-level provider.type | — |
Among image models only openai/gpt-image-2 is currently served by more than one provider (azure_foundry and openai); the rest are single-provider, so naming a different one returns 400 provider_type_unavailable. Note also that Gemini image models are reachable through two protocols — on /v1/images/generations the body field works, on the Gemini native generateContent it is ignored.
Passing it in the request body
extra_body must be a literal key in the JSON body, with provider nested inside it:
cURL
curl https://api.ofox.io/v1/chat/completions \
-H "Authorization: Bearer $OFOX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-5",
"messages": [{ "role": "user", "content": "..." }],
"extra_body": {
"provider": { "type": "bedrock" }
}
}'With the official OpenAI SDKs, extra_body must be present as a literal key in the request body. The TypeScript SDK sends it as written in the params object. The Python SDK’s extra_body= argument merges its contents into the top level of the body, so the key must be nested one level deeper, or passed as a request header instead.
The Gemini native protocol ignores extra_body.provider in the body — the request succeeds and the constraint simply does not apply, with no error. On that protocol use the header below instead.
Passing it in a header
X-OfoxAI-Provider-Type works on every text protocol, including Gemini, and suits integrations that cannot modify the request body:
curl https://api.ofox.io/gemini/v1beta/models/google/gemini-3.1-flash-lite:generateContent \
-H "Authorization: Bearer $OFOX_API_KEY" \
-H "X-OfoxAI-Provider-Type: vertex" \
-H "Content-Type: application/json" \
-d '{
"contents": [{ "parts": [{ "text": "..." }] }]
}'The header and the body field are equivalent where both are supported. The Video API has no header form — see Video API · Provider routing.
Errors
error.type | When it happens |
|---|---|
invalid_provider_type | The value is not a provider name — a typo, or a spelling that has been retired. |
provider_type_unavailable | The provider exists but does not serve this model. The message also lists the providers that do. |
Which providers you can name
The full list, and how to find which providers serve a given model, are in Provider routing.