← All posts
Product

Multimodal Cost Safety: An Unpriced Image Call Is Never $0

Image, video and audio models price per image, per second and per minute, not per token — and the expensive ones are the newest ones. nRouter holds a modality-appropriate reservation before the call and reports an unknowable cost as unpriced, never as zero.

nRouter team · 10 min read
Multimodal Cost Safety: An Unpriced Image Call Is Never $0

What multimodal cost safety does

Non-text calls take a modality-appropriate hold before the request leaves, and settle against the provider's reported cost. When that cost is not knowable, the call is reported unpricedx-nr-request-cost is absent, x-nr-cost-status says unpriced — and the hold settles rather than releasing. An unpriced call is never a free call, and it is never shown to you as $0.

Text taught everyone to reason about LLM cost in tokens, and the habit does not survive contact with the other modalities. An image is priced per image, and the per-image rate moves with size and quality. Video is priced per second of output. Speech and transcription are priced per minute of audio or per character of input. None of that is a token count, so any cost machinery built on multiplying tokens by a rate produces either nonsense or nothing on exactly the calls that cost the most.

The failure mode this creates is specific and quiet: a generation that genuinely cost real money gets recorded as costing nothing. Nobody gets paged, because nothing errored. The bill arrives at the provider anyway.

Why image, video and audio break token math

ModalityPriced byTypical cost driverToken math
TextInput and output tokensContext length, output lengthWorks
Image generationPer imageResolution, quality tier, countBreaks
Video generationPer second of outputDuration, resolution, modelBreaks
Speech synthesisPer character or per minuteScript length, voice tierBreaks
TranscriptionPer minute of input audioAudio durationBreaks

Three properties compound the problem:

  1. The unit is not in the response. A text response reports a usage object with token counts. A video job may report a duration, a status and a URL — enough to know it worked, not always enough to derive a charge.
  2. The rate card is multidimensional. "Per image" is really per image at a given size and quality, and the dimensions differ by vendor. A flat per-call rate is wrong in both directions depending on what was asked for.
  3. The newest model is the most expensive and the least documented. A flagship video model ships, everyone wants it that week, and it is precisely the model whose pricing metadata is thinnest. The highest-cost calls in your account are structurally the ones most likely to be unpriceable.

That third property is why this is a safety feature and not an accounting nicety. If unknown resolved to zero, the leak would be perfectly correlated with expense: the more a call cost, the more likely it was recorded as free. The cross-provider mechanics of getting a settled figure at all are in the cost tracking guide.

The three cost states, and why none of them is zero

Every call through the gateway lands in exactly one of three states, and all three are visible to you rather than being collapsed into a single populated column:

StateHeadersWhat it meansWhat to do with it
exactx-nr-request-cost present, x-nr-cost-status: exactThe provider reported a settled costUse it for attribution and chargeback directly
unpricedx-nr-request-cost absent, x-nr-cost-status: unpricedThe call succeeded; its cost is not derivable from what came backCount the call, flag it, reconcile at the ledger. Never substitute a number
In flightNeither is finalA hold is placed before the call and settled after itRead the ledger, not the header, for the final figure

The distinction that matters is between absent and zero. An absent field forces the consumer to make a decision. A zero makes the decision silently, and the decision it makes is "this generation was free". Every aggregate downstream then inherits that claim — the team's monthly spend, the customer's margin, the per-model cost ranking you use to decide what to keep running. The general principle is argued in cost honesty; multimodal is simply where it has the largest dollar consequences.

resp = client.images.generate(...)          # or a video / audio call
cost = resp.headers.get("x-nr-request-cost")   # None when unpriced
status = resp.headers.get("x-nr-cost-status")  # "exact" | "unpriced"

if cost is None:
    metrics.increment("llm.cost.unpriced", tags=[f"modality:{modality}"])
    # count it, alert on the rate, reconcile against the ledger — never zero-fill
