What You Need to Know
Every response from the Claude API contains a usage object. It splits the tokens the request used into separate counts. Input tokens are what you send, and output tokens are what Claude generates. Each count has its own price per token. Prompt caching stores a stable opening part of the prompt, the prefix, so later requests can reuse it. Storing it is a cache write, and reusing it is a cache read. A breakpoint marks where the cached prefix ends. A cache entry lasts for a set lifetime. A lever is any change that lowers the bill, such as caching, batching or a cheaper model.
This lesson uses one made-up example throughout: an invoicing software company that runs two Claude features. A help assistant inside the product uses the company's fixed user guide to answer customer questions. Every request re-sends that long guide and receives a short answer. A release-notes writer turns a few lines of developer notes into long release notes once a week. Some customers chat with the assistant for many turns while they configure their first invoice. The team wants to reduce the bill.
The Bill Is a Handful of Token Counts, Each at Its Own Rate
A cost model does arithmetic on the usage object and multiplies the result by real traffic. Anthropic's method prices each token count in the response's usage at its own rate. Then it sums the results across the task's requests. The top-level counts are input_tokens, cache_creation_input_tokens, cache_read_input_tokens and output_tokens. The cache_creation object splits the cache writes by lifetime: 5-minute writes and 1-hour writes. cache_creation_input_tokens is their sum. The two lifetimes have different prices, so the code below prices each one at its own rate. Claude Haiku 5.5 is priced by prompt length. A request whose prompt is over 100,000 tokens pays higher prices. The prompt length includes cache reads and cache writes. The sample rates below are prices in US dollars per million tokens (Mtok).
import json
# {"<model-id>": {"input": <usd per Mtok>, "cache_write_5m": <usd per Mtok>,
# "cache_write_1h": <usd per Mtok>, "cache_read": <usd per Mtok>,
# "output": <usd per Mtok>,
# "over_100k": {<the same five keys>}}} # only for a model priced by prompt length
# Standard rates. The Batch API discount and data residency pricing stack on top.
RATES = json.load(open("rates.json"))
def request_cost(model, usage):
r = RATES[model]
writes = usage.cache_creation # the cache writes, split by lifetime
writes_5m = writes.ephemeral_5m_input_tokens if writes else 0
writes_1h = writes.ephemeral_1h_input_tokens if writes else 0
reads = usage.cache_read_input_tokens or 0
prompt = usage.input_tokens + writes_5m + writes_1h + reads
if prompt > 100_000 and "over_100k" in r: # Claude Haiku 5.5 is priced by prompt length
r = r["over_100k"]
return (
usage.input_tokens * r["input"]
+ writes_5m * r["cache_write_5m"]
+ writes_1h * r["cache_write_1h"]
+ reads * r["cache_read"]
+ usage.output_tokens * r["output"]
) / 1_000_000Nearly every later decision depends on two facts. First, on every model, output costs several times as much as input. A workload that generates a lot relative to what it sends is output-dominated. A workload that sends a lot relative to what it generates is input-dominated. Each needs a different fix. Second, input_tokens is not all of the input. It counts only the tokens after the last cache breakpoint. On a cached request, the real input volume is the sum of all three input fields. If a team reads only input_tokens on a heavily cached workload, it will conclude that its prompt shrank when it did not.
So before you choose a lever, identify which axis dominates: input or output. If a workload re-sends a long fixed prefix hundreds of times a day and gets short answers, it has an input problem. Shortening the answers optimises the wrong axis. The help assistant is this kind of workload. A workload that sends two hundred tokens and generates four thousand has an output problem, and caching its prompt changes almost nothing. The release-notes writer is this kind of workload. Anthropic bills thinking tokens as output, and the response reports them under output_tokens_details.thinking_tokens. So a reasoning-heavy workload is output-dominated even when its visible answers are short. Do the arithmetic on one representative day of real traffic, not on one request. The mix of input and output in real traffic decides the answer.
Tracking Cost per Feature
Attribution means linking each cost to the feature that spent it. Without per-feature attribution, nobody can show that an optimisation worked. Tracking has three layers.
Per request, log the counts beside the request id and a workload label. Log successes as well as failures. The company labels each request as the help assistant or the release-notes writer, so the two costs stay separate.
import json, logging
log = logging.getLogger("usage")
def record(model, feature, response):
u = response.usage
log.info(json.dumps({
"request_id": response._request_id, # the only key shared with support
"feature": feature, # what makes aggregation meaningful
"model": model,
"input_tokens": u.input_tokens,
"cache_creation_input_tokens": u.cache_creation_input_tokens,
"cache_read_input_tokens": u.cache_read_input_tokens,
"output_tokens": u.output_tokens,
"cost_usd": request_cost(model, u),
}))Per feature, aggregate the logs. Then set an alert on the ratio you expect: a cache hit rate, an input-to-output ratio, a cost per completed task. The alert should then show a regression before the regression appears on an invoice.
Per organisation, the Usage and Cost Admin API is the authoritative source of aggregate data. Its /v1/organizations/usage_report/messages endpoint tracks "uncached input, cached input, cache creation, and output tokens". It reports them in buckets of a minute, an hour or a day. You can filter and group them "by API key, workspace, model, service tier, context window, data residency, or speed". The /v1/organizations/cost_report endpoint returns service-level cost breakdowns in USD. The Usage and Cost API is now a legacy API that remains supported. New integrations should use the Usage and Cost Analytics API. Anthropic states the reason to prefer this API over your own logs. In Anthropic's words, the reason is: "Get precise token counts and usage patterns instead of relying solely on response token counting". The other reason is to reconcile costs against Anthropic billing. The API needs an Admin API key, not a standard key. The docs also say the Admin API "isn't available to organizations on the claude.ai Team plan or to individual Claude Console accounts". Data typically appears within five minutes. The supported sustained polling rate is once a minute.
Three instruments do three different jobs. The token counting endpoint prices a request before you send it. The usage object reports what one request consumed. The Usage and Cost API aggregates spend across the organisation. Before the company launches a new assistant prompt, it would count tokens. It would read usage to calculate the cost of one reply. It would use the Usage and Cost API to see both features together.
When Caching Pays
Caching costs are asymmetric. A cache write costs more than sending the same tokens uncached. A cache read costs a fraction of the uncached price. The break-even follows from those two prices. Caching saves money after a single cache read at the shorter lifetime, or after two cache reads at the longer lifetime.
So caching saves money when your requests re-send a large, stable prefix often enough within its lifetime to cover the cost of the write.
- Large. Prompts below the model's minimum cacheable length "are processed without caching" and return no error. Caching a small prefix has no effect, and the minimum varies by model.
- Stable. The cached prefix must match byte for byte. Anything volatile before the breakpoint reduces the hit rate to zero without warning. Examples are a timestamp, a per-request identifier, an unsorted serialised object or a varying tool list.
- Often enough. A prefix that you use once loses money. You pay the write premium and never get the read discount.
- Within its lifetime. The lifetime is "measured from the start of the request that writes or reads the cache entry, not from response end". The lifetime "is refreshed at no additional cost each time cached content is used". Generation time also uses part of the lifetime. A response that streams for several minutes uses most of the shorter lifetime before the next request begins.
The company's user guide meets these tests if it is long enough. The reason is that the assistant sends it with every question, many times within each lifetime. If the assistant put a timestamp at the top of the prompt, before the breakpoint, every request would miss the cache. The release-notes writer sends its notes once, so they fail the "often enough" test.
Choosing the longer lifetime is an economic decision. The longer lifetime costs more to write. It recovers that extra cost on the first miss that it prevents. The reason is that a miss re-sends the whole prefix at full price and writes it again. So the longer lifetime is right for loops that wait for a person between turns. The invoice-configuration chat is one such loop.
Verifying is part of the change. Check the read count on each response:
response = client.messages.create(**request)
if response.usage.cache_read_input_tokens == 0:
log.warning("cache miss on a prefix that should be stable: %s", response._request_id)A zero where you expected a hit indicates something that invalidates the cache without warning, not a pricing surprise. The guidance says: "In Anthropic's measurements, prompt caching was usually the largest lever."
Current-state note (August 2026)
The domain quick reference holds the dated figures used to calculate the break-even, because a release can change any of them. The figures are the write and read multipliers relative to the base input price, and the two cache lifetimes. They also include the per-model minimum cacheable length and the maximum number of explicit breakpoints. The relations between the prices do not change. A write costs more than not caching, and a read costs a fraction. The longer lifetime costs more to write than the shorter one. Remember these relations, and find the numbers in the quick reference.
Checkpointing a Growing Conversation
Checkpointing means choosing where the breakpoint sits when the prefix grows every turn. The API renders a request in a fixed order: tools, then system, then messages. A change at one level invalidates that level and everything after it. In a growing conversation, the transcript of earlier turns is the stable part and the new turn is the volatile part. The breakpoint belongs at the boundary between them. The breakpoint must move forward as that boundary moves. In the invoice-configuration chat, each customer reply moves the boundary forward by one turn. Automatic caching moves the breakpoint forward for you. On each turn, the previous turn becomes part of the read prefix, and only the newest content is written.
With explicit breakpoints, you place them yourself. Two limits affect the design. A request contains at most a small fixed number of breakpoints. From each breakpoint, the system searches backwards through a bounded number of blocks for earlier cache entries. If a conversation grows past the last write by more than that lookback window, it will miss the cache. The fix is a second breakpoint. Place it closer, and from the start, so that writes accumulate there before they are needed.
The remaining choices are economic. A checkpoint placed before volatile content is wasted, because the volatile content invalidates everything after it on every request. Anything inserted into the middle of a cached prefix invalidates everything after the insertion point. So appending is cheap and editing history is expensive. For the same reason, it is best to do a context-editing pass in a few large batches, not many small ones.
Configuration is also part of the prefix. The API renders the thinking configuration and the resolved effort level into the prompt itself. So a change to the thinking configuration starts a new prefix, and a change to the effort level can do the same. A switch between fast and standard speed also starts a new prefix. As of 14 November 2026, the exception is a per-message effort change, which is in beta on the models that support it. Put a system message with empty content and a new output_config.effort level after Claude's last reply. Send it with the mid-conversation-output-config-2026-07-01 beta header. The new level takes effect from the next user turn that has new input. A user turn that holds only tool results does not count. The system message leaves everything before it unchanged, so the cached prefix still matches. In this way, the routine later turns of a long conversation cost less, without paying to write the cache again.
Put material that does not change first, and everything that varies after the last breakpoint. Change the configuration at points where the cache is written again anyway, not in the middle of a conversation. Then use cache_read_input_tokens to confirm that the prefix was not invalidated. For the company, that means the user guide first, the earlier chat next and the customer's new message last.
The Levers, in Order
Anthropic splits the levers into two groups. Free wins "cut spend without touching quality". Anthropic lists five:
- prompt caching
- token hygiene (pruning stale tool output, retrieving fewer and better passages, removing unneeded transcript and shrinking oversized images)
- a prompt audit against the model you are running
- batch processing at 50% off for work that can wait up to 24 hours
- workspace spend limits as the final safeguard
Trade-offs "exchange cost for intelligence: model choice, effort, output caps and session budgets, an elapsed-time clock, and multi-model architectures". A session budget is a dollar cap on what one Claude Managed Agents session can spend. At the cap, or slightly past it, the platform pauses the session.
Take the free wins first, in that order. Caching was usually the largest lever in Anthropic's measurements. Token hygiene is the plain lever: send less. Batch processing gives its discount in exchange for asynchronous delivery. Route anything that nobody is waiting for through it, and nothing that anybody is waiting for. The weekly release-notes writer can use batch processing. The assistant cannot, because a customer is waiting for each answer. Only then use the trade-offs. Effort is the direct control. A cheaper tier is legitimate for any task that passes an eval, a fixed set of test cases, with a stated pass threshold. That is the subject of 5.3.
max_tokens and Task Budgets
One setting looks like a lever and is not one. As of October 2026 the cost guidance says that max_tokens "caps a single response, invisibly to the model, so lowering it does not make the model economize. The turns that needed the room are discarded and still billed". In Anthropic's internal measurement, a tight cap truncated a large share of attempts. Very few of those still passed. Attempts got cheaper and fewer tasks got solved, so cost per solved task barely changed. If the company halved max_tokens on the release-notes writer, long release notes would stop mid-sentence and still be billed.
The correct approach is the opposite of what instinct suggests. Set max_tokens high enough that nothing is truncated. The page suggests 64,000 for agentic work, or the 128,000 maximum when one truncated attempt is costly. It also says to "treat stop_reason: max_tokens as a failure" and to "save money with effort, which the model can see". Take the saving from levers that the model can react to.
A task budget is one of those levers. As of September 2026, it is a beta, and you set it as task_budget inside output_config. It shows the model a running token countdown for the whole agentic loop. The model then cuts low-value work and finishes, instead of being stopped in the middle of an action. The budget is advisory, and max_tokens stays the hard limit for each request. If you change the task budget in the middle of a task, the change invalidates the cached prefix. So set it once, on the first request. Base its size on your own measured usage per task.
In the exam
The guide's scope is "Token budgeting and cost management techniques for Claude applications, including token usage tracking, cost modeling, and caching techniques (prompt caching, cache check-pointing) for cost optimization". The order in that sentence is the order of the work: model the bill before you optimise it. On almost every question in this sub-skill, the first step is to find which axis dominates.
Domain 2 covers how caching is configured: cache_control breakpoints, the identical-prefix rule and the invalidation mechanics. Domain 5 covers whether caching saves money. The lifetime choice and the verification check belong here, not in 2.3. The guide's own phrase "cache check-pointing" names the breakpoint decision on a growing conversation.
Under tracking, the guide asks about per-feature attribution. An option that offers one of the three instruments for the work of another is wrong. A candidate should be able to say the caching rule in words: a large, stable prefix, re-sent often enough within its lifetime.
Caveats and Sourcing
The quick reference contains the full list of levers. The Task budgets page suggests that you start a task budget at the 99th percentile of your per-task token spend. It then suggests testing higher or lower values.
Exam Traps
Lowering max_tokens to cut cost
The model cannot see the cap, so answers are cut off rather than made more concise, and the discarded tokens are still billed. Cost per attempt falls but cost per solved task does not. Give the model a task budget it can see.
Presenting caching as pure saving, with no write cost
A write costs more than sending the tokens uncached, so a single-use prefix loses money. Caching saves money on a large, stable prefix reused often enough within its lifetime. A prefix below the model minimum is silently not cached.
Optimising the axis that is not the problem
A fixed document with short answers is an input problem; short prompts with long reports is an output problem. input_tokens alone understates a cached request, as it counts only tokens after the last breakpoint. Price the four usage counts, then act on the dominant axis.
Using the token counting endpoint or the monthly invoice to prove a feature's saving
The counting endpoint prices a request before it is sent, the usage object reports what one request consumed, and the Usage and Cost API aggregates spend across the organisation. An invoice cannot isolate one feature. Log per-request usage against a feature label.
Practice Scenario
A travel booking website runs a Claude service that answers questions from its support staff against a fixed 30,000-token booking policy manual. It answers roughly 400 times a day, and each answer is a couple of hundred tokens. Each staff member waits for the reply before continuing with the customer. Queries arrive in clusters through the day rather than evenly. The team's cost-reduction plan is to halve max_tokens and move to the cheapest tier. What should they do instead?
Build Exercise
Put a Price on One Workload, Then Change One Thing at a Time
What you'll learn
- How to price the token counts in usage and find the dominant axis
- How per-feature attribution turns a claimed saving into a measured one
- How to verify a cache hit and diagnose a silent invalidation
- How the cache lifetime interacts with a bursty arrival pattern
- Why lowering max_tokens truncates answers instead of shortening them
- Pick one Claude workload you already run and instrument it: log input_tokens, output_tokens, cache_creation_input_tokens and cache_read_input_tokens beside the request id and a feature name, on every call, success or failure
Why: Nothing later in this exercise is measurable without a per-request record carrying a feature label.
You should see: One structured log line per call, with all the counts present even when most are zero.
- Run a representative day and produce the actual cost split by pricing each count at its own rate. Write down which axis dominates, input or output, before you touch anything
Why: Naming the dominant axis first is what stops you optimising the wrong one, which is the single most common defect this sub-skill tests.
You should see: A per-count cost breakdown and a one-sentence conclusion naming the axis.
- Add a cache breakpoint after your stable prefix and before anything that varies, then re-run the same traffic and record the hit rate, the write and read counts, and the new cost split
Why: Watching creation tokens turn into read tokens is what makes the write premium and read discount concrete rather than abstract.
You should see: Cache creation on the first call and cache reads on the rest, with a lower total.
- Test the lifetime deliberately: send two requests a few seconds apart, then two separated by longer than the shorter lifetime, and compare the usage fields. Work out from your own arrival pattern whether the longer lifetime would recover its higher write cost
Why: A bursty arrival pattern is exactly the case in which the lifetime choice is no longer a configuration detail and becomes a decision about cost.
You should see: Reads on the close pair and a fresh write on the separated pair.
- Change exactly one other thing and re-measure: run the same inputs against one tier down with a twenty-case eval and an explicit pass threshold, in a separate run from the caching change so the two remain separable
Why: Two changes measured together cannot be attributed, which is what makes an invoice the wrong instrument.
You should see: A pass rate and a cost per completed task for the cheaper tier, comparable to your baseline.
- Halve max_tokens on a sample so you can watch the failure yourself: record how many responses come back with stop_reason max_tokens, whether any of them are usable, and what the truncated attempts cost
Why: No explanation removes the belief that a lower cap makes the model concise, but the first measurement shows that it is wrong.
You should see: Truncated answers, unchanged or worse cost per usable answer, and stop_reason max_tokens on a share of the sample.
- Reconcile your own logs against the Usage and Cost API for the same period, grouped by model and API key, and note any gap. Then write down which change saved money, by how much, and which axis it acted on
Why: The reconciliation is what turns your logs into a record that the finance team and you can both trust later.
You should see: Two totals that agree within a small margin, and a one-paragraph verdict per change.
Sources
- Prompt caching — Claude Docs, the cache lifetime, minimum cacheable length, breakpoints, lookback and the invalidation hierarchy
- Pricing — Claude Docs, the cache write and read multipliers, the break-even rule and the batch discount
- Optimizing for cost and intelligence — Claude Docs, the per-count cost method, the lever ranking and the max_tokens finding
- Usage and Cost API — Claude Docs, the usage and cost endpoints, the grouping dimensions and the Admin key requirement
- Token counting — Claude Docs, estimating a request shape before you send it
- Task budgets — Claude Docs, the advisory loop budget the model can see, its interaction with max_tokens and choosing a starting budget
- Batch processing — Claude Docs, the discount and the asynchronous delivery window it trades for
- Messages — Claude Docs, the usage field names including the cache and thinking-token details
- Effort — Claude Docs, why a top-level effort change can invalidate cached prefixes
- Per-message effort — Claude Docs, the per-message effort change that keeps the prompt cache, in beta on select models
- Claude Certified Developer Foundations Exam Guide — Domain 5, Cost and Token Management — Anthropic