What the Anthropic usage and cost APIs actually give you
The Anthropic usage and cost admin APIs are real and useful, but they answer a different question than the one you are asking. They report aggregates at the organization level and the workspace level, and you can slice those by model, by api key, and by workspace.
What you cannot slice by is your end user. There is no user dimension in that data, because Anthropic has no concept of your customers. They see api keys and workspaces, not the person on plan Pro who ran forty long chats yesterday. So the usage API answers how much did my org spend, never which of my customers spent it.
Why per user attribution has to live in your code
Here is the structural reason, and it is the whole article in one sentence: every request goes through one api key, so the only place your user id exists is in your own code.
When your backend calls the Messages API on behalf of a customer, you know exactly who that customer is. Anthropic does not, and cannot. The moment you multiplex thousands of users through a single credential, the per user view stops being something you fetch and becomes something you instrument. You capture the user id at call time and pair it with the token counts Claude hands back.
This is the same wall you hit with any provider. If you have already dealt with track AI costs per user for OpenAI or Gemini, the shape is identical here.
Read the usage object on every Claude response
Every Messages API response carries a usage object with the token counts for that call. Read it right after the request returns:
import anthropic
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Summarize this ticket."}],
)
print(message.usage)
# Usage(input_tokens=812, output_tokens=143,
# cache_creation_input_tokens=0, cache_read_input_tokens=0)There are four fields, and you should know what each one means before you turn them into dollars.
input_tokens and output_tokens
input_tokens is the prompt you sent, and output_tokens is what Claude generated. These two are the backbone of per user cost. On a plain call with no caching, they are the whole story.
cache_creation_input_tokens and cache_read_input_tokens
The other two only matter once you use prompt caching. cache_creation_input_tokens is the portion of the prompt written into the cache on this call, and cache_read_input_tokens is the portion served from an existing cache entry.
The catch that trips people up: when caching is active, input_tokens counts only the uncached remainder. The cached parts are reported separately in the two cache fields, not folded into input_tokens. So your true prompt size is the sum of all three input style fields, and each is priced differently: cache writes cost more than base input, cache reads cost about a tenth of it.
Attribute the tokens to a user
Now capture those counts with the user id attached and turn them into cost. A single table with user_id, model, input_tokens, output_tokens, cost_usd, and created_at is enough to answer the question the usage API never could. Here it is in Python:
PRICES = { # USD per 1,000,000 tokens
"claude-haiku-4-5": {"in": 1, "out": 5},
"claude-sonnet-4-6": {"in": 3, "out": 15},
"claude-opus-4-8": {"in": 5, "out": 25},
}
def cost_usd(model, u):
p = PRICES[model]
# cache reads are ~0.1x input; cache writes ~1.25x input (5m ttl)
cached_read = u.cache_read_input_tokens * p["in"] * 0.1
cached_write = u.cache_creation_input_tokens * p["in"] * 1.25
base = u.input_tokens * p["in"] + u.output_tokens * p["out"]
return (base + cached_read + cached_write) / 1_000_000
model = "claude-sonnet-4-6"
db.ai_usage.insert(
user_id=request.user.id, # you have this; Anthropic does not
model=model,
input_tokens=message.usage.input_tokens,
output_tokens=message.usage.output_tokens,
cost_usd=cost_usd(model, message.usage),
created_at=datetime.utcnow(),
)And the same thing in TypeScript, reading the same fields off the response:
import Anthropic from '@anthropic-ai/sdk'
const anthropic = new Anthropic()
const PRICES = { // USD per 1,000,000 tokens
'claude-haiku-4-5': { in: 1, out: 5 },
'claude-sonnet-4-6': { in: 3, out: 15 },
'claude-opus-4-8': { in: 5, out: 25 },
} as const
function costUsd(model: keyof typeof PRICES, u: Anthropic.Usage): number {
const p = PRICES[model]
const cachedRead = (u.cache_read_input_tokens ?? 0) * p.in * 0.1
const cachedWrite = (u.cache_creation_input_tokens ?? 0) * p.in * 1.25
const base = u.input_tokens * p.in + u.output_tokens * p.out
return (base + cachedRead + cachedWrite) / 1_000_000
}
const model = 'claude-sonnet-4-6'
const message = await anthropic.messages.create({
model,
max_tokens: 1024,
messages,
})
await db.aiUsage.insert({
userId: req.user.id, // you have this; Anthropic does not
model,
inputTokens: message.usage.input_tokens,
outputTokens: message.usage.output_tokens,
costUsd: costUsd(model, message.usage),
createdAt: new Date(),
})Group that table by user_id over the month and sort descending. The rows at the top are where your Claude bill comes from. That is the answer the Anthropic usage API structurally cannot return, and you just built it from data you already had.
Where the manual version breaks at scale
The code above works. It also has three cracks that widen as you grow, and every founder who tracks usage by hand eventually hits them.
First, coverage. That insert runs only where you remembered to add it. A call wrapped in a helper, a retry path, a streaming endpoint, or a new feature written by a teammate can skip the logging entirely, and the missed spend just vanishes from your numbers without any error.
Second, you only have cost, not margin. The table tells you a user cost you nine dollars in Claude tokens. It does not know that user pays you five, so it cannot tell you they are unprofitable. Cost without the revenue side is half the picture. Closing that gap means joining subscriptions and prorating plan changes, which is its own source of edge cases. See margin per user for the math.
Third, no alerts. A runaway agent loop or one user hammering Opus can burn your budget for hours before the table shows anything, because nothing is watching it in real time. You find out when the monthly bill lands.
Track Claude usage and margin per user with Weckr
Weckr wraps your existing Anthropic client so the logging, the pricing, and the revenue side all happen for you. You add the user id and the plan once, at the call site, and wk.chat(anthropic, { ..., userId: user.id, plan: user.plan }) records cost and margin per user server side from current pricing:
import Anthropic from '@anthropic-ai/sdk'
import { Weckr } from '@weckr/sdk'
const anthropic = new Anthropic()
const wk = new Weckr({
apiKey: process.env.WECKR_API_KEY,
plans: { free: 0, pro: 29, business: 99 },
})
const message = await wk.chat(anthropic, {
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages,
userId: user.id,
feature: 'assistant',
plan: user.plan,
})Because the recompute runs server side, a leaked or wrong client cost never poisons your numbers, and the same path covers OpenAI, Anthropic, and Gemini with token counts normalized. You also get loop detection and per user spending caps that catch the runaway before the bill does. Try it on seeded data at the live demo, and the two line setup lives in the Weckr docs.
FAQ
Does the Anthropic usage API break spending down by end user?
No. The Anthropic usage and cost admin APIs aggregate at the organization and workspace level, sliced by model, api key, and workspace. They answer how much your org spent, not which of your customers spent it. Anthropic never sees your user ids, so per user attribution has to be built on your side from the token counts on each response.
How do I read Anthropic token usage from a Claude response?
Every Messages API response carries a usage object. Read message.usage right after the call returns. It has four fields: input_tokens, output_tokens, cache_creation_input_tokens, and cache_read_input_tokens. Store the ones you need next to your user id, then compute cost from your pricing table.
What are the four fields in the Claude usage object?
input_tokens is the uncached prompt, output_tokens is what Claude generated, cache_creation_input_tokens is the prompt portion written to the cache this call, and cache_read_input_tokens is the portion served from cache. When you use prompt caching, input_tokens counts only the uncached part and the two cache fields are separate line items.
How much does the Claude API cost in 2026?
As of July 2026, per million tokens (input then output): Haiku 4.5 is 1 and 5, Sonnet 4.6 is 3 and 15, and Opus 4.8 is 5 and 25. Cache reads are roughly 0.1x the input price. Output usually dominates a real bill, so the output rate matters most. Confirm current numbers on the Anthropic pricing page before you rely on them.
Why not just parse the Anthropic usage API into per user numbers?
You cannot, because the usage API has no user dimension to parse. It aggregates by org, workspace, model, and api key only. Your user id exists in exactly one place: your own code at the moment you make the call. That is why per user tracking is instrumentation you add, not a report you fetch.
Keep reading
Turn the org total into a per user answer
The Anthropic usage API will always report a total. It has no user axis to give you one, so the per user view is yours to build from the token counts on every Claude response. Read the usage object, attribute it to the id you already hold, and add the revenue side to get margin instead of just cost. This is one step in the complete guide to AI cost and margin management. For the cost angle on the same numbers, see Claude API cost per user, and for the billing side, how Anthropic billing works.