Skip to content

Cost and FinOpsGuide

Estimate LLM cost before the request, not after the bill

Every AI provider bills after the work is done, but budgets, cost previews and model choices have to be made before it. Here is how to estimate a request's provider cost for each modality, which parts are known, bounded or unknown, and how to use each kind of number.

By INFRO Editorial

Published

12 min read

An amber bracket of light on a dark ground framing a narrow band, with a fainter wider band behind it, like a range drawn around a single value

In short

Estimate a request's provider cost from what you know before the call: counted input tokens and the output ceiling for text, image count with resolution and quality, video seconds at a resolution, characters or audio minutes for speech. Text is always a range, because output and reasoning tokens are unknown until the model stops; use the worst case for budget admission, the expected figure for previews, and say unpriced rather than $0 when no rate is known.

Key takeaways

  • Split every request into what is known (input, image count, video seconds), what is bounded (output tokens under max_tokens) and what is unknown (reasoning length, self-chosen durations).
  • Count input tokens with the target model's own tokenizer; counts move between model generations.
  • Reasoning tokens are billed as output and are not visible, so the only safe text bound is the output ceiling you set.
  • Use the worst case to admit a request under a budget, the expected figure to preview cost to a user, and recorded costs to compare models.
  • When no rate is known the answer is unpriced, never $0, and a negotiated rate beats the list rate whenever you have one.

Every AI provider bills after the work is done. The decisions that cost money are made before it: whether a request fits under a budget, what a button in your product should say it costs, which model an experiment should try. Those need an estimate of the provider's charge before the call, and an estimate that is honest about what it does not know. This guide covers how to build one for text, images, video and audio, why the text estimate is always a range, and which number each decision needs. For how providers price in the first place, read AI API pricing explained; this article starts where that one ends.

Known, bounded and unknown

Every request can be split into three kinds of quantity:

  • Known before the call. The input you are about to send, the number of images you ask for, the seconds of video, the characters of a speech script, the length of an audio file to transcribe.
  • Bounded. Quantities you cannot know but can cap, chiefly output tokens under a max_tokens or max_output_tokens ceiling.
  • Unknown. Quantities with no cap you control: how much a reasoning model thinks inside its ceiling, how long a video model runs when it chooses its own duration.

An estimate multiplies the known and bounded quantities by the rate for the unit the provider bills in, and says plainly which part is a ceiling. The unit itself differs by provider and modality, which is the subject of tokens are not the billing unit.

What is known before the callBilled perKnown before the callUnknown until it finishes
TextInput and output token (some vendors: cached and cache-write input)Input tokens, if you count them with the model's own tokenizerOutput length, including reasoning tokens; only the max_tokens ceiling is known
ImageImage, by resolution and quality tier (some vendors bill image tokens)Count, resolution and quality you ask for◐a failed or retried generation, edits with input images
VideoSecond of output, by resolution; audio may be included or separateDuration and resolution you ask forModels that choose their own length
SpeechCharacter of input text, or audio tokensCharacters you sendAudio-token models: output length
TranscriptionMinute or hour of audioThe file's durationLittle; this is the most predictable unit
What a pre-request estimate can rely on, by modality. Units vary by vendor; check the rate card of the provider that will serve the request.

Text: count the input, bound the output

Input is knowable, provided you count it with the right tokenizer. Providers expose counting endpoints for this. Anthropic's token counting endpoint takes the same structure as a message, including system prompt, tools, images and PDFs, and returns the input token count; it is free to use, rate-limited separately from message creation, and Anthropic calls the result an estimate that can differ from the billed count by a small amount1. Anthropic also notes that its newer models use a tokenizer that produces roughly 30% more tokens for the same text than earlier models, and tells you to recount prompts against the model you plan to use rather than reuse old counts1. The general lesson holds for every vendor: a count is per model, and a cached count from last quarter's model is a wrong count.

Count everything the provider bills as input: the system prompt, every message in the history, tool definitions and schemas, retrieved documents and images. A retrieval step that adds ten passages changes the estimate more than the user's question does.

Output is not knowable, only boundable. The ceiling you set is the bound. Without one, the bound is the model's maximum output, which is usually far above anything the request needs and makes the worst case useless.

