Why an LLM Price Table Needs Provenance, Not Just Numbers
Comparing LLM APIs looks simple until the first spreadsheet update. A provider changes one rate, a router lists the same model under a different identifier, and a cached-input discount applies only to one channel. A sing
Comparing LLM APIs looks simple until the first spreadsheet update. A provider changes one rate, a router lists the same model under a different identifier, and a cached-input discount applies only to one channel. A single βprice per million tokensβ column cannot preserve those distinctions.
I treat an LLM pricing table as a small provenance system. Every displayed number should answer four questions: which model, which channel, which token type, and which source snapshot produced it.
Keep provider and router prices separate
The same model can be purchased directly from its provider or through a routing platform. Those routes may have different input and output prices, cache rules, fees, model identifiers, and update times.
A useful record therefore needs a channel field:
{
"model": "example-model",
"channel": "official",
"inputPerMillion": 2.5,
"cachedInputPerMillion": 0.25,
"outputPerMillion": 15,
"sourceUrl": "https://provider.example/pricing",
"verifiedAt": "2026-10-26"
}
The OpenRouter record for the same model is a second record, not an overwrite. That makes a price difference visible without implying that the provider itself changed its rate.
Model the workload before calculating cost
Price tables are hard to reason about because input and output tokens rarely occur in equal amounts. A calculator should accept a workload rather than asking the user to mentally average several rates.
For each request, store:
- fresh input tokens
- cache-read share
- output tokens
- requests per month
- optional channel fee assumptions
The calculation can then stay explicit:
fresh input cost = fresh tokens Γ input rate
cached input cost = cached tokens Γ cache-read rate
output cost = output tokens Γ output rate
monthly cost = per-request total Γ request count
When a cache-read rate is unknown, the safest default is the full input rate with a visible note. A missing discount should never silently become a zero-cost token.
Preserve unknowns instead of inventing precision
Pricing pages often omit a rate that another channel exposes. βPending verificationβ is a meaningful state. It prevents an unverified zero from entering rankings and tells the update process exactly what still needs review.
The same principle applies to tool-call charges, long-context surcharges, batch discounts, taxes, and credit-purchase fees. A calculator should list what it excludes so the estimate is useful without pretending to be an invoice.
Generate comparisons from one source of truth
Once the records are structured, the homepage table, model detail pages, two-model comparison, and monthly calculator can all read from the same dataset. The display can show source links and verification dates beside the result.
I used this approach in LLM API Prices, a source-linked comparison of official and OpenRouter rates with a workload calculator for fresh input, cached input, output, and monthly requests.
The practical lesson is that pricing data needs lineage as much as it needs arithmetic. Separate channels, retain unknown states, date every snapshot, and make assumptions visible. That turns a volatile list of numbers into a comparison users can audit.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.