Gateway
beta-router
Send model: beta-auto and Conifer picks the model for that turn from your routing pool, or from the catalog your key can call. The receipt names what it picked. Nothing is ever substituted behind a named id.
What it is
Every model in the catalog is behind one key. When you would rather not choose between them, send beta-auto instead of a model name and Conifer chooses for you, turn by turn. It looks at what the request needs, picks the model, and answers in the same request. The gateway then picks the host that serves that model. The receipt headers say which model served and what the turn cost. Routing adds no fee: the turn costs what the chosen model costs.
beta-auto is listed in /v1/models and /v1/catalog with virtual: true and the display name beta-router. It is not a model. Any key that can call the whole catalog can send it. A key limited to a list of named models gets a 404 model_not_found.
Your routing pool
beta-router picks only from the models in your routing pool, which you choose in the console under Models, Routing pool. With an empty pool it picks from every model your key can call. Company keys use the company owner’s pool. If no model in the pool can serve a request, for example because none of them has the context window it needs, the request is refused with a 422 no_eligible_model before anything is charged.
Use it
Any client that lets you set the model id. The examples below are the same call.
curl
curl -s -D - https://api.conifer.build/v1/chat/completions \
-H "authorization: Bearer $CONIFER_API_KEY" \
-H "content-type: application/json" \
-d '{"model":"beta-auto","messages":[{"role":"user","content":"What is 17 * 23?"}],"max_tokens":50}' \
| grep -i x-conifer
# x-conifer-requested-model: beta-auto
# x-conifer-effective-model: <the model it picked>
# x-conifer-receipt-reason: routed
# x-conifer-cost-nanousd: <what the turn cost>The Conifer SDK
import { Conifer } from "conifer-sdk";
const conifer = new Conifer(); // reads CONIFER_API_KEY
const answer = await conifer.chat({
model: "beta-auto",
messages: [{ role: "user", content: "What is 17 * 23?" }],
maxTokens: 50,
});
answer.receipt.effectiveModel; // the model it picked
answer.receipt.reason; // "routed"from conifer_sdk import Conifer, ChatRequest
conifer = Conifer() # reads CONIFER_API_KEY
answer = conifer.chat(ChatRequest(
model="beta-auto",
messages=[{"role": "user", "content": "What is 17 * 23?"}],
max_tokens=50,
))
answer.receipt.effective_model # the model it picked
answer.receipt.reason # "routed"The openai package
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.CONIFER_API_KEY,
baseURL: "https://api.conifer.build/v1",
});
// The model id is the whole integration. The receipt is in the headers.
const { data, response } = await client.chat.completions
.create({ model: "beta-auto", messages: [{ role: "user", content: "hi" }] })
.withResponse();
response.headers.get("x-conifer-effective-model");
response.headers.get("x-conifer-receipt-reason"); // "routed"Codex, Cursor, Cline, anything with a model field
Codex reaches Conifer through the provider block on the Codex page. Add it to your config once, then pass beta-auto as the model.
[model_providers.conifer]
name = "conifer"
base_url = "https://api.conifer.build/v1"
wire_api = "responses"
env_key = "CONIFER_API_KEY"# Codex speaks the Responses wire. beta-router routes it the same way.
codex -c model_provider="conifer" -c model="beta-auto"Read the receipt
On a routed turn x-conifer-requested-model is beta-auto and x-conifer-effective-model is the model that served.
| Header | What it says |
|---|---|
x-conifer-receipt-reason | routed when Conifer chose the model; provider_failover when the picked model was served by another host after the first failed. |
x-conifer-cost-nanousd | What the turn cost, in nanodollars. |
A live stream has no cost headers. It ends with a conifer_receipt event that carries the cost.
When it cannot route
beta-router never falls back to another model on its own. When it cannot make a pick, the request fails and nothing is charged.
| Status | Meaning |
|---|---|
503 service_unavailable | The router could not make a valid decision this time. Send the request again with a new request id, or name a model. |
422 no_eligible_model | No model in your pool, or in the catalog your key can call, can serve this request. |
400 | The router could not read this input, or the request also sent x-conifer-fallback-models, which beta-auto does not take. |
If the picked model’s host fails, the gateway serves the same model from another host and marks the receipt provider_failover. It never switches to a different model.
A long request is still routed: the picked model receives the whole request, and only models whose context window holds it are considered. The limits on the beta-auto catalog entry are the router’s own, not the picked model’s.
Which doors route
| Endpoint | model: beta-auto |
|---|---|
/v1/chat/completions | Routes. Streams live and ends with a conifer_receipt event; x-conifer-stream-mode says live, or buffered when the host cannot stream live. |
/v1/responses | Routes and streams live. Codex and the other Responses-wire agents get the router. Send x-conifer-stream-receipt: true for the receipt event. |
/v1/completions | Routes. |
/v1/messages | Routes among the models that speak the native Anthropic Messages wire. A stream arrives buffered. |