The contract: every nRouter request produces exactly one settled cost. Your application reads it off the response, your credit ledger is moved by it, and your dashboard aggregates it. When the cost cannot be determined, the cost header is absent and the call is marked unpriced — it is never reported as
$0.
Cost tracking sounds like a reporting problem. It is actually a consistency problem, and it goes wrong in a very specific way: three systems each compute the price of the same call, they disagree by a fraction of a cent, and six weeks later somebody has to explain to a customer why the invoice and the dashboard tell different stories.
This post is how we avoid that, written from the outside in — what you can observe, what is guaranteed, and where the guarantees stop.
The problem in one request
One chat completion, routed through the gateway to a flagship model:
POST https://api.nrouter.ai/v1/chat/completions
Authorization: Bearer $NROUTER_API_KEY
model: gpt-5.5
prompt: 4,000 tokens in, 900 tokens outFour different systems now want to know what that call cost:
- Your application, so it can attribute spend to the feature or customer that triggered it.
- Your credit balance, so the right amount comes off it.
- Your dashboard, so the monthly chart is right.
- You, later, reconciling against what the provider actually billed.
If each of those four derives the number independently, they will not agree. Not because anyone is wrong, but because they will round differently, cache the rate card at different moments, and disagree about how cached input tokens price. The disagreement is small, permanent, and impossible to explain.
Why the naive approach breaks
The version most teams build is a price table in the application and a multiplication at the call site:
cost = tokens_in * RATE_IN[model] + tokens_out * RATE_OUT[model]It works on day one with two models and one provider. It breaks on the following inputs, all of which are ordinary:
- A model whose rate changed this morning. Your table is a deploy behind. The ledger and the invoice diverge silently, and nothing surfaces the drift because both numbers look plausible.
- A response with no usage block. Some failure modes and some streaming
edge cases return without token counts. A naive multiplication yields
0, and a zero-cost call is the single most dangerous artifact in this whole domain — it looks like a cheap request instead of an unmeasured one. - Cached input tokens. They price at their own rate. A table keyed only on input and output silently overcharges or undercharges every cached call.
- A non-text modality. An image generation priced per image, a transcription priced per second of audio, and a video priced per second of output do not fit the two-rate shape at all.
- A retry. The call failed at one provider and succeeded at the next. That is two upstream calls and, if you are not careful, two bills for one customer request.
Every one of those is a normal Tuesday. The naive design is not wrong so much as it is a table that must be perfect forever, maintained by people who have other work.
Why provider pricing refuses to normalize
The reason a gateway earns its keep here is that the pricing shapes genuinely differ. This is not a tidiness problem you can refactor away.
| Pricing shape | Where you meet it | What breaks a naive table |
|---|---|---|
| Per input/output token | Most chat and completion endpoints | Separate rates per direction, changed independently |
| Cached input tokens | Prompt-caching on several providers | A third rate that only applies to part of the input |
| Per image | Image generation | Quality and size tiers, not tokens |
| Per second of audio | Speech and transcription | Duration, not tokens, and rounding rules differ |
| Per second of video | Video generation | Long-running, priced on output duration |
| Provisioned capacity | Reserved capacity and dedicated throughput from the major clouds | You bought capacity, not calls; per-call cost is derived |
| Batch discounts | Several providers' batch endpoints | Same model, different rate, different latency contract |
A gateway that only understands per-token pricing is a gateway that quietly reports the wrong number for everything else. See the vendor pages in Sources for the current shapes; they move.
The mechanism: one authoritative cost per request
The design rule is short. The cost of a request is computed once, at the gateway, after the call completes, from the usage the provider actually reported. Everything else reads that value.
Concretely, the contract has five parts:
- One producer. The gateway is the only thing that computes a request's cost. Your application does not recompute it; the ledger does not recompute it; the dashboard does not recompute it.
- Provider-reported usage is the input. Token counts, image counts and durations come from the provider's own response, not from a client-side estimate.
- The result is one of two states, never three. Either the cost is known and reported, or it is unpriced. There is no third state where an unknown quietly becomes zero.
- The ledger moves by that value and nothing else. Which is why the number on your response and the number on your credit ledger agree by construction rather than by reconciliation.
- The platform fee is not part of it. The fee is charged when you buy credits, on top of the amount you load. Per-request settlement is pure provider cost.
Unpriced is not zero
When the cost of a call cannot be determined — no usage reported, or a model
with no price on your catalog — the response carries no cost value at all. The
x-nr-request-cost header is absent, and x-nr-cost-status says the call
was unpriced. Treat an absent header as "unknown, investigate", never as
"free". A confident $0 is how an unmeasured call disappears from a
cost report, and it is the exact defect this design exists to prevent.
Reserve, forward, settle, release
Knowing the cost after the fact is not enough on its own, because your balance has to survive concurrency. Ten simultaneous requests against $1.00 of headroom must not all be approved.
- Reserve — before anything goes upstream, a hold is placed against your
balance for the maximum plausible cost of the call, atomically. Available
balance is
balance − reserved, so concurrent requests cannot all claim the same headroom. Not enough available? You get a402before the provider call, not after. - Forward — the request goes to the provider. Your held amount is untouchable by other requests for the duration.
- Settle — the call returns, the real cost is known, the hold settles at that amount and the unused remainder is released back to available.
- Release — if the request never reached a billable outcome (routing failure, upstream connection failure, upstream non-2xx, timeout), the full hold is released. Every failure path releases; a leaked hold is your own money frozen.
The full treatment, including why a hold survives a retry, is in Reserve-and-Settle.
Worked example: one request through the ledger
Take a single completion. The gateway reports its settled cost as $0.0428, and
your balance was $12.40 with $0.90 already held by other in-flight requests.
| Step | Balance | Reserved | Available | Note |
|---|---|---|---|---|
| Before | $12.4000 | $0.9000 | $11.5000 | two other calls in flight |
| Reserve | $12.4000 | $1.0500 | $11.3500 | $0.15 held — a ceiling, not a guess at the answer |
| Settle | $12.3572 | $0.9000 | $11.4572 | actual $0.0428 deducted, $0.1072 released |
Three things to notice in that table.
The reservation is bigger than the cost, and that is correct. A hold is a ceiling. Its job is to make overspend impossible, not to predict the answer. The remainder comes straight back at settle.
The displayed number is available, not balance. $11.4572, not $12.3572.
Showing raw balance while holds are outstanding is how a customer gets a 402
on a screen that says they have money.
Nothing in the row is a fee. The 4% platform fee was charged when credits were purchased, not on this request.
Now the purchase side, using the documented numbers from pricing:
| Plan | You load | Fee charged on top | Card total | Lands on balance |
|---|---|---|---|---|
| Pay as you go | $100.00 | $4.00 (4% of the credits) | $104.00 | $100.00 |
| Pro ($50/mo or $500/yr) | $100.00 | 0% = $0.00 | $100.00 | $100.00 |
The fee is charged on top and never deducted from the credits you loaded, so $100 loaded is always $100 spendable. It is a flat 4% of the credits, which is why the fee on $100 loaded is exactly $4.00. The minimum credit purchase is $5 (charged $5.20 on Pay as you go), and amounts above that floor are yours to pick rather than a menu of fixed options.
That table is also the whole breakeven calculation. The fee on a month's provider spend is 4% of that spend, so Pro's $50/mo pays for itself once that fee passes $50 — exactly $1,250/mo of spend. On the annual plan ($500/yr, about $41.67/mo) the crossover is around $1,042/mo. The long version is in From Credits to Pro.
Edge cases we had to decide
-
When the provider returns no usable usage, we settle at the reserved amount and mark the call unpriced, because releasing would make the request free. A call that reached the provider consumed tokens somebody is paying for. Releasing the hold would hand out an unmeasured request at no charge and hide it from every cost report. Settling at the hold is conservative and visible; the unpriced marker is the flag that says "reconcile this one".
-
When a post-call guardrail blocks the response, we settle rather than release, because the provider already generated and billed the tokens. The block protects your users; it does not un-bill the upstream call. Releasing here would mean every blocked response was a free request, which is an obvious abuse lane.
-
When a call is retried onto a fallback provider, the customer request holds one reservation, not one per attempt, because a retry is our reliability mechanism and not a second purchase. The full chain behaviour is in Provider Fallback Chains.
-
When a provider serves part of a prompt from its own prompt cache, the saving shows up as a genuinely cheaper request rather than as a special zero, because a zero and a cache hit look identical in a report and only one of them is good news. Cached input tokens price at their own published rate; when a provider gives no separate cached rate, they price at the ordinary input rate, never at zero.
-
When a model on your catalog has no usable price, we do not enable it at a price of zero. An unpriced model is reported as unpriced, and a price of zero on an enabled model is treated as missing data rather than as a free lunch. The reasoning is in Cost Honesty.
What you see from the outside
Everything above is observable without asking us anything.
- On the response —
x-nr-request-costcarries the settled cost, andx-nr-cost-statussays whether it is exact or unpriced. When the cost is unknown, the cost header is not present at all.x-nr-request-idgives you the handle to correlate with your own logs. - On the ledger — one movement per settled request, plus separate rows for purchases, bonuses and reversals. It reconciles to the balance by construction; the reading guide is How to Read Your LLM Credit Ledger.
- On the dashboard — per-model, per-key and per-team breakdowns, daily and monthly trends, and CSV export, all aggregating the same settled values. See Analytics.
- In your own tags — attribute spend by feature, customer or environment with cost attribution tags, so the number you read is the number you can bill on.
Everything is on every plan. Guardrails, A/B tests, prompt management, evals and per-team budgets are not gated — plans vary the platform fee and the rate limits, never the feature set.
Limits
- We report cost, we do not predict it. A reservation is a ceiling, not a forecast. If you want an estimate before you call, that is the cost calculator, and it is an estimate.
- Provisioned capacity is derived, not metered. When a model runs on reserved capacity you bought elsewhere, the per-call figure is a derivation from that arrangement, not a meter reading from the provider.
- Provider invoices can still differ at the margin. Rounding, currency conversion and the provider's own billing period boundaries are not ours to control. The number we report is the number we settle and the number we charge; reconcile against the provider's console for the rest.
- There is no BYOK path. You bring an nRouter key and credits; we hold the provider credentials. That is what makes one authoritative cost possible at all, and the trade-off is spelled out in Why We Don't Do BYOK.
- Unpriced calls need a human. The unpriced marker is a signal, not a resolution. If you see them recurring on a model you rely on, tell us.
Try it
Send one request and read the headers yourself:
curl -i https://api.nrouter.ai/v1/chat/completions \
-H "Authorization: Bearer $NROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-5.5","messages":[{"role":"user","content":"hello"}]}'Look for x-nr-request-cost and x-nr-cost-status in the response headers,
then open your ledger and confirm the same figure moved your balance. Two places,
one number — if they ever disagree, that is a bug worth an email.
Browse what is currently routable on models, check the fee on pricing, and if you do not have an account yet, sign up — a card is required and a $5 minimum charge is taken, with the platform fee on top.
See also
- Reserve-and-Settle: Never Overspend a Credit Balance — the concurrency mechanism this post summarizes in four steps, in full.
- How to Read Your LLM Credit Ledger — row by row, including holds, releases and reversals.
- Cost Honesty: We Read the Number, We Don't Invent It — why an unknown cost is reported as unknown rather than as zero.
- Cost vs Usage: Finding the Quietly Expensive Model — what to do with the settled numbers once you have a month of them.
- Attribute LLM Spend by Team, Customer, and Feature — turning one cost per request into per-customer billing.
- Multimodal Cost Safety: An Unpriced Image Call Is Never $0 — how the non-token pricing shapes are handled without a zero slipping through.
- Pricing — the canonical fee table and the $5 minimum purchase.
Sources
Verified 2026-05-05. Provider pricing shapes change; each claim about a vendor's pricing model traces to that vendor's own page below. If one has moved and we have not refreshed, email hello@nrouter.ai and we will re-check.
- OpenAI pricing: openai.com/api/pricing
- Anthropic pricing: anthropic.com/pricing
- AWS Bedrock pricing: aws.amazon.com/bedrock/pricing
- Google Vertex AI generative-AI pricing: cloud.google.com/vertex-ai/generative-ai/pricing
- Azure OpenAI provisioned throughput: learn.microsoft.com
- nRouter pricing and platform fee: nrouter.ai/pricing
- nRouter model catalog: nrouter.ai/models


