Metering & receipts

Most providers bill token counts that they report themselves and nobody checks. TokenCannon is built so that anyone can check. This page describes exactly what is counted, what is published, and how to verify a bill without trusting us.

What we commit to

  1. Exact token accounting. usage reports what the engine processed. No rounding up, no per-request surcharge, no billing for tokens the model did not emit. Four billed dimensions: input, output, cache read, cache write. Input is the uncached prompt, billed once. Cache read is what the engine served from its prefix cache, at the cache-read price. Cache write is the prompt prefix the engine reports it wrote into its cache this request (created_cache_tokens), priced at $0 under automatic prefix caching. Output includes any reasoning tokens; reasoning is not billed separately.
  2. Independently verifiable. /v1/tokenize runs the exact tokenizer of the exact model revision we serve, so you can recount your own prompt.
  3. No silent truncation. finish_reason is accurate and no token is dropped from a completion.
  4. Published configuration. /v1/modelsstates the repository, the pinned commit, precision, quantization, context length and engine version. Never "unknown".
  5. Honest context. We advertise only the context we allocate, and we test recall near the limit before advertising it (see Latency).
  6. Honest parameters. Any parameter we accept, we honor. An unsupported parameter is rejected with a 400 that names it, never silently ignored.
  7. Per-request receipts. Every request that reached a model has a receipt.

Usage objects

Every response carries usage exactly as the engine counted it. Streaming responses include it in the final chunk. Each request is billed on four counts:

  • input_tokens — the uncached part of the prompt, at the input price.
  • cache_read_tokens — the prompt prefix the engine served from its prefix cache, at the cache-read price.
  • cache_write_tokens — the prompt prefix the engine wrote into its cache this request, at the cache-write price ($0 under automatic prefix caching).
  • output_tokens — everything the model emitted, reasoning included, at the output price.

Cost is floor((input × in + cache_read × cache_read + cache_write × cache_write + output × out) / 1,000,000), computed in exact integer micro-dollars; the price is the same at any concurrency.

Both cache counts come from the engine's prompt_tokens_details (cached_tokens, created_cache_tokens). If the engine does not report cached tokens, the whole prompt is billed as input and the receipt says so (note). Unknown is never rounded to zero.

Reasoning tokens

Qwen3 models think before they answer. The thinking is streamed separately as delta.reasoning and never mixed into content. Reasoning tokens are output tokens: they are part of output_tokens and billed at the output price. There is no separate reasoning count and no separate reasoning price.

Recount your bill

POST /v1/tokenizereturns the token ids for a prompt or a message list under the served model's tokenizer and revision. It is free and never metered — it exists so you can verify the prompt side of usage yourself.

shell
curl https://api.tokencannon.io/v1/tokenize \
  -H "Authorization: Bearer $TOKENCANNON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "tokencannon/qwen3-0.6b", "messages": [{"role": "user", "content": "Hello, world!"}]}'

{"model":"tokencannon/qwen3-0.6b","hf_revision":"c1899de2…","count":12,"max_model_len":32768,
 "tokens":[151644,872,198,9707,11,1879,0,151645,198,151644,77091,198]}

Receipts

GET /v1/receipts/{request_id} returns the metering record for one request: the four billed counts, the four prices the request was billed at, cost, model revision, engine version, time to first token, total latency, finish reason and status. Receipts are written for every request that reached a model, including failures and client disconnects, which are recorded at zero cost.

shell
curl https://api.tokencannon.io/v1/receipts/req_01M180J9T92B2DFDCCDHWJJ5Q6 \
  -H "Authorization: Bearer $TOKENCANNON_API_KEY"

{"request_id":"req_01M180J9T92B2DFDCCDHWJJ5Q6","model":"tokencannon/qwen3-0.6b",
 "hf_revision":"c1899de289a04d12100db370d81485cdf75e47ca","engine_version":"v0.27.1",
 "endpoint":"chat/completions",
 "usage":{"input_tokens":2415,"output_tokens":8,"cache_read_tokens":0,"cache_write_tokens":2400},
 "prices":{"input_micros_per_mtok":"50000","output_micros_per_mtok":"150000",
           "cache_read_micros_per_mtok":"5000","cache_write_micros_per_mtok":"0"},
 "cost_micros":"121","ttft_ms":530,"latency_ms":1172,"finish_reason":"length","status_code":200,
 "streamed":true,"created_at":"2026-08-30T00:19:33.644Z"}

The first request above wrote a 2,400-token prefix into the cache at $0 and paid input price on the whole prompt. Sending the same prompt again reads that prefix back at the cache-read price, so only the 15 uncached tokens are billed as input:

application/json
{"request_id":"req_01M180JB3G6X4D2Q0V7KJ5WZ1N","model":"tokencannon/qwen3-0.6b",
 "hf_revision":"c1899de289a04d12100db370d81485cdf75e47ca","engine_version":"v0.27.1",
 "endpoint":"chat/completions",
 "usage":{"input_tokens":15,"output_tokens":8,"cache_read_tokens":2400,"cache_write_tokens":0},
 "prices":{"input_micros_per_mtok":"50000","output_micros_per_mtok":"150000",
           "cache_read_micros_per_mtok":"5000","cache_write_micros_per_mtok":"0"},
 "cost_micros":"13","ttft_ms":210,"latency_ms":640,"finish_reason":"length","status_code":200,
 "streamed":true,"created_at":"2026-08-30T00:19:41.102Z"}

Published configuration

GET /v1/models lists each model with hf_repo, hf_revision (a commit hash, never a branch), dtype, quantization, context_len, engine, engine_version and all four prices. A change to any of these is a new revision on the models page, not a silent swap.