Routing policy
A policy decides which offers may serve a call and how they're ranked. It can be set four ways, and the four are merged so that they only ever tighten.
The four ways
1. Key policy
Set in the dashboard when creating or editing a key. Applies to every request made with that key.
2. Policy path
Prefix the API path with /p/{policy}, tokens joined with +. Works for /v1/… and /anthropic/….
http://localhost:8787/p/min60+zdr+eu+verified/v1| Token | Meaning |
|---|---|
min{N} | Minimum discount vs list price, in percent — e.g. min60 |
zdr | Zero-data-retention offers only |
tee | Attested TEE offers only (coming soon — no offer qualifies yet) |
eu / us / apac | Region |
verified / probed | Minimum verification tier |
fast | Objective latency |
cheap | Objective price |
reliable | Objective reliability |
value | Objective value |
mask | Mask secrets and PII before forwarding |
cache | Use your opt-in response cache |
hedge{ms} | Hedge if no first token within ms — e.g. hedge800 |
max{usd} | Maximum output price in $ per 1M — e.g. max0.5 |
An unknown token returns 400 invalid_request.
3. Headers
X-Thin-Min-Discount: 60
X-Thin-Objective: latency
X-Thin-Region: eu
X-Thin-ZDR: on
X-Thin-Verification: verified
X-Thin-Mask: on
X-Thin-Cache: on
X-Thin-Hedge-Ms: 800
X-Thin-Max-Output-Price: 0.54. Body field
A thin object in the request body. It is stripped before the request is forwarded.
"thin": {
"objective": "price | latency | reliability | value",
"price_tolerance_pct": 10,
"min_discount": 60,
"max_input_price_micro": 300000,
"max_output_price_micro": 900000,
"verification": "probed | verified | attested",
"zdr": true,
"tee": false,
"regions": ["eu"],
"sellers": ["s_7f3a"],
"sellers_blocked": ["s_19cc"],
"max_latency_ms": 2000,
"hedge_after_ms": 800,
"mask": true,
"cache": true,
"cache_ttl_s": 3600,
"rescue": true,
"max_attempts": 3
}Defaults and precedence
- Defaults: objective
price, verificationverified, rescuetrue,max_attempts3, price tolerance 0 forpriceand 25% for the other objectives. - The default tier applies only when no source names one, so a request may opt into
probedoffers. Once any source (for example your key) sets a tier, the strictest named tier wins. - Floors take the strictest value (highest
min_discount, lowest max price, highest tier). - Requirements add up: any source asking for ZDR, TEE or masking turns it on.
- Allow-lists intersect; block-lists union. A request can narrow a key's policy, never widen it.
Objectives
- price — cheapest eligible offer first.
- latency — fastest time-to-first-token within the price tolerance band.
- reliability — highest recent success rate within the band.
- value — price weighed against verification score and success rate.
price_tolerance_pct sets how far above the cheapest eligible price an offer may be and still be ranked by a non-price objective.
Seeing the decision
POST /v1/route/preview takes a chat request and returns the merged policy, the eligible offers in rank order and every rejected offer with its reason. Nothing is sent upstream and nothing is charged.
Rejection reasons
| Reason | Meaning |
|---|---|
unhealthy | Offer is failing health checks |
paused | Seller paused the offer |
verification_below_policy | Offer's tier is below your required tier |
not_zdr | You required ZDR |
not_tee | You required TEE |
region_excluded | Offer region not in your regions |
seller_excluded | Not in your sellers allow-list |
seller_blocked | In your sellers_blocked list |
below_min_discount | Discount vs list below your floor |
above_max_price | Price above your max input/output price |
latency_above_max | p50 time-to-first-token above max_latency_ms |
daily_cap_reached | Seller's daily cap is used up |
at_capacity | Seller's max concurrency reached |
outside_schedule | Outside the seller's selling windows |
context_too_small | Request won't fit the offer's context |
When nothing qualifies
If offers exist but your policy excludes them all, the call fails with no_eligible_offers and the error includes the rejected list. If no one sells the model, it's no_offers_for_model.
Per-key guardrails
- Budgets:
budget_daily_microandbudget_monthly_micro; exceeding one returnsbudget_exceeded. - Model map: glob patterns mapping incoming model names to exchange models.
- Anomaly guard: if a key's spend over the last 10 minutes exceeds the larger of $5 and 10× its trailing 24-hour 10-minute average, the key is frozen (
key_frozen) and you're notified. Unfreeze it in the dashboard.