POST https://api.airouter.io/v1/select returns a ranked model-selection decision for applications that run their own gateway. It does not call a model, execute a completion, or return generated content. Your gateway uses the first candidate or applies its own policy to the ranked candidates, then sends the completion to the provider of its choice.
This endpoint is independent of the OpenAI-compatible chat completions path: calling one never calls the other.
Send an AI Router API key as a bearer token:
The Decision API is available on paid plans. Requests that send an embedding additionally require the full privacy feature; see the pricing page.
Exactly one selection input is required:
messages sends the chat prompt to AI Router for embedding and selection.embedding keeps the prompt private. When it is used, embedding_type is also required and messages must be omitted.| Field | Type | Required | Description |
|---|---|---|---|
messages | array of objects | One input required | Chat messages used to make the decision. |
embedding | array of numbers | One input required | Client-generated prompt embedding. Requires embedding_type. |
embedding_type | "fastembed_mpnet" or "openai_small" | With embedding | Identifies the embedding model (paraphrase-multilingual-mpnet-base-v2 or text-embedding-3-small) so the matching benchmark data is used. |
model | string | No | Default model for this decision; overrides the team default. |
models | array of strings | No | Candidate model names. Defaults to the team's enabled models (or the API key's subset). |
weighting | object | No | Non-negative costs, latency and quality boost factors. Defaults to the team preferences. See Weighting. |
max_tokens | positive integer | No | Expected maximum completion tokens, used for cost and latency prediction. |
tools | boolean | No | Whether the completion will require tool support. Defaults to false. |
Unknown request fields are rejected. messages and embedding cannot both be present, and embedding_type cannot be sent without embedding.
Generate the embedding in your environment with one of the supported embedding models, then send only its numeric vector:
The shortened vector is illustrative. Production input must contain the full vector produced by the embedding model identified by embedding_type. The response uses the same schema as the chat-prompt example and does not echo the embedding.
| Field | Type | Description |
|---|---|---|
decision_id | string or null | Identifier used to report usage for this decision. It is null when the decision could not be logged. |
candidates | array | Candidates in descending recommendation order. |
candidates[].model | string | Canonical model name to use for the completion. |
candidates[].effort | "minimal", "low", "medium", "high", or null | Reasoning effort to pass when the candidate has an effort tier. |
candidates[].quality | number | Predicted raw quality measurement. |
candidates[].costs | number | Predicted raw completion cost. |
candidates[].latency | number | Predicted raw completion latency. |
candidates[].quality_score | number | Normalized quality component used for ranking. |
candidates[].costs_score | number | Normalized cost component used for ranking. A higher score is preferred. |
candidates[].latency_score | number | Normalized latency component used for ranking. A higher score is preferred. |
candidates[].score | number | Final weighted score. A higher score is preferred. |
predicted_savings | object or null | Predicted savings relative to the router's reference model. null when a comparison is unavailable. |
predicted_savings.costs | number | Fractional predicted cost reduction; 0.41 means 41% lower predicted cost. Negative values indicate an increase. |
predicted_savings.latency | number | Fractional predicted latency reduction; 0.23 means 23% lower predicted latency. Negative values indicate an increase. |
Choose candidates[0] for the router's preferred decision. The raw quality, costs, and latency values explain the underlying predictions; their corresponding *_score values are normalized ranking components. The final score blends those components using the request's weighting. Use decision_id as the handle when reporting the resulting completion's usage. A null value does not invalidate the selection; it means the decision log was unavailable when the response was produced.
| Status | Meaning |
|---|---|
400 | Invalid JSON or an invalid request (both or neither input, unknown fields, negative weights). |
401 | Missing or invalid API key. |
403 | The Decision API or full privacy mode is not included in your plan. |
Authorization: Bearer $AIROUTER_API_KEY
Content-Type: application/json
curl https://api.airouter.io/v1/select \
--request POST \
--header "Authorization: Bearer $AIROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"messages": [
{"role": "user", "content": "Explain quantum tunnelling."}
],
"models": ["gpt-5-mini", "gemini-3.5-flash"],
"weighting": {"costs": 1.0, "latency": 1.0, "quality": 1.0},
"max_tokens": 512,
"tools": false
}'
{
"decision_id": "019c7f2e-2e30-7d10-b1e5-50aa75c49a36",
"candidates": [
{
"model": "gemini-3.5-flash",
"effort": "low",
"quality": 0.91,
"costs": 0.00042,
"latency": 2.4,
"quality_score": 0.95,
"costs_score": 0.83,
"latency_score": 0.78,
"score": 0.88
},
{
"model": "gpt-5-mini",
"effort": null,
"quality": 0.89,
"costs": 0.00071,
"latency": 3.1,
"quality_score": 0.9,
"costs_score": 0.7,
"latency_score": 0.65,
"score": 0.79
}
],
"predicted_savings": {
"costs": 0.41,
"latency": 0.23
}
}
curl https://api.airouter.io/v1/select \
--request POST \
--header "Authorization: Bearer $AIROUTER_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"embedding": [0.12, -0.34, 0.56],
"embedding_type": "openai_small",
"models": ["gpt-5-mini", "gemini-3.5-flash"],
"tools": true
}'