Routing policies and Azure connections
Order your provider connections and set fallback funding.
A routing policy is a saved rule set for a key. It says which of your connections and which marketplace deployments the key may use, in what order, and who pays. You can bind a policy to an org, a workspace or a key.
Create and bind a policy
Policy management uses the site origin, with the same session cookie, JSON content type and same-origin write protection as BYOK connection management. Inference keys cannot manage policies. Viewers can read them.
POST /api/routing-policies creates a policy revision. A revision never changes.
{
"models": ["your-exact-model-id"],
"connections": ["FIRST_CONNECTION_UUID", "SECOND_CONNECTION_UUID"],
"funding": "byok_only",
"allow_fallbacks": true,
"max_attempts": 4,
"timeout_ms": 450000
}The response is 201 with {"policy_id":"UUID"}. The connections must belong to your org.
| Request | Effect |
|---|---|
POST /api/routing-policies/{id}/bind with {"key_id":"KEY_UUID"} | Binds the policy to an existing key. |
POST /api/routing-policies/{id}/bind with {"scope":"org"} | Binds the policy to the org. |
GET /api/routing-policies | Lists the newest 100 revisions. |
GET /api/routing-policies/{id} | Returns one revision. |
Binding rules:
- An org policy applies to every key in the org. A key policy can narrow it.
- A key with no policy and no single-connection binding of its own uses the org policy.
- An older single-connection binding stays as an extra restriction when an org policy exists.
- Binding a policy to a key replaces the key's single-connection binding. Binding a single connection replaces the key's policy.
- To change a policy, create a new revision and bind it. You cannot delete a policy or unbind a key back to marketplace-only routing.
- Cached marketplace-only decisions can take up to 5 seconds to see a new binding. Calls already dispatched can finish on their pinned revision.
- Workspace bindings use the identity API.
Policy fields
| Field | Behavior |
|---|---|
models | 1 to 100 exact IDs. Every policy that applies must allow the requested model. |
connections | Up to 8 BYOK connection UUIDs that your org owns, in order. |
house_deployments | Up to 8 marketplace deployment IDs. |
funding: "byok_only" | The default. Needs connections. Forbids marketplace deployments. |
funding: "house_only" | Needs marketplace deployments. Forbids connections. |
funding: "byok_with_house_fallback" | Needs both. Marketplace deployments are always the last phase. |
allow_fallbacks | Default true. false keeps only the first eligible route, before health filtering. |
max_attempts | Integer 1 to 8. Default 4. |
timeout_ms | Admission and generation deadline, 1,000 to 600,000 ms. Default 450,000. |
regions, zdr, data_collection | Hard restrictions, checked against provider facts that RouterPlus operators record. A route with no recorded fact is refused. |
Fallback
- Under a policy, automatic fallback stays within the first selected provider label.
- You can authorize and select both OpenAI and Azure. A failed OpenAI call does not switch to Azure on its own.
- RouterPlus does not decide that two models are the same. It rejects
attest_equivalence:true. - Azure deployment mappings are your declarations.
- When fallbacks are off, an unavailable first route does not authorize a fallback.
- No retry crosses the streaming commit boundary or a content-policy refusal.
How restrictions combine
- The restrictions in force are the intersection of the org policy, workspace policy, key policy or binding, the server catalog and the request. An empty intersection refuses the request. Lower limits win.
- Order: request connection preference, then provider preference, then saved order, then deployment ID as a stable tie-breaker.
- With mixed funding, marketplace deployments come after every BYOK route.
Deadline
timeout_ms covers admission and generation after planning, including active streams. Request upload, policy and price reads, and the final billing settlement are separate phases. A timeout never skips billing settlement. A reservation that arrives after the deadline is released, and RouterPlus never dispatches it.
Request controls
The inference provider object accepts:
{
"only": ["openai"],
"ignore": [],
"order": ["openai"],
"connections": ["CONNECTION_UUID"],
"connection_order": ["CONNECTION_UUID"],
"funding": ["byok"],
"allow_fallbacks": false,
"require_parameters": true
}only, ignore and order name route labels: marketplace anthropic and openai, and a BYOK connection's profile (openai, anthropic, azure, bedrock). A route label keeps that meaning even when its route does not serve the model. Any other label matches no route. It selects, orders or skips nothing, and an only list with no route label leaves no route.
On POST /v1/decisions the labels are the decision providers:
typesafefor Jevbespokelabsfor the Bespoke Nimble modelsworkers-aifor Clef and Clef-flashrouterplusfor Decider 2B and Kev 4Bperplexity-decisionsfor Perplexity Decider v1 27Bopenai-decisionsfor GPT-6 Luna Decisionslevantofor Sagefastinofor GLiNER-2.5-Decide
Clef's label is workers-ai, not cloudflare: on POST /v1/decisions, cloudflare names no provider. Perplexity Decider's label is perplexity-decisions, not perplexity. GPT-6 Luna Decisions' label is openai-decisions, not openai, the label of the RouterPlus OpenAI chat route.
Other controls:
require_parameters: truerefuses a deployment that would drop one of your request fields. Without it, RouterPlus calls the deployment without that field.regions,zdranddata_collectionwork here too, as hard restrictions.sort(price,throughput,latencyorquality) andmax_priceapply to marketplace routes only. See Provider routing. The Agent integration guide covers how to keep a session's prompt cache warm.- Raw request keys and arbitrary destinations return 400.
Request preferences never grant connections, models, providers or funds that the saved policy does not allow. You cannot write the provider facts used for region and privacy restrictions. A restriction is not a residency or ZDR guarantee.
Explain a route
POST /v1/route takes {"model":"ID","provider":{...}} with the inference key. It returns, with advisory: true:
- the plan, catalog and policy IDs;
- the candidates in order, with their funding and pinned marketplace price IDs;
- the excluded routes, each with a reason;
- the time and source of the health data.
It makes no provider request, decryption or reservation. Health and authorization can change before the real dispatch.
Related endpoints:
GET /v1/modelsapplies the same restrictions. An optional URL-encoded JSONproviderquery parameter narrows the list.output_modalities=text,image,decisionsfilters by kind.- Token counting uses the same plan but needs an Anthropic route. It sends one count request and does not fall back.
GET /v1/generation?id=...shows each attempt'sroute_contextand fallback cause.- Policy requests return
x-tm-route-plan-idfor correlation.
Funding
- BYOK needs no marketplace credit.
- Marketplace fallback reserves credit only when the request reaches it, and charges under the standard pricing rules.
- Earlier marketplace holds stay until the request finishes, so fallback admission is conservative while settlements are pending.
- Each attempt pins its own funding and credential.
- RouterPlus does not know what a provider charges you on BYOK. Marketplace prices come from the model price list and are fixed before dispatch.
Azure/Foundry API-key connections
Create a connection with POST /api/connections. In the console, open Access > Provider connections.
{
"profile": "azure",
"models": ["your-public-model-id"],
"api_key": "YOUR_RESOURCE_API_KEY",
"endpoint_config": {
"resource": "your-resource-name",
"host": "foundry",
"api_version": "v1",
"deployments": {"your-public-model-id": "your-deployment-name"}
}
}hostisopenai({resource}.openai.azure.com) orfoundry({resource}.services.ai.azure.com). RouterPlus builds the public hostname. You cannot send a URL.- Every model you declare needs a deployment mapping.
endpoint_configcannot change. A change needs a new connection.- Validate the connection, then bind it to a key or include it in a policy. Rotation and revocation follow the connection lifecycle.
RouterPlus calls /openai/v1/chat/completions?api-version=v1, with the deployment name in the model field and the native api-key header. Validation calls the model-list endpoint and generates nothing. These shapes follow Microsoft's chat reference, models reference and v1 lifecycle guide.
| Supported | Not supported |
|---|---|
| API-key authentication, public v1 endpoints | Entra or workload identity, legacy dated APIs, preview versions, sovereign or private endpoints, Azure capacity or residency checks |
Validation confirms endpoint authentication only. It does not confirm deployment entitlement, model equivalence, quota or capacity.
Limits
- Shared admission needs declared quota pools and gateway limits.
- A full quota can skip a route that the policy allows. It never adds providers or marketplace funding.
- Model lists and route explanations do not reserve capacity.
- The attempt record stores at most 32 exclusion details, with
excludedTotalfor the full count. The catalog hash and the full route explanation keep the rest of the context.
For agents: /docs/routing-policies.md and /llms.txt