Provider routing
Choose which providers serve a request, and in what order.
Many models have more than one provider. RouterPlus picks the provider for each request. When a provider cannot serve, RouterPlus fails over to the next one before the first byte reaches you. Use the provider object to change the order or filter the providers.
Request
curl https://dev2-api.routerplus.com/v1/chat/completions \
-H "Authorization: Bearer $TM_API_KEY" -H "content-type: application/json" \
-d '{
"model": "moonshotai/kimi-k3",
"messages": [{ "role": "user", "content": "Hello" }],
"provider": { "sort": "price", "max_price": { "prompt": 1, "completion": 4 } }
}'Default order: lowest cost per good answer
For each provider of the model, RouterPlus estimates the cost of one good answer:
- the price of the model's typical request: uncached input, cached input at that provider's cache hit rate, and output;
- plus the cost of waiting: time to first token and output time at the provider's measured speed;
- plus the time lost to rate limits;
- divided by the share of requests that succeed, with a heavy penalty for provider errors and a penalty for malformed tool calls.
RouterPlus splits traffic as follows:
- Providers whose cost is close to the best share the traffic.
- Every provider keeps a small share, so RouterPlus keeps measuring new and recovering providers.
- A provider that fails or rate-limits gets less traffic until it recovers.
- Traffic above a provider's learned capacity goes to the next provider.
- Until providers have measurements, the cheapest goes first.
A conversation stays on the provider that served its first turn while that provider can serve. This keeps the provider's prompt cache warm. Requests that share a long prompt prefix (system prompt and tools) go to the same provider across sessions.
The response header x-tm-routing names the strategy: routing_cost (the default), price, throughput, latency or quality. It adds ;pinned or ;prefix when a conversation pin or a shared prefix chose the provider.
The provider object
| Field | Effect |
|---|---|
order | Try these providers first, in this order. Turns off the default order. |
only | Only these providers. |
ignore | Never these providers. |
allow_fallbacks | false: only the first provider, with no failover. |
require_parameters | Refuse the request instead of dropping a parameter a provider does not take. |
sort | "price", "throughput", "latency" or "quality", or { "by": ..., "partition": "model" | "none" }. Turns off the default order. See Sort. |
preferred_min_throughput | Tokens per second (a number means p50, or { "p50", "p75", "p90", "p99" }). Slower providers go last. None is excluded. |
preferred_max_latency | Seconds to first token, same forms. Slower providers go last. |
max_price | { "prompt", "completion" } in USD per million tokens, plus request and image. A provider above a cap is left out. |
quantizations | Only providers that serve the model at these quantizations (int4, int8, fp4, mxfp4, nvfp4, fp6, fp8, mxfp8, fp16, bf16, fp32, unknown). |
zdr | Only providers that keep no prompts or completions. |
data_collection | "deny": only providers that do not train on or keep request data. |
enforce_distillable_text | Only false is accepted for now. |
Guardrails on your key apply first. A request can narrow them. It cannot widen them.
Sort
sort | Order |
|---|---|
price | Cheapest first. |
throughput | Highest measured tokens per second first. |
latency | Lowest measured time to first token first. |
quality | Highest share of well-formed tool calls first. Ties go by the default cost estimate. |
In the object form, partition is "model" (the default) or "none". Both give the same order, because RouterPlus routes one model per request.
After the sort, a conversation pin or a shared prompt prefix can still choose the provider. preferred_min_throughput and preferred_max_latency then move providers that miss them to the end.
Errors
An unknown field in provider, or a sort or partition value outside the lists above, returns 400.
Your default
An organization or workspace can make price its default order with PATCH /v1/org {"default_sort": "price"} or PATCH /v1/workspaces/<id> (see the management API). A sort in the request wins over this default.
Rankings and benchmarks
| Endpoint | Returns |
|---|---|
GET /v1/rankings?period=day|week|month | Models ranked by tokens served on RouterPlus. A model used by fewer than 3 organizations is not listed. |
GET /v1/rankings?task=code|reasoning|extraction|chat|creative|vision|long_context | Models ranked for one kind of request. RouterPlus labels each request with its kind (the task label). |
GET /v1/rankings?view=sessions | Models ranked by sessions, with the median cost and the median number of requests per session. |
GET /v1/benchmarks/<model> | What the model takes (context, output limit, inputs, reasoning efforts, response formats) and how it serves now across its providers: the best latency, throughput, error rate and tool-call quality measured. |
GET /v1/benchmarks?task=coding|math|reasoning&limit=20 | Catalog models ranked by a quality index. See below. |
GET /v1/models/<model>/endpoints | Each provider with its price, data policy, status and measurements. Its quality field holds the model's quality scores. |
GET /v1/benchmarks?task=... ranks coding by the coding index, math by the math index and reasoning by the intelligence index. limit is 1 to 100 (default 20). When a model has no coding or math index, the mean of its published coding or math evaluations (out of 100) ranks it. A model with neither is not listed.
Quality scores
GET /v1/benchmarks/<model> and GET /v1/models/<model>/endpoints carry a quality object:
{ "quality": {
"intelligence_index": 58.4, "coding_index": 55.0, "math_index": 90.1,
"evaluations": { "gpqa": 0.9, "hle": 0.4, "livecodebench": 0.8 },
"aa_model": { "slug": "claude-opus-5-5", "name": "Claude Opus 5.5 (Max)" },
"source": "Artificial Analysis",
"source_url": "https://artificialanalysis.ai/",
"model_url": "https://artificialanalysis.ai/models/claude-opus-5-5",
"fetched_at": "2026-10-31T09:00:00.000Z" },
"scores_status": "ready" }- The scores come from Artificial Analysis. RouterPlus does not run these evaluations.
evaluationsholds every other evaluation Artificial Analysis publishes for the model, by its name.qualityisnullwhen Artificial Analysis has no entry for the model.scores_statusisready,loadingorunavailable.loadingmeans RouterPlus is fetching the scores. Ask again shortly.- Scores refresh every 6 hours.
fetched_atgives the time of the copy in use. - When you show these scores, credit Artificial Analysis and link to https://artificialanalysis.ai/. Artificial Analysis asks for this attribution.
For agents: /docs/provider-routing.md and /llms.txt