Reasoning tokens sit inside that ceiling and make the range wider. OpenAI's reasoning guide states that reasoning tokens are not visible through the API, occupy context, and are billed as output tokens; max_output_tokens limits the total including reasoning; and the response's usage object reports the exact count afterwards2. OpenAI recommends reserving at least 25,000 tokens for reasoning and output when you start experimenting, and warns that a request which reaches the limit returns incomplete, possibly before any visible output, so you can pay for input and reasoning and get no answer2. That makes the ceiling a cost control and a correctness risk at once: set it too low and you pay for nothing usable. The reasoning tokens article covers how to size it.

  • Input (counted)
  • Visible output
  • Reasoning
  • tokens
  • Low (short answer)2,600 tokens
  • Expected (p50 of past runs)4,200 tokens
  • Worst case (max_tokens 8,000)10,400 tokens
The same request at three points of its range, in tokens. Input is fixed; output and reasoning move. Illustrative figures from the example above.

Two refinements tighten text estimates. Use the dearest input rate the request could incur when you need a bound: a prompt-cache write is billed above the plain input rate at some vendors, so a bound priced at plain input is not a bound. And for an expected figure, use your own history: the median output of the same workflow over the last few weeks is a better predictor than any rule of thumb.

Images: count, resolution and quality

Image generation is easier because the output is chosen in the request. The quantities are the number of images, the resolution and, where offered, a quality setting. Google prices image output from its Gemini image models per image by resolution; Gemini 3.1 Flash Image, for example, lists separate per-image prices for 0.5K, 1K, 2K and 4K output3. OpenAI prices its image models per million image and text tokens and points to a calculator in its image generation guide for estimates4. The same picture is therefore a per-image figure at one vendor and a token figure at another; normalize to cost per image at the resolution and quality you ask for.

The estimate can still miss. An edit that sends input images adds input cost, and a request that fails and is retried may bill twice depending on the provider. Price the request as asked, and record what was actually billed.

Video: seconds, resolution and audio

Video is billed per second of output, and the rate depends on the model tier and the resolution. Google's Gemini API lists Veo 3.1 Fast at $0.10 per second at 720p, $0.12 at 1080p and $0.30 at 4K, with audio included in the default price, and says you are charged only when the video generates successfully3. An eight-second 1080p clip on that rate card is 8 × $0.12 = $0.96, which can be stated before the job starts.

Two things break that arithmetic. A model that chooses its own duration cannot be priced in advance; the honest answer is "unknown length" until the job finishes. And audio is priced into the base rate at some vendors and as a separate option at others, so the same flag can change the estimate at one provider and not at another.

Audio: characters and minutes

Speech synthesis is billed either per character of input or per audio token of output. OpenAI lists tts-1 per million characters and gpt-4o-mini-tts per million text and audio tokens4; Google bills Gemini TTS audio output per million tokens at 25 tokens per second of audio3. A character-priced model is exact before the call; a token-priced one depends on how long the voice takes to say it.

Transcription is the most predictable unit of all: OpenAI prices its transcription models per minute of audio4, and the file's duration is known before you send it.

Why the answer is a range, and sometimes no answer

A single figure for a text request is a promise the provider did not make. Show the expected figure with its ceiling, or the range, and say which is which.

Sometimes there is no figure. A new model with no published rate, a provider whose rate card does not cover the option you chose, or a self-chosen duration all leave the estimate unknown. Report that as unpriced, with the reason. Never substitute $0: a dashboard that adds unpriced requests as zero shows spend falling exactly when the riskiest traffic grows, and a budget that measures them as zero does not govern them.

List rate or your negotiated rate

Most estimates use the vendor's published list rate because it is the only one in the documentation. If your organization has a negotiated rate, a committed-use agreement, or buys a model through a cloud provider with its own rate card, the list rate is the wrong input and the estimate will drift from the invoice by exactly that difference. Enter the rate you actually pay, per model and per provider where they differ, and keep the list rate as the fallback. The negotiated rates article covers how that drift appears and how to find it.

Which number each decision needs

