Guides / token accounting

What is token accounting?

Token accounting is recording input, output, and cached tokens for every call, then pricing each category at its own rate in exact decimal arithmetic. The three categories bill differently, so one combined count can't produce a correct figure. Culpa, a local-first LLM cost, margin, and forecast ledger, meters all three per call and prices them from a versioned book.

Why this happens

Two things break token accounting in practice. The first is collapsing the categories, treating tokens as one number when input, output, and cached tokens carry rates that differ by an order of magnitude. The second is floating-point money. A per-call cost of a fraction of a cent, summed across millions of calls, accumulates float error into a figure that no longer reconciles with anything. Both failures are silent, which is what makes them expensive.

What this usually looks like

  • Your totals disagree by small amounts depending on which report ran them, with no code change in between.
  • Per-call costs display as long trailing decimals, which is the visible symptom of float arithmetic underneath.
  • You track a single token count per call, so you can't say whether input or output drove a change.
  • Cached tokens either aren't recorded or get counted at the standard input rate, overstating spend.

Free, no card, no account

Run the free Cost Leak Scan

It shows your most expensive conversation before you install anything.

Run the free Cost Leak ScanStart 14-day trial

Mistakes that cost the most

MistakeWhy it hurtsDo instead
Storing money as a floating-point number.Float can't represent most decimal fractions exactly, so millions of tiny costs accumulate an error you can't audit away.Store money as an exact decimal type, and do the arithmetic at a fixed precision from token counts and rates.
Rounding each call to cents before summing.Most calls cost well under a cent, so per-call rounding either zeroes them out or inflates them massively.Keep full precision per call and round only at the point of display, never in storage or in a running total.
Trusting a provider-reported cost field as the source of truth.Not every provider returns one, formats differ, and a field you can't reproduce from tokens and a rate can't be audited.Compute cost yourself from tokens and a versioned rate, then use any provider figure as a cross-check rather than the answer.

Run this check tonight

  1. Check whether your cost column is a float or an exact decimal type. If it's a float, that's the first fix.
  2. Take one call and recompute its cost by hand from its token counts and the rate. It should match to the last digit.
  3. Confirm you store input, output, and cached tokens as separate fields rather than one total.
  4. Sum a day of per-call costs and compare against your own daily aggregate. A drift means rounding is happening somewhere.
  5. Check what your system records when a model isn't in your rate book. Silent zero is worse than a flagged gap.

The same call, priced three ways

One Claude Haiku 4.5 call at real rates of $0.001 per 1k input, $0.005 per 1k output, and $0.0001 per 1k cached input. The call sends 3,000 input tokens of which 2,000 hit the cache, and returns 500 output tokens.

Collapsed count (3,500 tokens at the input rate) = 3.5 x $0.001 = $0.0035, which is wrong in both directions
Correct split: 1,000 uncached input = 1 x $0.001 = $0.001
2,000 cached input = 2 x $0.0001 = $0.0002
500 output = 0.5 x $0.005 = $0.0025
Correct total = $0.001 + $0.0002 + $0.0025 = $0.0037, and rounding this call to cents would record $0.00

The collapsed count under-read by 5% on one call. Rounding to cents would have recorded nothing at all. Across a million calls, either error is the whole number.

Every number, with its confidence and source

FigureWhat it meansConfidenceSource
$0.0037correct cost of a single cached Claude Haiku 4.5 call, priced by categorycalculated(1 x $0.001) + (2 x $0.0001) + (0.5 x $0.005), using Claude Haiku 4.5 rates per 1k tokens from the price book, effective 2026-07-02.
5%understatement produced by collapsing the three token categories into one countcalculated($0.0037 - $0.0035) / $0.0037, from the two calculations shown in the teardown.

What a generic answer can’t know

A dashboard built on a provider's aggregate can only be as precise as the aggregate. It can't re-derive a single call's cost from its tokens, so it can't show you the working or let you audit a figure you doubt. Culpa computes each call from tokens and a dated rate on your own infrastructure, where your prompts and responses stay, and counts the calls to run your plan.

Questions founders ask next

Why can't I just use floating-point for LLM costs?

Because a per-call cost like $0.0037 has no exact binary representation, and the error compounds across millions of rows. Financial systems have used exact decimal types for this reason for decades, and LLM billing has the same shape.

What happens when a model isn't in my price book?

It should record zero cost and flag the record as incomplete, so the gap is visible rather than silently understating your spend. A system that guesses a rate for an unknown model is producing a number nobody can defend.

Should I count cached tokens as input tokens?

Count them separately. On several providers the cached rate is an order of magnitude below the input rate, so folding them together overstates spend badly. On Anthropic models you also need to track cache writes, which bill above the input rate.

On your infrastructure

Culpa runs on your infrastructure. Your prompts and responses never leave it. Culpa counts calls to run your plan, and it fails open, so if it ever breaks your app keeps running.


How Culpa works

Find the culprit. Not just the total.

Your dashboard shows what you spent. It stops short of who spent it. Culpa shows the conversation, the user and the feature behind it.

Your prompts stay local.

Culpa runs on your own infrastructure. What you send to a model reaches us at no point.

Every dollar has a name.

Follow any charge to the conversation, the user, the feature and the customer behind it.

See the bill before it lands.

Cost your next feature before you ship it. You get the likely bill and the worst case, at best, median, p90 and p99.

Three steps to your first answer.

1

Change one base URL.

Or drop in the Python or TypeScript library.

2

Find your most expensive conversation.

In the first session, not the first week.

3

Cost your next feature before you ship it.

Base URLhttp://localhost:4545/v1Your traffic keeps flowing if Culpa ever stops.

Why the bill went up

Example dashboard

Calls traced

418,209

across 3 projects

Spend this week

$378.41

+ $182 vs last week

Failed calls

312

74% retried, and you paid for all of them

+ $182 this week traced to one culprit

Spend over 14 days

$0$20$40$60$8024262830020406
user_384report_generatorconv_91fprompt_v1894,220 tokens3 retries$6.81

Most expensive users

user_384$38.42
user_119$21.07
user_562$14.90
user_204$8.30
user_871$5.10

Next week forecast

Best$180
Median$240
p90$310
p99$395

Graded against reality. Accuracy shown as results land.

Keep reading


Sources: Anthropic pricing. Last reviewed 2026-08-01. Plain text version.