Cost Optimization & FinOps

Logging Token Counts for Internal FinOps

Every Claude response already tells you exactly what it cost — in tokens. Capturing that usage object on every call is the foundation of any internal cost system.

Claude 3P 101 · Updated July 2026 · Unofficial guide

Cloud invoices arrive monthly and aggregate everything. The usage object on each API response arrives instantly and describes one request. If you want dashboards, alerts, per-feature unit economics, or chargeback, the raw material is the same on every platform: log the usage fields from every response into your own cost store.

The fields to capture

Four token counters cover billing:

FieldWhat it countsBilled at
input_tokensInput after the last cache breakpointBase input price
cache_creation_input_tokensTokens written to the prompt cache1.25x (5m) or 2x (1h) input price
cache_read_input_tokensTokens served from cache0.1x input price
output_tokensEverything generated, including thinkingOutput price

Total input processed is the sum of the first three — a common FinOps bug is logging only input_tokens and concluding that caching made traffic disappear. Also worth storing: usage.output_tokens_details.thinking_tokens (the reasoning share of output; always ≤ output_tokens, which remains the authoritative billing total), usage.service_tier (whether the request ran Priority, standard, or batch), and usage.inference_geo where data residency's 1.1x multiplier applies.

A minimal capture wrapper

from anthropic import AnthropicFoundry

client = AnthropicFoundry(api_key=KEY, resource="my-resource")

def log_usage(resp, tags):
    u = resp.usage
    emit_event({  # to your queue / warehouse
        **tags,
        "model": resp.model,
        "input_tokens": u.input_tokens,
        "cache_write": u.cache_creation_input_tokens or 0,
        "cache_read": u.cache_read_input_tokens or 0,
        "output_tokens": u.output_tokens,
    })

The response shape, including usage, is consistent across the Claude API, Claude Platform on AWS, Bedrock's current Messages surface, Vertex AI, and Foundry — so one wrapper serves a multi-platform estate.

Streaming and other edge cases

Streaming: usage arrives incrementally in message_delta events, and the counts are cumulative — log the final values at message_stop, don't sum the deltas.

Server-side compaction: if you use the compaction beta, the top-level token counts do not include compaction iterations; sum everything in usage.iterations for the true billed total.

Batches: results stream back as a .jsonl file — parse each line's usage into the same event schema, and record the batch context so the 50% discount is applied when you convert to dollars.

Failures: refused structured-output requests return HTTP 200 with stop_reason: "refusal" and are billed; log them. Expired batch requests are not billed.

Converting tokens to dollars

Store tokens raw and convert to currency at query time using a versioned price table — prices change (Sonnet 5's introductory $2/$10 rate ends August 31, 2026, moving to $3/$15) and modifiers stack (batch 50%, cache multipliers, 1.1x US-only inference, 10% regional-endpoint premium on Bedrock/Vertex). Baking dollars into events at write time makes historical data wrong every time the price list moves.

Keep the events granular. It is tempting to pre-aggregate to hourly sums to save storage, but per-request events are what let you answer the questions that actually save money later: which feature has the fattest prompts, which sessions blow past your token budget, whether cache reads are actually dominating after a deploy. Token-count events are tiny relative to the value of the queries they enable; aggregate in views, not at ingestion.

What the response can't tell you

Two things need estimating before the call rather than logging after it. For pre-flight budget checks, the free token-counting endpoint (POST /v1/messages/count_tokens) accepts the same inputs as message creation and returns an estimate — with its own generous rate limits, separate from message creation. And when migrating models, re-baseline everything: Opus 4.7-and-later models and Sonnet 5 use a newer tokenizer that produces roughly 30% more tokens for the same text, so week-over-week token comparisons across a model migration are apples to oranges unless you annotate the cutover in your data.

Reconcile against the source of truth: on the Claude API, the Admin Usage API (/v1/organizations/usage_report/messages, data typically visible within 5 minutes) and Cost API give the official org-level numbers — your event store should match them. Note these endpoints are not available on Claude Platform on AWS or the other cloud platforms, where the marketplace bill and cloud-native monitoring are the reference instead.

Where to go next

Add attribution dimensions with request tagging, then build alerts per cost anomaly alerting. The token bill anatomy article decodes each line item.

Sources