Which number does this decision need?

  • Admitting a request under a blocking budgetThe worst case: input at the dearest input rate, output at the full ceiling, the dearest fallback target
  • Showing a user what an action will costThe expected figure, with the range or a ceiling beside it
  • Choosing a model in an experimentThe recorded cost of real runs, compared on the same inputs
  • No rate is published for the modelUnpriced: say so, never show $0
Three decisions, three different numbers, and one rule for when there is none.
  • Budget admission needs the worst case. A gate that admits a request on its expected cost will be crossed by the requests that run long. Price input at the dearest rate it could incur, output at the full ceiling, and, if the request can fail over, at the dearest target it could reach.
  • Cost previews in a product need the expected figure, with the ceiling or range beside it when the spread is large. A preview that shows the worst case for every text request trains users to ignore it.
  • Experiments need recorded costs, not estimates. When you compare models, run the same inputs through each and compare what each provider reports, because output length differs by model and that is most of the cost.

Estimates in INFRO: POST /v1/estimates, the Playground and your rates

INFRO is a control plane in front of the provider accounts you already hold. It takes 0% markup on model spend; every cost figure it shows is an estimate of what your own provider will bill you, and INFRO's subscription is never part of it.

POST /v1/estimates answers what a request would cost on your own provider account before you make it. It takes model, an optional provider (otherwise the first of your connections that would serve the model), and the quantities: n, size or resolution and quality for images, duration_seconds for video and transcription, characters for speech, input_tokens and output_tokens for text. The request is checked against your model allowlists, and no provider is called.

Estimate an eight-second 1080p clip
curl https://api.infro.io/v1/estimates \
  -H "Authorization: Bearer $INFRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "google/veo-3.1-fast", "provider": "google", "duration_seconds": 8, "resolution": "1080p"}'
Response
{
  "object": "estimate",
  "model": "google/veo-3.1-fast",
  "provider": "google",
  "estimated_cost": 0.96,
  "unpriced_reason": null,
  "price_source": "list",
  "rate": {
    "unit": "second",
    "unit_cost": 0.1,
    "tiers": { "720p": 0.1, "1080p": 0.12 }
  }
}
  1. POST /v1/estimates

    You send
    model, optional provider, and the quantities: n, size or resolution and quality, duration_seconds, characters, input_tokens and output_tokens.
  2. no provider call

    INFRO resolves
    Checks the model against your allowlists, picks the named provider or the first of your connections that serves the model, and finds the rate.
  3. object: estimate

    You get back
    estimated_cost in USD or null, unpriced_reason, price_source, and the rate: unit, unit_cost, tiers, and per-million-token rates for text.
  4. authoritative

    Your provider bills
    The estimate is what your provider is expected to bill your account. INFRO's subscription is never part of it.
What POST /v1/estimates takes and returns, from the gateway source. The provider is never called.

estimated_cost is in US dollars, or null with an unpriced_reason: no_rate when nobody has published a rate, unknown_length when a video or transcription request names no duration, unknown_quantity when a text or speech request names no quantity. For a text model, rate also carries input_per_1m_tokens and output_per_1m_tokens. The text estimate is input times the input rate plus output times the output rate, so the number you pass as output_tokens decides which point of the range you get: pass your ceiling for the worst case, your typical output for the expected figure. Units are billed per started unit, as the gateway records them, so 7.5 seconds is priced as 8.

The rate comes from your own negotiated rate for that provider where you have entered one, then your rate for the model on any provider, then the model vendor's list rate; price_source reports which (custom_provider, custom, list). Resolution and quality tiers apply to a list rate only; a negotiated rate is used as you entered it. Entering negotiated rates under Prices in the console is included from the Team plan; on other plans estimates use list rates.

  1. 1 · custom_provider

    Your rate for this provider

    A negotiated rate entered for this model on the provider that would serve it.

  2. 2 · custom

    Your rate for the model

    A negotiated rate entered for the model without naming a provider.

  3. 3 · list

    Vendor list rate

    The model vendor's published rate, with its resolution or quality tier where the vendor lists one.

  4. 4 · null

    Unpriced

    No rate is known: estimated_cost is null with unpriced_reason no_rate.

