◉CLAUDE LABJP
●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/API & SDK
⬡ API & SDK/2026-06-22Advanced

When Your Claude API Cost Math Doesn't Match the Bill: Accounting for the Four Token Buckets

Turn on prompt caching and your homegrown cost tally drifts from the console bill. Here is how to weight the four token buckets the usage object returns and build a ledger you can reconcile.

Claude API128Cost Management4Prompt Caching6Operations21

✦ Premium Article

As an indie developer, I run a daily digest across several of my own apps on Claude, and one month my own cost tally was off from the console bill by roughly ten percent.

I traced the logs. Request counts were right. Token counts were right. It still didn't add up.

There was exactly one cause. I was computing cost from input_tokens + output_tokens only. The moment I enabled prompt caching, that simple formula broke silently.

Cached tokens are not in input_tokens

This was my first wrong assumption.

The usage object splits input tokens by role. Tokens served from cache are not included in input_tokens. They land in separate fields.

# What usage actually looks like with caching on
usage = {
    "input_tokens": 412,                  # only uncached, regular input
    "cache_creation_input_tokens": 18500, # writes to cache (expensive)
    "cache_read_input_tokens": 17800,     # reads from cache (cheap)
    "output_tokens": 1240,
}

So if you cache a long system prompt, its body never shows up in input_tokens at all. Pricing off input_tokens alone misses the tens of thousands of tokens sitting in the cache.

In my case the shared digest prompt is about 18,000 tokens. It gets written as cache_creation on every cold start, then read back as cache_read on later calls. The naive formula ignored both.

Each bucket bills at a different rate

The key to matching the books is understanding that the four buckets do not share one rate.

Cache reads and writes bill as a multiple of the base input rate. The multipliers are stable; even when prices change, the ratios rarely do.

Bucketusage fieldMultiplier on base input rate
Regular inputinput_tokens1.0×
Cache write (5-min TTL)cache_creation_input_tokens1.25×
Cache write (1-hour TTL)cache_creation_input_tokens2.0×
Cache readcache_read_input_tokens0.1×
Outputoutput_tokensoutput rate (separate)

Reads are a tenth of base input. Writes are 1.25× to 2×. Treat them uniformly and the calls where caching is working drift the most. Over-price the reads and you over-count; price the writes at base and you under-count.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Why cached tokens never appear in input_tokens, and how that quietly breaks naive cost math
✦A Python implementation that accounts for cache writes and reads at their correct multipliers
✦Logging one ledger row per call and reconciling against the console bill each month
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ API & SDK2026-08-01
Swapping Tools Mid-Conversation Without Losing Your Prompt Cache
Tools can now be added and removed between turns, but the tool block sits at the very front of the cache prefix. I measured 12 mutation patterns with fingerprints and built a stable-core plus volatile-tail registry with a guard that refuses unsafe changes.
⬡ API & SDK2026-10-16
Sending 40 Rows From Make to the Claude API Stops at Row 14 — Avoiding the 429 With One Subtraction
Why a no-code automation that sends spreadsheet rows to the Claude API one by one hits a 429 partway through, and how to fix it. Seven spacing strategies tested on a mock bucket, a formula for the Sleep delay, and settings that stop failed rows from vanishing.
⬡ API & SDK2026-10-13
Haiku 5.5 is cheaper per token, but your bill jumps fivefold past about 77k Haiku 4.5 tokens
On the price sheet, Haiku 5.5 costs roughly a tenth of Haiku 4.5. But the same text becomes about 30% more tokens, and a prompt over 100k tokens is billed at five times the rate. Here is the boundary in Haiku 4.5 terms, a script I actually ran, and the changes that return a 400.