else:
    metrics.observe("llm.cost.usd", float(cost), tags=[f"modality:{modality}"])

How a hold becomes a charge

The sequence is the same one text calls use, with the reservation sized by modality instead of by estimated tokens:

multimodal request
  ├─ reserve a modality-appropriate hold      (not token math)
  ├─ check the hold against every ceiling     (org / team / user / key)
  ├─ forward to the provider
  └─ settle
       ├─ cost reported  → settle at the reported cost, status `exact`
       └─ not derivable  → settle the reservation, status `unpriced`

Two design decisions in that diagram are deliberately counter-intuitive and worth stating outright.

The hold is taken before egress, not after. Insufficient available credit means the request is refused before the provider is ever called — which is the only point at which refusing is still cheap. The general mechanism, including why a balance cannot go negative under concurrent load, is reserve-and-settle.

An unpriced call settles rather than releases. Releasing the hold would return the money and make the request free, and free requests are how a gateway leaks money while every dashboard reads green. So the reservation becomes the charge, the call is flagged unpriced, and you can see exactly which calls were charged that way. This is a conservative charge in place of a dishonest zero — and it is why the reservation is sized per modality in the first place, because a token-shaped estimate would be a bad floor for a video job.

There is a fourth outcome that never happens: a model nobody can price does not get enabled. If we cannot establish a defensible cost for a model, it does not appear in your catalog on the models page, so there is no window in which a model is simultaneously live and free.

Set it up for a multimodal workload

Nothing here requires code beyond reading two headers. The controls are configuration.

  1. Give the multimodal workload its own key. Image and video traffic has a completely different cost-per-call profile from chat, and mixing them under one key makes both budgets meaningless. One key per workload, each with its own ceiling.
  2. Set the budget in currency, at the right scope. Org, team and user budgets return 402 with budget_exceeded; a single key's budget returns 429 with key_budget_exceeded. Four scopes, and which one to reach for is covered in the four ceilings every request passes and Budgets vs Rate Limits: Pick the Control, Then Set Both. Configure them under budget controls.
  3. Handle the two stop codes. A 429 carrying key_budget_exceeded is a ceiling, not a throttle — retrying it is the single most common client bug after a migration. The branch to write is in handling 429 and 402.
  4. Log both cost headers on every non-text call, with the modality as a dimension. This is the line of code that makes the rest observable.
  5. Alert on the unpriced rate, not just on spend. A rising share of unpriced calls in one modality is the earliest signal that your traffic has moved onto a model whose cost reporting is thin. Set it up under alerts and watch it beside the aggregates in analytics.
  6. Reconcile monthly. Sum the ledger, compare against the balance movement, and check the unpriced count against your own call log. Reading a spend ledger is the procedure.

Worked example: what a zero would have cost you

The unit costs below are illustrative placeholders, not rates from any vendor — real per-image and per-second rates come from the provider rate cards in the Sources section. What is not illustrative is the structure of the leak.

A product ships two multimodal features in one month: thumbnail generation and short promotional clips.

FeatureCallsIllustrative unit costPriced exactReported unpriced
Thumbnail images12,000$0.04 per image11,640360
Promo clips (8s each)200$0.50 per second14060

Now compare the two accounting treatments:

TreatmentImage spend recordedVideo spend recordedTotal recordedUnrecorded but incurred
Unknown cost zero-filled$465.60$560.00$1,025.60$254.40
Unknown cost reported unpriced, hold settled$480.00$800.00$1,280.00$0

The image row is a rounding error — $14.40 on the month, the kind of gap nobody would ever chase. The video row is $240 on 60 calls, and it is the same 60 calls that a growth spike would multiply by ten. That asymmetry is the whole argument: zero-filling costs you least where you would notice and most where you would not.

