By default the router tries our listings in routing order and fails over before the first byte — never mid-answer. Prices are each provider's own list price; you pay $0.24 in / $0.00 out per 1M, whichever runs the request. Uptime is our own measurement; an hour stays grey until it has a sample. Open the row for the provider's specs and policies.
curl https://api.routerplus.com/v1/decisions \
-H "Authorization: Bearer $TM_API_KEY" -H "content-type: application/json" \
-d '{"model":"cloudflare/clef",
"state":"Help! My payouts have been failing for 3 days.",
"questions":{
"team":{"type":"choice","instructions":"Which team should handle this?",
"criteria":{"billing":"Payments and refunds","technical":"Bugs and outages"}},
"urgent":{"type":"noul","instructions":"Is this urgent?"}}}'
# answers.team.choice, answers.team.probabilities, answers.urgent.noulimport os, httpx r = httpx.post("https://api.routerplus.com/v1/decisions", headers={"Authorization": f"Bearer {os.environ['TM_API_KEY']}"}, json={"model": "cloudflare/clef", "state": "Help! My payouts have been failing for 3 days.", "questions": {"urgent": {"type": "noul", "instructions": "Is this urgent?"}}}) r.json()["answers"]["urgent"]["noul"] # probability of yes
const r = await fetch("https://api.routerplus.com/v1/decisions", { method: "POST", headers: { authorization: `Bearer ${process.env.TM_API_KEY}`, "content-type": "application/json" }, body: JSON.stringify({ model: "cloudflare/clef", state: "Help! My payouts have been failing for 3 days.", questions: { urgent: { type: "noul", instructions: "Is this urgent?" } } }), }); const { answers } = await r.json(); // answers.urgent.noul: probability of yes
| prompt | $0.24 |
| completion | $0 |
Every billed response carries usage.cost — recompute your bill from the wire.
An hour counts at the best provider's uptime: a request goes to another provider when one fails. Grey hours have no sample yet.