Back to blog

AI patterns

LLM Cost Transparency: Formulas, Field Names and Price Sources in Practice

If you want to show AI costs per customer, project or department, you need three things: the right token counts, the right prices and a formula that brings both together. We measured how well that works at twelve providers.

SvK by Sven von Känel 12 min read
  • KI
  • LLM-Kosten
  • Controlling

TLDR

xAI, Requesty, EU Router and Cortecs report the cost per call directly in the response — and there, our formula matched to the cent. OpenAI, Anthropic, Gemini and Mistral report only token counts, so you have to calculate the costs yourself. For that, you need current prices, which OpenAI, Mistral and Gemini publish only on web pages. And with routers: listed isn't charged. Part 3 of the series "What an LLM call really costs".

Introduction

As soon as a second department uses an AI application, the question comes up: who accounts for which part of the bill? The provider's monthly invoice doesn't help much — it knows no customers, no projects, no departments. Cost transparency only exists if you price every call yourself or the provider reports the cost per call.

Both are harder than they look. This part shows why.

Isn't billing per API key enough?

The obvious objection: the provider already bills per API key — why price every call yourself? The key answers exactly one question: which application? Every other cost question needs the cost per call.

  • Customer, user or feature. A SaaS product serves many customers with the same code. Creating, distributing and rotating a key per customer doesn't scale. Without cost per customer, though, you can't see margins or outliers.
  • Cost per transaction. What does a processed invoice, an answered ticket, an agent run cost? Only unit costs show the benefit; the total per key has no denominator.
  • Budgets in real time. A run should stop before the budget is reached, not at the end of the month. For that, the admin APIs are too coarse or missing: OpenAI reports costs only per day. Anthropic denies an individual organisation access (HTTP 403). For the Gemini API there is only Cloud Billing (not measurable). Mistral offers a usage API only on the enterprise plan (not measurable). EU Router has only the dashboard (not measured).
  • Several providers and routers. The costs sit in several dashboards and in different units: Cortecs reports micro-euros, xAI dollar ticks. With routers, the upstream actually chosen determines the price (section 7 and part 4); a key per router tells you nothing about that.
  • Internal allocation or recharging. If you allocate costs to cost centres or recharge them to customers with a markup, you need line items you can back up.
  • Proving an optimisation. Whether prompt caching or a lower reasoning effort really saves money shows only in the cache and reasoning tokens per call (part 1 and part 2).

1. The formula

The cost of a call comes from five token types and their prices:

cost = (input − cache read − cache write) × input price
     + cache read  × read price
     + cache write × write price (5 min or 1 h)
     + output      × output price      (reasoning is part of output)

If a cache price is missing, we use the input price — better slightly overestimated than costs left out. Where the provider itself reported costs, this formula deviated by 0.0 %: at xAI, Requesty, EU Router and for Claude via Cortecs.

2. The field-name chaos

The formula is simple. Collecting the numbers isn't — every provider names the same quantity differently:

Provider Input includes cached tokens? Cache read Cache write Reasoning
Anthropic no cache_read_input_tokens cache_creation_input_tokens (+ 5 min / 1 h) in output
OpenAI Responses yes input_tokens_details.cached_tokens input_tokens_details.cache_write_tokens output_tokens_details.reasoning_tokens
OpenAI-compatible yes prompt_tokens_details.cached_tokens differs by router completion_tokens_details.reasoning_tokens
Gemini yes cachedContentTokenCount – thoughtsTokenCount
Requesty yes cached_tokens caching_tokens (+ 5 min / 1 h) –

At Anthropic, input_tokens doesn't include cached tokens; in OpenAI-compatible APIs, they're included in prompt_tokens. The field names differ at every provider. Requesty reports cache writes as caching_tokens. Gemini reports thinking as thoughtsTokenCount.

Note: A particularly tricky trap: when OpenAI stops a response because of max_output_tokens, the usage for that call reports 0 tokens — input included. The good news from the admin API (section 4): these calls weren't billed either. The bad news: there was no answer either — your application has to detect the case and retry.

3. Cost per call: who reports it?

Provider / router Cost in the response Format Deviation from our formula
xAI yes cost_in_usd_ticks (10¹⁰ = 1 USD) 0.0 %
Requesty yes usage.cost in USD 0.0 %
EU Router yes cost (USD) and cost_eur 0.0 % (Claude)
Cortecs yes cost as an integer in micro-euros 0.0 % (Claude)
OpenRouter yes usage.cost in USD 0.0 % (Claude)
OpenAI, Anthropic, Gemini, Mistral, IONOS no token counts only –

xAI reports costs in ticks; 10 billion ticks are one dollar. Requesty and OpenRouter report USD, and EU Router also reports euros at the daily ECB rate. Contrary to its own API reference, Cortecs also reports costs in every response — as an integer in micro-euros, which isn't documented anywhere. No provider sends a cost header in the HTTP response.

4. Costs via admin APIs

If you don't get costs per call, some providers let you query aggregated costs — usually only with an admin key:

Provider Endpoint Resolution Status
OpenAI /v1/organization/costs, /usage/completions costs per day and project, usage per minute and key matched exactly
xAI management-api.x.ai/v1/billing/teams/{team}/usage down to the second matched exactly
Anthropic /v1/organizations/cost_report, /usage_report/messages costs per day and workspace blocked for individual organisations
Cortecs /v1/manage/logs, /manage/usage per request, including fallbacks not measured
Gemini Cloud Billing only hours to days of delay not measurable
Mistral admin API on Enterprise plans only per day not measurable

