Skip to content

What a request costs

Integer micro-dollars, where the number comes from, and the three places you can check it.

6 min read

Micro-dollars

Every price, balance and charge in the system is an integer count of millionths of a dollar. One dollar is 1,000,000 micros. Nothing that touches money is ever a floating-point number, because a single token can cost around 0.00000002 USD and float addition over millions of requests drifts far enough to produce a balance nobody can reconcile.

You see both forms. cost_micros is the authoritative figure; cost_usd is the same number as a decimal, provided because a human reading a response should not have to divide by a million.

The arithmetic

Providers quote per million tokens. Your prompt, the part of it the provider served from its own cache, and the completion are each priced at tokens × price_per_mtok ÷ 1,000,000 at full precision, added together, and then rounded up to the nearest micro, once, over the whole request rather than once per part.

Rounding up rather than to nearest is a deliberate choice and it is worth at most $0.000001 per request, never in your favour. A micro is the smallest amount that can be billed at all, so the only question is who absorbs the fraction; rounding to nearest would have meant a request whose true cost is 0.4 micros billing nothing while the provider still charged us for it. Rounding each part separately, which is what the older wording described, threw away up to half a micro three times over.

Prompt tokens that the provider served from its own cache are priced separately when the route has a cached rate. The cached count is subtracted from the prompt count and charged at the lower rate, and the remainder at the full one. Charging the whole prompt at the full rate would over-bill every customer who benefits from Cache hitThe identical request was made recently, so the saved answer was returned. It cost nothing and arrived instantly., which is the entire reason the split exists.

There is no spread of ours on the token rate

The prices used here are what the route costs Multigrid, from the same catalogue rows GET /models serves. Where we hold a direct key with the provider (OpenAI, Anthropic, Groq, Together, DeepInfra) that is their published rate unchanged. Most of the catalogue is reached through OpenRouter instead, and we buy their credit at list plus 5.5%, so those rates carry that 5.5% inside them rather than behind them.

Multigrid takes its own percentage once, when you top up credit, as its own line on the receipt: never as a spread hidden inside a per-token rate.

When you are not charged

A cost of zero is always explained. The response carries a waived field naming the reason, and saved_usd showing what it would otherwise have cost.

ReasonDescription
byokYour own provider key paid for it, so the provider billed you directly and we take nothing. See bring your own key.
zero_completionThe model produced no text and called no tools. Billing a prompt that came back empty is billing for a failure, and from the outside you cannot tell a content filter from a model with nothing to say.
cache hitServed from your own response cache. Cost zero, saved_usd equal to what the original call cost.

A waiver covers the model’s tokens and nothing else. If a web-search plugin ran before the model did, that search was bought from a third party and is charged regardless, on top of the tokens, only on requests that ask for it. It is passed through at cost: $0.007 per search, flat, whether it returns one result or the maximum of ten. That is what the search engine charges us for the call, and it is taken from the cost the engine reports for your particular search rather than from a price list, so if it ever changes you are billed the new number and not our copy of the old one. The response splits the total under cost_breakdown so a charge with no tokens behind it is visible rather than surprising.

A stream you hang up on is charged for the tokens the provider produced before you disconnected. It generated them and billed us for them; aborting a stream is not a way to get free inference. Two details are worth knowing before you rely on that sentence.

Cancelling mid-stream is an estimate, not a count. The token counts arrive in the usage chunk, which is the last thing an OpenAI-shaped upstream sends, so a stream you cut short usually has none. We fall back to about four characters per token over what was actually delivered to you, bounded above by the max_tokens the request was gated against. That runs slightly in your favour on CJK and on code, and slightly against you on long common English words.

Opening a stream and never reading it is charged at the ceiling. If nothing consumes the body, there is no delivered text to measure, and the provider has still generated and billed us for the whole completion, so the charge falls back to the worst case the request was reserved against: your max_tokens, or the model’s entire output ceiling if you did not set one. On a large reasoning model that is a six-figure token count and a charge in the tens of dollars for a response nobody read. Set max_tokens, and read or cancel the streams you open.

Checking the number

Three ways, all reporting the same figure from the same row.

  • On the response. multigrid.cost_micros, or the X-Multigrid-Cost-Usd header. On a stream the cost is not known until the last token, so it rides the terminal chunk rather than a header.
  • Per request, afterwards. For the case where the response did not survive: a crashed client, a retry loop that discarded the body, a reconciliation weeks later.
  • Aggregated. The same numbers the Analytics page renders, so finance can pull them without screen-scraping a dashboard.
bash
curl "https://api.multigrid.ai/v1/generation?id=req_…" \
  -H "Authorization: Bearer $MULTIGRID_API_KEY"
bash
curl "https://api.multigrid.ai/v1/usage?days=30" \
  -H "Authorization: Bearer $MULTIGRID_API_KEY"

GET /usage takes days between 1 and 365 and returns totals, a daily series, and breakdowns by model and by provider, including saved_usd, byok_requests and cache_hits, so the difference between what you spent and what you would have spent is arithmetic you can check rather than a claim.

The ledger

Charges are append-only entries, one per billable request, each carrying the request id and a description naming the model and its token counts. A ledger row is never updated or deleted. A correction is a new row with the opposite sign, which is what makes an invoice defensible.

Your balance is a cache of the sum of that ledger, written in the same statement as the row it comes from. An audit script re-derives every balance and exits non-zero on any disagreement, so a billing bug stops a deploy rather than reaching a customer. It repairs nothing: a correction is a compensating entry made deliberately by a person, never a silent overwrite.

Telemetry never fails a served response
If the requests row or the ledger entry cannot be written, the response still goes to you. Losing a telemetry row is cheaper than turning a served request into a 500, and the audit is what catches the drift.

Something here disagrees with what the API actually did? That is a bug in this page, and worth reporting.

Report it