The second-order damage is worse than the $254.40. Under the top row, a $1,000 monthly budget never trips even though real spend crossed it, because the ceiling sums the recorded figures. Your cost of goods on the clips feature is understated by 30% ($560 recorded against $800 incurred), which overstates the margin you report on it. And the model-versus-model cost ranking you use to pick a default model puts the unpriceable model at the top of the cheap list — see cost vs usage analytics for how that ranking gets read in practice.

What it costs

Multimodal cost safety is not a paid add-on, and the number that makes it work is the one that is zero on every plan: the per-call markup, because the platform fee is charged on top at purchase instead — which is exactly why the figure attached to an image or a video generation is the provider's own and can honestly read unpriced rather than being quietly rounded to something convenient. The fee model is argued in markup-free LLM credits and tabulated on the pricing page.

Budgets, guardrails, alerts, analytics and per-team scoping are on every plan; a plan changes the platform fee and the rate limits and nothing else.

Where it fits with the rest of the platform

  • Predictable AI spend and hard spend limits only hold if the priciest calls count against them. A zero-filled video call is a hole in the ceiling.
  • Attribution by team, customer and feature stays reconcilable when unpriced calls are counted and flagged rather than silently valued at nothing.
  • Per-customer LLM billing depends on a real cost of goods per generation. If you resell image or video generation, this is the post that determines whether your margin is a number or a guess.
  • Reserve-and-settle is the underlying credit mechanism, and the reason the unpriced case settles instead of releasing.
  • Cost honesty is the principle: read the number, never invent it, and say so when it cannot be read.

What to watch on your own traffic

Four signals, all available without asking us for anything:

  1. The unpriced rate per modality. A stable low percentage is normal. A jump usually means traffic shifted to a newly released model.
  2. Unpriced calls concentrated in one key. That is one service or one customer generating the calls you cannot yet attribute a real cost to, and it is where a margin surprise comes from.
  3. Ledger total versus the sum of your exact headers. The difference should equal the settled reservations on unpriced calls. If it does not, quote us the x-nr-request-id values.
  4. A budget that never trips on a month you know was heavy. That is the classic symptom of a cost pipeline that zero-fills somewhere — if not ours, then in your own aggregation.

Limits and what this will not do

  • A settled reservation is a conservative charge, not a measurement. On an unpriced call we charge the hold. That is deliberately not a claim about what the provider actually charged us.
  • It does not make an unpriceable model priceable. There is no override that produces a figure. If a provider does not report enough to settle, the status stays unpriced until that changes.
  • It does not predict cost before the call. A reservation is a hold, not a quote. If you need an exact figure before egress on a variable-duration video job, no gateway can honestly give you one.
  • Your dashboard will sometimes show a count instead of a number. If your finance pipeline cannot represent "unknown", that is real integration work we are pushing onto you, and we know it.
  • Not every modality is available for every provider. Coverage varies, and the models page is the only current answer. Anthropic, OpenAI and AWS Bedrock are live today; check the catalog for what each one serves.
  • Reconciliation is yours if you want it. We publish the ledger and the headers. Proving they agree is a job we make possible and do not do for you.

Try it

Load the $5 minimum at signup — a real charge with the platform fee on top. Give a throwaway key a $1 budget, run a handful of image generations, and log both cost headers with the modality attached. Then deliberately reach for something at the edge of the catalog and watch what an absent x-nr-request-cost looks like in your own logging. That single observation is the entire argument of this post, and it takes about ten minutes.

See also

Sources

Verified 2026-08-23. Provider rate cards for non-text modalities change often and are the fastest-moving prices in this space; if any link below has moved, email hello@nrouter.ai and we will correct this post.

OpenAI, Anthropic and AWS are trademarks of their respective owners. nRouter is not affiliated with or endorsed by them. All claims above are sourced from their public pricing or documentation on the date shown. The unit costs in the worked example are illustrative placeholders and are not attributed to any vendor.

Share
Written by nRouter teamEngineering, product, and company posts from the nRouter team — code-first, cost-honest, no vendor-marketing fluff.