Forecast a feature's monthly LLM bill before you ship it
Monthly spend is one token measurement times a volume assumption. Both are free to obtain from Infrai, and the arithmetic beats any calculator page.
Yes, and it takes about ten minutes. Measure one representative prompt with a real tokenizer, decide how many times a month the feature will run it, then multiply by each candidate model’s input and output rates. On Infrai the measuring calls — token counting, cost estimation and the model catalogue — are all free and don’t draw down the trial credit, so a forecast costs nothing but your attention.
The trap sitting inside every prompt-cost calculator is that it asks you for the price of a model. There isn’t one.
Your workload has a shape and the rate card has two columns
Input and output are billed at different rates, and the gap between them is wide — output is commonly 4× to 10× input on the same model. So “which model is cheapest” has no answer until you know your prompt-to-completion ratio. A retrieval feature that stuffs 900 tokens of context in and gets 150 tokens back ranks models in a completely different order from a drafting feature that takes a 200-token brief and writes 800 tokens of prose.
Get that ratio from a measurement, not a guess about characters per token.
export INFRAI_API_KEY="your_infrai_api_key"
curl -sS -X POST "https://api.infrai.cc/v1/ai/tokens/count" \
-H "Authorization: Bearer ${INFRAI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5-mini",
"messages": [
{"role": "system", "content": "You answer from the supplied policy extracts only."},
{"role": "user", "content": "Customer asks whether an annual plan can be downgraded mid-term. Policy extracts follow."}
]
}'
{
"ok": true,
"data": { "prompt_tokens": 42, "model": "gpt-5-mini" },
"metadata": { "latency_ms": 3, "cost_usd": 0.0 }
}
Run that against three or four real prompts from your design doc, take the mean, and you have the input half. The output half is an assumption — but it’s an assumption you can convert into a ceiling by passing the same figure as max_tokens on the live call later.
Rank the candidates without sending a single billable request
POST /v1/ai/cost/compare prices one message array across several models at once and sorts the result cheapest first.
curl -sS -X POST "https://api.infrai.cc/v1/ai/cost/compare" \
-H "Authorization: Bearer ${INFRAI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"models": ["openai/gpt-4o", "openai/gpt-4o-mini", "deepseek/deepseek-chat", "deepseek/deepseek-reasoner"],
"messages": [
{"role": "system", "content": "You label support tickets. Reply with one label."},
{"role": "user", "content": "My card was charged twice for the same invoice last Tuesday and the refund has not appeared."}
],
"expected_output_tokens": 8
}'
Verified 2026-07-26 on a 48-token prompt with 8 expected output tokens, that returns deepseek/deepseek-chat at $0.00000896, openai/gpt-4o-mini at $0.0000126, deepseek/deepseek-reasoner at $0.00004392 and openai/gpt-4o at $0.000378 — a 42× spread across four rows of the same request. Those four figures are a snapshot; the underlying per-million-token rates come from the catalogue, so re-read them rather than trusting this paragraph in six months:
curl -sS "https://api.infrai.cc/v1/ai/models?capability=chat&available=true" \
-H "Authorization: Bearer ${INFRAI_API_KEY}"
Rates move, and the direction has been downward for two years running, so whatever that call returns today is likelier to be a ceiling than a floor.
{
"model": "deepseek/deepseek-chat",
"vendor": "deepseek",
"vendor_region": "china",
"prompt_tokens": 48,
"expected_output_tokens": 8,
"breakdown": { "input_cost": 6.72e-06, "output_cost": 2.24e-06, "markup": 0.0, "final": 8.96e-06 }
}
One caveat before you build a dashboard on it: the comparison endpoint recognises a much shorter model list than the catalogue serves. Ask it about gpt-5-mini and you get MODEL_NOT_FOUND even though that model answers chat requests all day. The per-call implications of that are worked through in the price-preview guide; for a monthly forecast, the fix is simply to build the arithmetic from the rate card instead.
A month, projected across the catalogue
GET /v1/ai/models?capability=chat&available=true returns every model a verified vendor will actually serve, each with price_input_per_mtok and price_output_per_mtok. That’s all a projection needs.
const KEY = process.env.INFRAI_API_KEY;
if (!KEY) throw new Error("INFRAI_API_KEY is not set");
const WORKLOAD = { callsPerMonth: 200_000, promptTokens: 900, outputTokens: 150 };
const res = await fetch("https://api.infrai.cc/v1/ai/models?capability=chat&available=true", {
method: "GET",
headers: { Authorization: `Bearer ${KEY}` },
});
if (!res.ok) throw new Error(`catalogue lookup failed: ${res.status}`);
const { data } = await res.json();
const rows = data
.filter((m) => typeof m.price_input_per_mtok === "number")
.map((m) => {
const perCall =
(WORKLOAD.promptTokens * m.price_input_per_mtok +
WORKLOAD.outputTokens * m.price_output_per_mtok) / 1e6;
return { id: m.id, owner: m.owned_by, monthly: perCall * WORKLOAD.callsPerMonth };
})
.sort((a, b) => a.monthly - b.monthly);
for (const r of rows) {
console.log(`${r.id.padEnd(20)} ${r.owner.padEnd(14)} $${r.monthly.toFixed(2)} / month`);
}
Run it against the catalogue as it stood on 2026-07-26 and the 900-in/150-out feature lands like this:
| Model | Owner | $/month at 200k calls | Same feature at 200 in / 800 out |
|---|---|---|---|
| glm-4-flashx | zhipu | $2.94 | $2.80 |
| gpt-5-mini | openai | $105.00 | $330.00 |
| qwen3.7-plus | alibaba_intl | $120.00 | $272.00 |
| gpt-5 | openai | $525.00 | $1,650.00 |
| gpt-5-pro | openai | $6,300.00 | $19,800.00 |
Look at rows two and three. On the retrieval-shaped workload gpt-5-mini is 12% cheaper than qwen3.7-plus; invert the ratio and it becomes 21% more expensive. Neither model changed price — your feature did. That inversion is why a static comparison table is a poor substitute for running your own numbers, and it’s the one part of this exercise nobody else can do for you.
Two discounts the naive projection misses
If the work doesn’t have to be interactive, ask the estimator to price it in batch mode.
curl -sS -X POST "https://api.infrai.cc/v1/ai/cost/estimate" \
-H "Authorization: Bearer ${INFRAI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o-mini",
"messages": [{"role": "user", "content": "Summarise this ticket in one sentence and pick a tag."}],
"expected_output_tokens": 120,
"batch_mode": true
}'
The response carries a batch_discount line that took our 21-token example from $0.00007891 to $0.00004133 — call it half price, in exchange for giving up latency guarantees. The second discount is the exact-match cache: send an identical request body twice and the repeat is billed at roughly 70% of the original. Neither shows up unless you ask for it, and cache_strategy in the estimate body doesn’t model the cache at all — that field returned a zero discount on every call we made.
Where the forecast stops being trustworthy
It assumes your output-token guess holds. If users write longer inputs than your sample, or the model starts rambling because you removed max_tokens, the projection drifts the same way a query plan drifts when the table grows. Reconcile monthly:
curl -sS "https://api.infrai.cc/v1/account/usage" \
-H "Authorization: Bearer ${INFRAI_API_KEY}"
That returns 30 days of real spend broken down per capability, alongside cache_hits and total call count, which is the only number that settles an argument. GET /v1/account/balance adds a runway_days figure derived from your recent daily average.
Two honest limitations. The forecast covers inference only — if the feature also stores artefacts, sends email or enqueues jobs, those are separate line items (all on the same key and the same usage view here, which is the actual reason we do the arithmetic in one place). And retries aren’t modelled: a 3% failure rate with one retry is a 3% cost increase nobody budgets for.
If you only ever call OpenAI models, their pricing page plus a local tiktoken count gives you the same answer without a new dependency, and CloudZero’s model-by-model breakdown is a reasonable sanity check on the rate card. If you want the widest possible model list to compare against, OpenRouter publishes more vendors than we serve. The reason to run the projection here is that the catalogue you’re pricing and the account you’ll actually bill are the same object — and switching to whichever row won is a model string change, not a re-integration.