Claude Usage and Cost Analytics API: Attribute Spend by Key and User
TL;DR
The Claude Usage and Cost Analytics API beta reports token usage and cost by model, workspace, API key and user. How it works, the limits, and how to migrate.
Last updated: October 29, 2026
Anthropic launched the Usage and Cost Analytics API in beta on October 29, 2026. It has one usage endpoint and one cost endpoint that report historical token usage and spend for a Claude Console or Claude Enterprise organization. You can group and filter by model, workspace, API key, service tier, and the user or service account behind each request. It is the API to use for chargeback, "which key spent the most this month" alerts, and per-user Claude Code cost. The older Usage and Cost API is now legacy but still supported.
Tracing shows you individual requests. This shows you the bill. If you already export spans, our Claude API OpenTelemetry tracing guide covers the per-request side.
What shipped#
From the Claude Platform release notes for October 29 and the Usage and Cost Analytics API docs:
- Two endpoints:
GET /v1/organizations/analytics/usagereturns token and request counts, andGET /v1/organizations/analytics/costreturns cost in USD. - Beta header:
anthropic-beta: analytics-usage-cost-2026-08-24, plusanthropic-version, on every request. The SDK and theantCLI send both and fetch the remaining pages as you iterate. - One API for both org types. The same endpoints, parameters and fields serve Claude Console and Claude Enterprise organizations. Some dimensions apply to only one of them:
api_key_idis Console-only, andslack_channel_idis Enterprise-only. - Legacy status. The Usage and Cost API, and the
usage_report,cost_report,user_usage_reportanduser_cost_reportendpoints of the Claude Enterprise Analytics API, are now legacy. All of them remain supported. - Cloud paths too. Both endpoints work on Claude Platform on AWS, authorized by IAM, and on Claude Models on Google Cloud (Anthropic managed), with the
usageAnalytics.listandcostAnalytics.listIAM permissions.
Authentication#
- Claude Console: an Admin API key, or an OAuth token with the
org:adminscope sent asauthorization: Bearer. The docs recommend a dedicated key in a secrets manager with an expiration set. Better still, use a Workload Identity Federation rule withorg:admin, so the collector gets short-lived tokens. - Claude Enterprise: a key with the
read:analyticsscope, created in claude.ai by the primary owner after the Analytics API is enabled. - AWS: each request covers only the workspaces in that region's endpoint, so call each region. Some dimensions, including
user_profile_idand the Managed Agents ones, arenullthere.
How results are shaped#
Every row has a time range (starting_at, ending_at), a group object holding every dimension, and a usage or cost object holding the metrics. The rules that matter:
- Dimensions are
nullunless grouped. List the ones you want ingroup_by[], up to five. With nogroup_by[]and no time bucket, you get one row that totals the whole range. - Rows are ranked, not chronological. By default rows come back largest first by the
order_bymetric. For a time series, settime_bucket_width(1m,1hor1d) andorder_by=time, and fill empty buckets with zeros yourself, because buckets with no usage produce no rows. - Filters are independent of grouping. Most dimensions have a list filter in bracket notation, such as
models[]=claude-opus-5-5, with up to 100 values. Values within one filter are ORed, and different filters are ANDed. An unknown ID or a misspelled model name matches nothing, with no error. - Actors.
actoris who a request is attributed to: a user, a service account, a federated cloud identity, or the API key itself when no identity is behind it.api_key_ids[]matches every request a key authenticated, whileactor_ids[]=apikey_...matches only requests attributed to the key itself. - Cost amounts are cents.
cost.amount, the cost after discounts and before credits, andcost.list_amountare decimal strings in cents with six decimal places:"41280.000000"is $412.80. The cost endpoint also acceptsgroup_by[]=cost_typeandgroup_by[]=token_type, which don't count toward the five-dimension limit.
Attribute a month of spend#
This example ranks API keys by September cost, then runs the docs' recommended query for per-user Claude Code cost (products[]=claude_code&group_by[]=actor):
import Anthropic from "@anthropic-ai/sdk";
// An Admin API key (Console) or a read:analytics key (Enterprise).
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_ADMIN_KEY });
const analytics = client.beta.organization.analytics;
// Top API keys by cost for September. Amounts are decimal strings in cents.
const byKey = await analytics.cost.list({
starting_at: "2026-09-01T00:00:00Z",
ending_at: "2026-10-01T00:00:00Z",
group_by: ["api_key_id"],
limit: 20,
});
for await (const row of byKey) {
const dollars = Number(row.cost.amount) / 100;
console.log(row.group.api_key_id, `$${dollars.toFixed(2)}`, `${row.cost.requests} requests`);
}
// Per-user Claude Code cost, the docs' recommended query.
const claudeCode = await analytics.cost.list({
starting_at: "2026-09-01T00:00:00Z",
ending_at: "2026-10-01T00:00:00Z",
products: ["claude_code"],
group_by: ["actor"],
});
for await (const row of claudeCode) {
console.log(row.group.actor, row.cost.amount);
}
We type-checked this with tsc --strict against @anthropic-ai/sdk 1.3.0 and did not run it against a live organization. The group_by values are a closed union, so a typo such as "api_key" fails to compile. That catches the "filter matches nothing silently" problem for grouping, though not for filter values.
Limits that shape your queries#
- Date range:
starting_atmust be on or after January 1, 2026 and within the last 365 days. One request spans at most 31 days, and at most 24 hours with1mbuckets.ending_atis required whenever you set a bucket width. Split longer ranges into several requests. - Rounding: both ends round down to a bucket boundary, or to the hour with no bucket.
- Paging:
limitis rows per page, from 1 to 1,000, default 20. - Freshness: data typically lands within 4 hours and can take up to 24. Every response has
data_refreshed_at, and usage after it is missing or partial. Values can be revised until about 7 days after the month ends, so October 1 can change until about November 7. For stable dashboards, setending_atat or before adata_refreshed_atyou've already seen. For finance, query only months that ended at least 7 days ago.
That freshness is the biggest change from the legacy API, where data typically appeared within 5 minutes. Don't build a real-time spend alarm on this endpoint. Use it for daily and monthly reporting, and use spend limits for hard stops.
Migrating from the legacy Usage and Cost API#
Your Admin API key, anthropic-version, starting_at/ending_at, bucket values, bracket notation, pagination field names, and token and cost field names all carry over. The migration guide lists what changes. The ones most likely to break a report:
| Legacy | New |
|---|---|
| No beta header | anthropic-beta: analytics-usage-cost-2026-08-24 |
bucket_width, default 1d | time_bucket_width, no default. Omit it for whole-range totals |
data is time buckets, oldest first, empty ones included | data is ranked rows. Combinations with no usage have no row |
limit counts time buckets | limit counts rows (1 to 1,000) |
| Any date range | On or after Jan 1, 2026, within 365 days, at most 31 days per request |
account_ids[], service_account_ids[] | actor_ids[], with group_by[]=actor or actor_type |
| Unknown key or workspace ID returns an error | It matches nothing |
Default workspace is workspace_id: null | The default workspace's real wrkspc_ ID |
Cost amount like "123.45" | Six decimal places plus list_amount |
To reproduce the old daily report: request time_bucket_width=1d with the same group_by[] and order_by=time&order=asc, page with limit=1000, group rows by starting_at, and fill missing days with zeros. Enterprise customers on the old usage_report and cost_report endpoints have a separate migration section.
What people are actually saying#
- The beta launched today and we found no Hacker News or Reddit thread on it yet.
- The trade-off to plan around is in the migration table: richer attribution (actors, five dimensions, request counts, code execution rows) in exchange for data that is hours behind rather than minutes. If your current alerting depends on the legacy API's five-minute freshness, keep it running. It is still supported.
FAQ#
What is the Claude Usage and Cost Analytics API?#
A beta Admin API with /v1/organizations/analytics/usage and /v1/organizations/analytics/cost. It reports token usage and cost by model, workspace, API key, user and more, for Console and Enterprise organizations.
Which header does it need?#
anthropic-beta: analytics-usage-cost-2026-08-24 and anthropic-version. The SDKs send both.
How fresh is the data?#
Usually within 4 hours and at most 24. Values can be revised until about 7 days after the month ends.
Is the old Usage and Cost API going away?#
It is legacy now but still supported, and so are the Enterprise report endpoints.
How do I get Claude Code cost per user?#
Use the cost endpoint with products[]=claude_code&group_by[]=actor.
Continue Reading#
- Claude API OpenTelemetry Tracing: How to Set It Up (Beta) - per-request visibility to pair with monthly cost
- Claude on Google Cloud, Anthropic Managed: Setup and SDK Guide - one of the platforms these endpoints now cover
- Claude Code Usage Limits in 2026: The Practical Playbook - when interactive limits, not spend, are the constraint
Sources#
Get the next deep dive like this in your inbox
One email a week on Anthropic and the rest of the AI dev stack. Free.
Read next on Claude Code
Claude API OpenTelemetry Tracing: How to Set It Up (Beta)
The Claude API exports OpenTelemetry traces in beta. Set up SDK spans in TypeScript or Python, add a Console destination for API spans, and count tokens once.
20 min readClaude on Google Cloud, Anthropic Managed: Setup and SDK Guide
Claude Models on Google Cloud (Anthropic managed) is the full Claude API behind Google Cloud IAM and billing. Setup, the 2 services, IAM roles and SDK code.
8 min readClaude Code Usage Limits in 2026: The Practical Playbook for Pro and Max Teams
Claude Code usage limits are mostly an ops problem. A playbook for Pro and Max teams: lock auth mode, bound subagents, add hooks and route work by difficulty.
9 min readTechnical content at the intersection of AI and development. Building with AI agents, Claude Code, and modern dev tools - then showing you exactly how it works.







