Pricing & billing
What a request costs and how you are billed.
You pay the provider's per-token price, published per model in USD per million tokens. RouterPlus adds no per-token markup and no fee line.
Every billed response has usage.cost: the amount debited from your balance. You can recompute it from the response.
One provider is our own: RouterPlus, which runs its decision models on its own GPUs. These models cost $0 for input and output (see Decision models).
In the console, open Billing > Credits to buy credits and see your balance.
Where prices live
The catalog is public and needs no key:
curl -s https://demo.routerplus.com/api/models.json \
| jq '.models[] | select(.id == "claude-sonnet-4-5").pricing_usd_per_million'{
"prompt": "3",
"cached_prompt": "0.30",
"cache_write": "3.75",
"completion": "15"
}Prices are decimal strings with up to six fractional digits, in USD per million tokens. They convert without loss to the ledger's unit, so billing uses no floating-point rounding.
| SKU | What it bills | Example (claude-sonnet-4-5) |
|---|---|---|
prompt | Non-cached input tokens | $3 / M |
cached_prompt | Prompt-cache reads | $0.30 / M |
cache_write | Prompt-cache writes | $3.75 / M |
completion | Output tokens, including reasoning unless a distinct rate is declared | $15 / M |
internal_reasoning | The reasoning part of output, when a provider declares a distinct rate | (none) |
A model that declares no cache or reasoning SKU bills those tokens at its base rate. cached_prompt and cache_write default to the prompt price. internal_reasoning defaults to the completion price. A missing price never means $0.
Image models
Image models bill on the same two SKUs, in USD per million tokens: prompt for the text you send, completion for the image that comes out. OpenAI reports image output in tokens, and the size and quality you ask for set the count. The per-image ceiling is the most output tokens one image can bill. It is max_output_tokens on the model page and in /api/models.json.
| Model id | Text in /1M | Image out /1M | Per-image ceiling |
|---|---|---|---|
gpt-image-1 | $5 | $40 | 6,240 tokens |
gpt-image-1-mini | $2 | $8 | 6,500 tokens |
gpt-image-1.5 | $5 | $32 | 6,500 tokens |
gpt-image-2 | $5 | $30 | 8,232 tokens |
gpt-image-2.5-flare | $5 | $30 | 8,232 tokens |
gpt-image-2.5-sunburst | $5 | $30 | 8,232 tokens |
Every output token bills at the image rate. This includes the text output tokens that gpt-image-1.5 counts in its output_tokens. See POST /v1/images/generations.
Models billed at the provider's reported cost
Some image and video models are billed at the provider's listed price for the render or the job, with no margin. RouterPlus reserves the model's ceiling (per image, or per second of video), charges the cost the provider reports, and releases the rest. The prices and ceilings are on POST /v1/images/generations and Videos.
Decision models
Decision models answer typed questions on POST /v1/decisions. They are priced in USD per million tokens, like every other model.
| Model id | Input /1M | Cached /1M | Output /1M | What the token counts are |
|---|---|---|---|---|
typesafe/jev-1.13 | $0.042 | – | $0 | The provider's input count |
bespokelabs/nimble-v4 | $0.04 | – | $0 | The provider's input count |
bespokelabs/nimble-v4-max | $0.09 | – | $0 | The provider's input count |
cloudflare/clef | $0.24 | – | $0 | The provider's input count |
cloudflare/clef-flash | $0.09 | – | $0 | The provider's input count |
routerplus/decider-2b | $0 | $0 | $0 | The provider's input count; an answer from its cache bills $0 |
routerplus/kev-4b | $0 | $0 | $0 | The provider's input count; an answer from its cache bills $0 |
perplexity/pplx-decider-v1-27b | $0.04 | – | $0 | The provider's input count, which holds the state once per question |
openai/gpt-6-luna-decisions | $0.10 | – | $0 | The provider's input count: the state once, and about 150 tokens for each question |
levanto/sage-1.2 | $0.05 | – | $0 | The provider's input count, which holds the state once per question |
scaledown/classify-1 | $0.05 | – | $0 | The provider's input count, summed over its questions (each one is a call) |
fastino/gliner-2.5-decide | $0.03 | – | $0 | Fastino's prompt_tokens |
Output is free on every decision model. Each model is billed on its provider's input count at the provider's price, with no markup, unless its section below says otherwise.
Bespoke Nimble
- $0.04 per million input tokens for Nimble v4, $0.09 for Nimble v4 Max.
- Bespoke counts the state and the questions once per call.
- A three-question call of 178 input tokens costs $0.000007 on Nimble v4 and $0.000016 on Nimble v4 Max.
bespokelabs/nimble-latestis in no list. It bills at $0.04 per million input tokens, Bespoke's price fornimble-latest, whichever model Bespoke picks for it.
Clef and Clef-flash
- $0.24 and $0.09 per million input tokens. Cloudflare reports
output_tokens: 0. - Cloudflare bills Workers AI in neurons, at $0.011 per 1,000 neurons. Its price page lists Clef at 21,818 neurons ($0.24) and Clef-flash at 8,182 neurons ($0.09) per million input tokens.
- A call of 400 input tokens costs $0.000096 on Clef and $0.000036 on Clef-flash.
Decider 2B and Kev 4B
Decider 2B and Kev 4B are RouterPlus's own models, on RouterPlus's own GPUs. RouterPlus charges nothing for them.
- Input, cached input and output are free.
usage.costis0on every call. - RouterPlus still reports its input count, which is at most the model's context. A long input that Decider 2B (25,600 tokens) cuts counts only the tokens the model read.
- A free call is still metered, counted against your limits and its pool, and recorded in
GET /v1/generation. It still needs an organization with credit. - RouterPlus answers an identical request from its cache for 600 s.
Perplexity Decider v1 27B
- $0.04 per million input tokens.
- Perplexity runs one prompt for each question, and each prompt holds the whole state.
- Five questions about a state of 1,843 tokens bill 9,215 input tokens, $0.000368.
- One call with many questions still saves round trips.
GPT-6 Luna Decisions
- $0.10 per million input tokens. OpenAI reports
output_tokens: 0. - It bills at its list price: no discount applies to it today.
- OpenAI bills the state once per call. It runs a prompt for each question, so each question adds about 150 input tokens. One yes/no about a two-character state billed 156 tokens, and five billed 760.
- A three-question call (a choice, a score and a yes/no about a short complaint) billed 396 input tokens, $0.000039.
- One call with many questions saves round trips and the state's tokens. The questions' tokens stay the same.
- A question that OpenAI declines (its answer is
{"type": "refusal"}) is billed too. - The listing's context is 272,000 tokens. Up to there, OpenAI's listed price holds. OpenAI bills input above it at twice the rate.
GLiNER-2.5-Decide
- $0.03 per million input tokens.
usage.input_tokensis Fastino'sprompt_tokens.usage.output_tokensis itscompletion_tokens.- A call of 1,000 input tokens costs $0.00003.
Sage
- $0.05 per million input tokens.
- Sage reads and bills the state once per question, like Perplexity Decider.
The decisions discount
A discount can apply to decision models: a percent off the charge of every decision model, or of some of them, each at its own percent. It applies to every key, the Playground's included. It does not change the list price, and it can change or end.
A discounted model's page and directory row show the percent beside the struck list price. Its row in /api/models.json has discount_percent. Every discounted response says what applied:
| Where | What it shows |
|---|---|
usage.cost | What you paid, after the discount |
usage.cost_before_discount | The charge at the list price |
usage.discount_percent and the x-tm-discount-percent header | The percent taken off |
cost_usd in GET /v1/generation | What you paid, after the discount |
inference_cost_usd in GET /v1/generation | The cost at the list price |
- The discounted charge is the list charge × (100 − percent) / 100, rounded down to the micro-dollar.
- With no discount, the three discount fields are absent and
usage.costis the list charge. - A discount needs an organization with credit. With a balance of $0, a discounted request gets
429 insufficient_quota, as any request does, even at 100 %.
A discount can cover a model whose list price is already $0 (Decider 2B and Kev 4B today). Then the discount has nothing to take off: usage.cost and usage.cost_before_discount are both 0. The gateway still reports usage.discount_percent and the header, and /api/models.json still carries discount_percent on its row, so one reader works for all twelve models. The model's page, the directory and the Playground show no "N % off" beside a $0 price, because the model is free, not discounted.
The math: integer micro-USD
All money math is in integer micro-USD (millionths of a dollar). A published price of "2.50" becomes 2500000 micro-USD per million tokens. Two rounding rules apply:
- Reserve rounds up (ceiling), so the hold is conservative.
- Settlement rounds down (floor).
The settlement formula:
non_cached_input = max(0, input_tokens − cached_tokens − cache_write_tokens)
reasoning = clamp(reasoning_tokens, 0, output_tokens)
plain_output = output_tokens − reasoning
cost_micro = floor((
non_cached_input × prompt_per_M
+ cached_tokens × cached_prompt_per_M
+ cache_write_tokens × cache_write_per_M
+ plain_output × completion_per_M
+ reasoning × reasoning_per_M
) / 1,000,000)Each *_per_M is the integer micro-USD price. usage.cost is this number divided by 10⁶.
Reserve, then settle
Every billed request has four steps:
- 01Reserve. Before RouterPlus contacts a provider, the gateway holds an estimate of the highest cost.
- Input (chat surfaces): one token per byte of the request body, plus 65,536 tokens for each image or document part. An image sent inline counts the 65,536 only, not its base64 bytes.
- Output: all of your
max_tokens(ormax_completion_tokens, ormax_output_tokenson POST /v1/responses). - No output limit: the hold covers at most 32,768 output tokens, and the model gets its own maximum. On the chat surfaces, the gateway writes that maximum into the request, lowered when needed so that the input and output fit the model's context window (see POST /v1/chat/completions). On
/v1/responsesthe gateway adds none, and OpenAI applies the same maximum. - Rate: each side is priced at the model's highest rate for that side (cache writes and reasoning, when they cost more than plain input or output). The sum rounds up to micro-USD.
- Web search: a request with a web search tool also holds the search fee for the tool's
max_usessearches (at most 20), or for 5 when it sets none (see Web search). - Images: on
/v1/images/generations, the output is reserved atn× the model's per-image ceiling (notmax_tokens), and the input at the prompt bytes ÷ 4.
- 02Dispatch. The request goes to a provider. Prices are pinned at this moment (see Price changes).
- 03Settle. When the attempt finishes, RouterPlus prices the provider-reported token counts with the formula above and rounds down. You pay that amount, also when it is more than the hold (a long answer to a request without a limit).
- 04Release. RouterPlus releases the hold in full.
When usage is not reported
An attempt can end before the provider reports usage: you cancelled it, or the provider failed after your answer started. You then pay for the input and for the output already streamed to you. RouterPlus does not charge the hold.
- Input: the provider's own count when it sent one. Claude sends it when its answer starts, with its cache reads and writes, each at its own price. Otherwise, the request's likely input (its size at four bytes a token, with 1,600 tokens for each image or document part) at the plain input price.
- Output: what was streamed to you before the end (text, tool-call arguments and any reasoning you received), at four characters a token. If you cancel before the first token, or the call does not stream, the output part is $0.
A model that hides its thinking (the Claude 5 models, by default) streams nothing while it thinks. A cancel during that time costs the input only. Such a charge has the provenance estimated.
You pay the reserved maximum in two cases:
- The gateway stopped mid-request and cannot observe the outcome (
unknown_after_crashin GET /v1/usage & /v1/generation), because the provider may have billed the call. - An attempt completes and the provider reports no usage. This is rare.
Refusals before dispatch
| Cause | Refusal |
|---|---|
| Balance too low. Your balance must cover every reservation your org has in flight, this one included. | 429 with error_type: insufficient_quota (the OpenAI shape SDKs handle; native type billing_error on the Anthropic surface) |
| Monthly spend cap hit. Caps are org-wide and per key, per UTC calendar month. The strictest wins. | The same 429 insufficient_quota, with the reset time in the message and in the x-tm-cap-reset header |
| A rate limit hit. The key's RPM, a shared limit of the organization, or the provider's pool. | 429 with error_type: rate_limit and retry-after |
Errors & remediation gives the fix for each.
Failed images cost nothing
A failed attempt, a response over the 32 MiB cap, and a 200 with no decodable image all settle at zero. RouterPlus never returns or bills a partial image.
If you hang up mid-render, the render still finishes upstream. That attempt settles the provider-reported usage: never the reservation, and never $0.
The cost on the wire: usage.cost
Every billed response has usage.cost (USD, a JSON number):
- Non-streaming: in the response body's
usage, on both surfaces. - Streaming, OpenAI surface: in the final usage chunk, before
[DONE]. - Streaming, Anthropic surface: in the
message_deltausage at stream end.
curl -s https://dev2-api.routerplus.com/v1/chat/completions \
-H "Authorization: Bearer $TM_API_KEY" -H "content-type: application/json" \
-d '{"model":"claude-sonnet-4-5","max_tokens":350,"messages":[{"role":"user","content":"hello"}]}' \
| jq .usage{
"prompt_tokens": 1200,
"completion_tokens": 350,
"total_tokens": 1550,
"prompt_tokens_details": { "cached_tokens": 800, "cache_write_tokens": 0 },
"cost": 0.00669
}import os
from openai import OpenAI
client = OpenAI(base_url="https://demo-api.routerplus.com/v1", api_key=os.environ["TM_API_KEY"])
r = client.chat.completions.create(
model="claude-sonnet-4-5", max_tokens=350,
messages=[{"role": "user", "content": "hello"}],
)
print(r.usage.model_dump()["cost"]) # the ledger debit, in USDimport os
import anthropic
client = anthropic.Anthropic(base_url="https://demo-api.routerplus.com", api_key=os.environ["TM_API_KEY"])
msg = client.messages.create(
model="claude-sonnet-4-5", max_tokens=350,
messages=[{"role": "user", "content": "hello"}],
)
print(msg.usage.model_dump()["cost"])usage.cost is the full request debit, not the serving attempt's share. If a provider failed mid-prompt and the gateway failed over before your answer started, the number includes the tokens the failed attempt used. The per-attempt breakdown is at GET /v1/generation.
Usage reporting is always on:
- Streams and non-streams both carry usage.
- The gateway requests usage from the provider whatever you send, because RouterPlus cannot recompute unreported usage.
- Only an explicit
stream_options.include_usage: falsechanges anything. You are billed the same, but no usage chunk is written to you.
On the Anthropic surface, a stream that fails after your answer started has no place for usage outside message_delta. Its terminal error event carries no cost. Read those costs from /v1/generation. The OpenAI surface sends any known usage and cost before its terminal error.
Cache reads and writes
Cache tokens bill at their own rates on both surfaces. Both surfaces report the split:
| Concept | OpenAI surface | Anthropic surface | Billed at |
|---|---|---|---|
| Non-cached input | prompt_tokens minus the two details below | input_tokens | prompt |
| Cache reads | prompt_tokens_details.cached_tokens | cache_read_input_tokens | cached_prompt |
| Cache writes | prompt_tokens_details.cache_write_tokens | cache_creation_input_tokens | cache_write |
| Output | completion_tokens | output_tokens | completion |
On the OpenAI surface, prompt_tokens includes cache reads and writes. Billed responses always have prompt_tokens_details with both fields, set to zero when the provider reports none. Stream and non-stream usage have the same shape.
On Claude, a cache write costs 1.25 times the input price (cache_write). A cache read costs a tenth of it or less (cached_prompt).
When an agent sends a conversation with tools or earlier turns and no cache marks of its own, the gateway turns on Claude's automatic caching for it. The first turn pays a cache write on its prompt. The next turns read that prompt at the cache price.
- The
x-tm-auto-cacheresponse header says whether automatic caching applied. - The request header
x-tm-auto-cache: offturns it off. - Wire compatibility has the rules.
Web search
RouterPlus bills a web search that the provider runs for the model at the provider's price per search, plus the tokens:
| Tool | Where | Price |
|---|---|---|
Anthropic's web search server tool (web_search_20250305 and later) | Claude models on POST /v1/messages | $10 per 1,000 searches ($0.01 a search) |
| Anthropic's web fetch server tool | Claude models on POST /v1/messages | No fee: only the tokens of the fetched page |
OpenAI's hosted web_search tool | OpenAI models on POST /v1/responses | $10 per 1,000 calls |
OpenAI's older web_search_preview tool | GPT-4o, GPT-4o mini and GPT-4.1 mini on POST /v1/responses | $25 per 1,000 calls |
- Each search counts once, whatever the number of results. A failed search is not billed.
- The pages a search returns become input tokens at the model's input price, as on the provider's own API. On a stream, the input is the count at the end of the turn.
- The fee is part of
usage.cost, and ofcost_usdin GET /v1/usage & /v1/generation. There, each attempt also showsserver_tool_use(web_search_requests,web_fetch_requests) andserver_tool_fee_usd. On/v1/messages, the answer'susage.server_tool_use.web_search_requestsalso gives the number of searches. - While the request runs, the hold includes the fee for each web search tool's
max_usessearches (at most 20), or for 5 searches when the tool sets nomax_uses. A tool of your own namedweb_searchholds nothing. - If the model searches more often than the hold allows, you pay for every search it made. The hold limits what is set aside, and the charge has no such limit.
- On your own provider connection (BYOK), RouterPlus charges no fee. The provider bills you.
Anthropic's server tools, web search included, work only for Claude models on POST /v1/messages. Claude Code calls them there. See POST /v1/messages.
Reasoning tokens
Reasoning tokens are part of output. They are never billed on top of it.
- The settlement math splits them out and prices them at the model's reasoning rate.
- Today every cataloged model prices reasoning equal to
completion, so the split changes nothing until a provider declares a distinct rate. - The OpenAI surface reports them in
completion_tokens_details.reasoning_tokens. The Anthropic surface does not report them separately.
Price changes: frozen snapshots
You pay the price in effect at dispatch time.
- Price rows are append-only. A change is a new effective-dated row, never an edit.
- The row in effect when your request is reserved is pinned into the reservation and written onto every attempt's ledger row.
- A price change published while your request is in flight does not affect it.
- Past attempts always settle, and audit, against the prices they were dispatched under.
Paid credits and purchase matching
Create an account at Sign up, complete Clerk authentication and email verification, and save your first API key. Signup and card verification alone do not grant credit. Existing customers keep their balance and API keys.
Standard credit purchases start at $10 in Billing. The payment adds the amount you buy as paid credit. Your balance is the sum of credit ledger entries minus settled spend.
If purchase matching is offered for your account, Billing shows the cap and remaining matching credit.
Only eligible paid purchases receive a match, when the offer is available in Billing.
- New matching offers have a lifetime maximum of $100 per account across eligible purchases. Billing shows the offer and the matching credit left for your account.
- Matching credit is promotional and shows as its own ledger entry.
- Refunds and chargebacks reverse the matching credit. A partial refund reverses its proportional matching credit.
- Adding a card without a purchase does not earn a bonus.
- Existing trial and card-verification grants stay in the ledger. Those signup offers are no longer available.
Before an organization buys credit, its customer keys share the trial rate of 20 requests a minute. A purchase lifts that cap. Each key then has its own ceiling (300 for a console key). RouterPlus can also limit past trial credit when it detects unusual usage. Contact support if that happens. See Rate limits & spend caps.
Worked example
A claude-sonnet-4-5 request reports 1,200 prompt tokens (800 of them cache reads, no cache writes) and 350 completion tokens:
non-cached input: 400 × 3,000,000 = 1,200,000,000
cache reads: 800 × 300,000 = 240,000,000
output: 350 × 15,000,000 = 5,250,000,000
─────────────
sum / 1,000,000 (floor) = 6,690 micro-USDusage.cost in the response is 0.00669. The attempt's cost_usd in GET /v1/usage & /v1/generation is the same number, from the same computation.
Worked example: an image
A gpt-image-1 request for two medium 1024×1024 images (n: 2) with a 12-token prompt estimate. Text in is $5 / M, image out is $40 / M, and the per-image ceiling is 6,240 tokens.
The reservation, before RouterPlus contacts a provider:
prompt estimate: 12 × 5,000,000 = 60,000,000
output ceiling: 2 × 6,240 × 40,000,000 = 499,200,000,000
───────────────
ceil(sum / 1,000,000) = 499,260 micro-USDThe provider reports 12 input tokens and 2,112 output tokens (1,056 per image). Settlement:
input: 12 × 5,000,000 = 60,000,000
output: 2,112 × 40,000,000 = 84,480,000,000
──────────────
floor(sum / 1,000,000) = 84,540 micro-USDusage.cost in the response is 0.08454. RouterPlus releases the hold in full, and you pay the settled amount.
For agents: /docs/pricing.md and /llms.txt