Ollama API usage: turn response metrics into a cost estimate

Read Ollama API token and timing fields, reconcile streaming responses, avoid double-counting cache, and distinguish cloud consumption from local running costs.

The Ollama API gives you the raw material for a usage ledger, but it does not turn every response into an invoice. First identify where the selected model ran. Then collect the completed response metrics, separate cached input from fresh input, and apply the rates for that exact provider and model. Only after adding those request costs should you compare subscription fees and included credits.

This guide is for someone whose API request already works and who now needs trustworthy accounting. It is not another installation walkthrough. Documentation checked September 5, 2026. The numerical examples below are synthetic bookkeeping examples, not observed customer activity or current model prices.

Start with the endpoint and execution route

Ollama documents a local native API base at http://localhost:11434/api and a hosted base at https://ollama.com/api. However, a local client can also call a cloud model through the local Ollama service. Therefore, the word localhost alone does not prove that inference happened on your hardware. Record the endpoint, exact selected model, and whether cloud execution was selected together. See the API introduction and cloud execution guide.

Keep that route identity beside each aggregate. A report titled “Ollama usage” that mixes a laptop experiment with hosted requests cannot support a sensible price comparison. Local requests need a resource-cost model; hosted requests need the applicable provider rates. You can keep the same ledger format for both while leaving the monetary calculation separate.

Which response fields matter?

FieldMeaning for your ledgerCommon mistake
prompt_eval_countTotal prompt token countTreating it as fresh input only
prompt_eval_cached_countPrompt tokens served from cacheAdding it on top of total input
eval_countGenerated output token countSubstituting visible word count
total_durationTotal response durationCalling it GPU billing time
load_durationModel loading durationAssuming every request is warm
eval_durationOutput generation durationComparing nanoseconds with seconds

The official usage reference defines timing values in nanoseconds and places usage fields in the final chunk of streaming responses, where done is true. Read that completion record; do not add the same usage totals repeatedly while assembling text fragments. The prompt timing field covers evaluation of uncached prompt tokens, so timing and token totals answer different questions.

A request-level cost example you can audit

Suppose one completed request reports 12,000 input tokens, including 9,000 cached tokens, and 1,500 output tokens. Fresh input is 3,000, not 12,000. To make the arithmetic visible, assume illustrative prices of $1 per million fresh-input tokens, $0.10 per million cached-input tokens, and $3 per million output tokens. These deliberately round values are not a quote for any model.

fresh input = 12,000 - 9,000 = 3,000
fresh cost  = 3,000 / 1,000,000 × $1    = $0.0030
cache cost  = 9,000 / 1,000,000 × $0.10 = $0.0009
output cost = 1,500 / 1,000,000 × $3    = $0.0045
request consumption value             = $0.0084

Five hundred identical requests would represent $4.20 in consumption under those assumptions. That does not mean a subscriber receives a $4.20 invoice: a subscription fee, included allowance, overage rules, taxes, and the relevant billing period can change cash paid. Put measured monthly Ollama Cloud consumption into the cash calculator when its dated plan assumptions match your account.

Build a ledger without storing private prompts

A useful internal row can contain a locally assigned request identifier, completion time, execution route, model identifier, the three token counts, duration, and a status. None of those accounting tasks requires storing the prompt or generated answer. Keep identifiers out of public dashboards, restrict access to operational logs, and decide a retention period before collecting a large history.

Give retries distinct attempt identifiers under one task identifier. The task may succeed once after three attempts, but a success-only report can hide resources consumed by earlier work. Conversely, do not invent a token count for an interrupted stream that never supplied its completion record. Mark its usage as unknown and reconcile against the provider's account records when available. Unknown is a meaningful data-quality state, not the same as zero.

Validate relationships before calculating money. Reject negative counts, a cached count larger than total input, non-finite numbers, and timestamps outside the reporting period. Keep full precision while summing; rounding every sub-cent request to two decimal places would make the example above look like one cent and distort a large aggregate. Round for display after aggregation.

Separate performance measurement from billing

For a synthetic response with 200 output tokens and an output-generation duration of 4,000,000,000 nanoseconds, the generation rate is 50 tokens per second. That is a throughput measurement for the reported generation phase. It is not an end-to-end latency guarantee because loading, prompt processing, queuing, network travel, and client rendering may also matter.

When comparing configurations, run the same task and keep cold-start and warmed-up results separate. Record whether the answer passed a simple correctness check. A faster request that produces unusable code has not reduced cost per accepted result. A sensible benchmark table therefore needs completion quality and elapsed task time as well as tokens per second.

Handle stream failures explicitly

Ollama's error documentation explains that a streaming error can appear in the response body after the HTTP response has already started. An initial successful status is therefore insufficient proof of a completed model response. Check the stream for an error object and confirm a normal ending before marking the attempt successful.

For debugging, save the status and a redacted error category rather than the whole request body. Retry a temporary service failure within a bounded policy, but inspect an invalid request before sending it again. Repeating an unchanged malformed payload is not a recovery strategy. The context-overflow checklist covers one important class of request problems.

Frequently asked questions

Can I calculate tokens by counting characters?

A rough character estimate can help before a request, but it should not replace response metrics in a ledger. Tokenization varies by model and content. Store the provider-reported fields and their source so later changes to your estimator do not rewrite historical usage.

What if cached usage is missing?

Label the cached split unknown. You may present an explicitly conservative scenario that prices all reported input as fresh, but do not present that scenario as an observed bill. Compatibility endpoints can expose different field shapes; validate the format you actually use before mapping it.

Does a local response with token counts incur an API fee?

Token counts describe work, not who charges for it. For confirmed local inference, consider electricity, equipment allocation, and operation time. For a cloud route, check the actual provider account. The same output format does not create the same billing relationship.

What is the minimum useful monthly report?

Report completed attempts, unknown-usage attempts, fresh input, cached input, output, consumption value under a dated price snapshot, and actual account charges separately. Add the scope and exclusions. That small report is more defensible than a single impressive-looking savings number.