The order in which an INFRO estimate looks for a rate.

The same arithmetic runs inside the gateway. Under a blocking budget, a request is admitted only if its worst-case estimated cost fits the room left: the whole billed request body, every requested choice, the most expensive input rate the model could apply, and the most expensive model and provider it could fall back to. When a chat request sets no max_tokens, the worst case assumes the model's maximum output, 32,768 tokens where the catalog lists none, and INFRO sends that ceiling to the provider. Setting max_tokens yourself reserves less. A request that could reach an unpriced model is refused with 402 unpriced_model_under_budget by default, because its worst case is unknown. The details are in the spend controls docs.

After a request, every response carries usage.cost and usage.price_source, and the request log records the estimated cost per request, or null when the model is unpriced, as described in the billing docs.

The console Playground runs text, image, video, speech and transcription on one of your connections or through a gateway key. After each run it shows the total time and, for text, time to first token, tokens in and out and output speed, with the estimated provider cost, shown as "Unpriced" when no rate is known. Copy cURL copies the request as a call to /v1 with a gateway key, which makes the Playground a quick way to build the body you then pass to /v1/estimates. The Playground's history of your last twenty runs stays in your browser only; INFRO stores no prompt for it, while the request log keeps each run's record. INFRO Studio uses the same estimate to show the provider cost of every step before a run starts.

A checklist before you ship a cost estimate

  • Input counted with the target model's own tokenizer, including tools, history and retrieved context.
  • An explicit output ceiling on every text request that a budget governs.
  • Reasoning models given enough ceiling to finish, and the ceiling priced as the worst case.
  • Images priced per image at the resolution and quality requested; video per second at the resolution, with audio checked.
  • Unpriced shown as unpriced, with its reason, never as $0.
  • Negotiated rates entered wherever they apply, with the list rate as the fallback.
  • Worst case for admission, expected figure for previews, recorded cost for experiments.

From the team that builds it

Where this shows up in INFRO

INFRO is a control plane in front of the provider accounts you already hold. The capabilities below are the parts of it this article touches, each with the documentation that defines its behaviour.

  • Cost estimates before a request

    Private early access

    Ask what a request would cost on your own provider account before you make it: per image with resolution and quality tiers, per second of video, per character of speech, per token of text.

    Read the documentation for Cost estimates before a request
  • Console playground

    Private early access

    Run text, image, video, speech and transcription on one of your connections or through a gateway key, and copy the call as cURL. The Playground's history stays in your browser.

  • Negotiated provider rates

    Private early access

    Enter the rates your contracts actually carry, per model and optionally per provider, so estimated cost uses them before the vendor's list rate. Included from the Team plan.

    Read the documentation for Negotiated provider rates
  • Usage and cost per request

    Private early access

    Every request records its model, latency, token or unit counts, and estimated provider cost, queryable by project and key.

    Read the documentation for Usage and cost per request

INFRO is in private early access. Provider usage is billed to you by your providers; INFRO charges a software subscription and takes 0% of model spend. See plans.

Sources

Numbered in order of first citation. Each was opened and checked against the claim on the date shown.

  1. 1.Token counting (opens in a new tab) — Anthropic. Accessed Oct 13, 2026.
  2. 2.Reasoning models (opens in a new tab) — OpenAI. Accessed Oct 13, 2026.
  3. 3.Gemini Developer API pricing (opens in a new tab) — Google. Accessed Oct 13, 2026.
  4. 4.Pricing (opens in a new tab) — OpenAI. Accessed Oct 13, 2026.

About this article

Provider behaviour was read on 2026-10-13 in OpenAI's reasoning guide and pricing page, Anthropic's token counting documentation and Google's Gemini API pricing page. Dollar figures in the example blocks are illustrative arithmetic; the Veo 3.1 Fast rates in the request example are Google's published list rates as read that day. INFRO behaviour is described from its public docs (org/billing, observability, spend controls) and from the gateway source of POST /v1/estimates and the console Playground; no production data was used.

Last checked against its sources on . The next review is due by . No separate named reviewer is recorded for this article.

How articles are written, sourced and corrected is set out in the editorial standards.