At OpenAI, the admin API reported exactly the same token counts for our key as our raw data; it didn't even count the three aborted responses with 0 usage as requests — so they weren't billed either. The daily costs matched our formula to the cent for all three models and were available the same day. Costs come only per day, and the usage API has no reasoning field. The bill also shows a separate line item for 12-hour cache writes. xAI's management API reported exactly the sum of the cost fields of all individual responses. According to its docs, Anthropic reports costs per day and workspace (not measured) — for our individual organisation, the API refused access even with an organisation-wide key (HTTP 403). For the Gemini API, there's only Cloud Billing (not measurable). Mistral offers a usage API only on Enterprise plans (not measurable). EU Router has no API for cost history, only the dashboard (not measured).

Tip: For a clean match with admin APIs, every application needs its own key in its own project or workspace. Otherwise, the costs of several applications end up in the same pot.

5. Where the prices come from

Calculating costs yourself needs current prices. Only some providers publish them in machine-readable form:

  • Via API: xAI , Cortecs (in EUR) , EU Router, Requesty and OpenRouter.
  • Web page only: OpenAI, Mistral and Gemini. Anthropic's /v1/models returns capabilities and effort levels, but no prices.

There are also public collections. models.dev has no price for the 1-hour cache write ; LiteLLM does. The cache factors in the OpenRouter documentation differ from the providers' pricing pages.

And prices have tiers: xAI doubles all prices from 200,000 tokens of context , GPT-6.1 Sol from 272,000 input tokens. So one price per model isn't enough — you need a price per model and context size.

6. Our catalogue, checked

For CompanyWizard, we run our own model catalogue. It combines models.dev (which models exist) with LiteLLM (more precise cache prices, including 1 hour) and checks the prices against OpenRouter; deviations above 25 % go to the log. Router prices sit next to them as separate entries per host, in euros for Cortecs.

We held the catalogue against the measurements:

  • Prices: For every measured model the catalogue lists, the prices matched the pricing pages.
  • Effort levels: The levels matched as well — for Claude, Gemini and GPT-5.6 Luna exactly the values the API accepted.
  • Gaps: Three of the measured models were missing: Claude Sonnet 5 at Anthropic direct, and GPT-6.1 Sol and gpt-5-mini at OpenAI.

The gaps come from the approval step: new models enter the catalogue as a proposal and reach the applications only after a manual check. That's intentional — a wrong price is worse than a missing one — but it costs freshness.

7. Listed isn't charged

Routers add another uncertainty: the listed price is often the price of the cheapest upstream, while you're charged for the one actually chosen.

Router Model Deviation from the listed price (median)
EU Router gpt-oss-120b +103 %
Cortecs gpt-oss-120b +50 % to +67 %
Cortecs DeepSeek V4.1 Flash +44 %
Cortecs, EU Router, Requesty Claude Sonnet 5 0 %

For open-weight models, the charged costs were up to 170 % above the list price. For Claude they matched, but EU Router lists Claude Sonnet 5 10 % above the others.

8. How we solved it in .NET

Microsoft.Extensions.AI has a property for cache reads, but none for cache writes. So the Anthropic adapter puts them into an additional field — and only when the value is above 0:

public const String CacheCreationInputTokensKey = "CacheCreationInputTokens";

public TurnTokenUsage Add(UsageDetails? usage)
{
    var cacheWrite = usage.AdditionalCounts?.TryGetValue(CacheCreationInputTokensKey, out var written) == true ? written : 0L;

    return new TurnTokenUsage(
        Input      + (Int32) (usage.InputTokenCount       ?? 0),
        Output     + (Int32) (usage.OutputTokenCount      ?? 0),
        CacheRead  + (Int32) (usage.CachedInputTokenCount ?? 0),
        CacheWrite + (Int32) cacheWrite);
}

Source: TurnTokenUsage (excerpt)

In CompanyWizard, TurnTokenUsage counts at every point where a conversation turn calls a model, including tool loops and after interruptions. A single booking path turns this into one record per turn.

Lesson Learned: A stream that breaks off midway books nothing in our setup — the Anthropic SDK reports usage only at the end of the stream. This gap is known and documented. It isn't closed.

9. What we deliberately left open

  • Admin APIs: we didn't reconcile Anthropic (individual organisation, HTTP 403) and Cortecs (no management key).
  • Batch, flex and priority tiers: not part of this series.
  • Image prices: not part of it either.

Conclusion: patterns you can reuse

  1. Normalise usage per provider before you calculate — above all, whether input includes cached tokens.
  2. Use cost fields where they exist, and check your own formula against them.
  3. Store prices with a date and a context tier, not as one number per model.
  4. The key for the application, the cost per call for everything below it: a separate key per application keeps admin APIs attributable; customer, transaction and budget need the cost per call.
  5. Pin the upstream at routers if the price has to be predictable.

All raw data and scripts: github.com/evanto-media-ag/llm-caching-reasoning-costs

The series

References


Want to show AI costs per customer or department? Let's spend 30 minutes on your specific workflow — no obligation, no cost, with concrete next steps at the end. Book a 30-minute call

Note: Article created with AI assistance.

NEWSLETTER

Four to six times a year, no marketing noise.

One pattern, one case, one recommendation. Signup with double opt-in, unsubscribe at any time.