usage-cost-analytics-api changedmanage-claude/usage-cost-analytics-api
Nearest release: v2.1.314, published 6 hours after this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
## Quick start ## How results are shaped ### Actors ## Usage endpoint ## Cost endpoint ## Date ranges and time buckets ## Data freshness ## Migrate from the Usage and Cost API ## Migrate from the Claude Enterprise usage and cost reports ## Frequently asked questions ### How is the default workspace represented? ### How do I get per-user cost for Claude Code? ## See also
The whole hunk
1584 lines, new pageA whole new page. There's nothing to diff it against, so here is what it says.
---
title: Usage and Cost Analytics API
url: https://platform.claude.com/docs/en/manage-claude/usage-cost-analytics-api
description: Query token usage and cost for your Claude Console or Claude Enterprise organization by model, workspace, API key, actor, and more.
---
<Tip>
**The Admin API is unavailable for individual accounts.** To collaborate with teammates and add members, set up your organization on the [Organization](https://platform.claude.com/settings/organization) page (`platform.claude.com/settings/organization`) in the Claude Console.
</Tip>
The Usage and Cost Analytics API reports historical token usage and cost for your organization, broken down by the dimensions you choose, such as model, workspace, API key, or the user or service account behind each request. For Claude Console organizations, this data is similar to what the [Usage](https://platform.claude.com/usage) and [Cost](https://platform.claude.com/cost) pages of the Claude Console show.
The API has two endpoints:
* `GET /v1/organizations/analytics/usage` reports token counts and request counts.
* `GET /v1/organizations/analytics/cost` reports cost in USD.
The Usage and Cost Analytics API is in beta. Send the `anthropic-beta: analytics-usage-cost-2026-08-24` header and an [`anthropic-version`](https://platform.claude.com/docs/en/api/versioning) header on every request. The SDK and the `ant` CLI send both headers for you and fetch the remaining pages as you read the results, so `limit` sets only the page size.
Use this API to:
* **Attribute spend:** Break down cost and token usage by workspace, API key, model, service tier, or the identity that made each request.
* **Find top consumers:** Rank results by tokens, requests, or cost to answer questions such as “which API keys spend the most this month?”
* **Build time series:** Split results into daily, hourly, or per-minute buckets for dashboards and finance reports.
* **Integrate once:** The same endpoints, parameters, and response fields serve Claude Console and Claude Enterprise organizations.
<Check>
**Authentication**
Claude Console organizations use an [Admin API key](https://platform.claude.com/docs/en/manage-claude/admin-api-keys#create-a-key-for-a-claude-console-organization) or another [Admin API credential](https://platform.claude.com/docs/en/manage-claude/admin-api#authentication), such as an OAuth token with the `org:admin` scope. Send an OAuth token in an `authorization: Bearer` header instead of the `x-api-key` header; see [Obtain an OAuth bearer token](https://platform.claude.com/docs/en/manage-claude/admin-api#oauth-bearer-token).
Claude Enterprise organizations use a key with the `read:analytics` scope, created in claude.ai by the primary owner after the Analytics API is enabled for the organization; see [Get access to the Claude Enterprise Analytics API](https://platform.claude.com/docs/en/manage-claude/analytics-api#get-access-to-the-claude-enterprise-analytics-api).
The examples on this page read a key from the `ANTHROPIC_API_KEY` environment variable, so set it to your key before you run them.
If you call these endpoints with an Admin API key, give the service that collects this data its own key, store it in a secrets manager, and rotate it regularly; setting a [key expiration](https://platform.claude.com/docs/en/manage-claude/authentication#key-expiration) when you create the key enforces the rotation. Where you can, use a [Workload Identity Federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation) rule with the [`org:admin` scope](https://platform.claude.com/docs/en/manage-claude/wif-reference#oauth-scopes) instead, so the service gets short-lived tokens and there’s no long-lived key to leak.
</Check>
<Note>
**Claude Platform on AWS:** Both endpoints are available. Requests use the Claude Platform on AWS base URL and authentication in place of an Admin API key (see [Making requests](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws#making-requests)), and AWS IAM authorizes them through the [`ListAccountUsage` and `ListAccountCost` actions](https://platform.claude.com/docs/en/api/claude-platform-on-aws-iam-actions#usage-and-cost). Each request covers only the workspaces in the AWS region of the endpoint you call, so call each region’s endpoint to cover your whole organization. `user_profile_id`, `claude_tag_category`, `claude_tag_user_id`, and the Claude Managed Agents dimensions (`agent_id`, `environment_id`, `deployment_id`, and `session_id`) are `null` on every row.
</Note>
<Note>
**Claude Models on Google Cloud (Anthropic managed):** Both endpoints are available. Call them through the [organization-level base URL](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#making-requests) with Google Cloud credentials instead of an Admin API key. The `/usage` endpoint needs the `usageAnalytics.list` [IAM permission](https://platform.claude.com/docs/en/api/claude-models-on-google-cloud-anthropic-managed-iam-permissions), and the `/cost` endpoint needs `costAnalytics.list`.
</Note>
## Quick start
Get daily token usage for the first week of September, one row for each model and day:
<CodeGroup>
```bash cURL
curl --globoff "https://api.anthropic.com/v1/organizations/analytics/usage?\
starting_at=2026-09-01T00:00:00Z&\
ending_at=2026-09-08T00:00:00Z&\
time_bucket_width=1d&\
group_by[]=model&\
limit=10" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: analytics-usage-cost-2026-08-24" \
-H "x-api-key: $ANTHROPIC_API_KEY"
```
```bash CLI
ant beta:organization:analytics:usage list \
--starting-at 2026-09-01T00:00:00Z \
--ending-at 2026-09-08T00:00:00Z \
--time-bucket-width 1d \
--group-by model \
--limit 10
```
```python Python
client = anthropic.Anthropic()
rows = client.beta.organization.analytics.usage.list(
starting_at="2026-09-01T00:00:00Z",
ending_at="2026-09-08T00:00:00Z",
time_bucket_width="1d",
group_by=["model"],
limit=10,
)
for row in rows:
print(f"{row.starting_at} {row.group.model}: {row.usage.total_tokens}")
```
```typescript TypeScript
const client = new Anthropic();
const rows = await client.beta.organization.analytics.usage.list({
starting_at: "2026-09-01T00:00:00Z",
ending_at: "2026-09-08T00:00:00Z",
time_bucket_width: "1d",
group_by: ["model"],
limit: 10
});
for await (const row of rows) {
console.log(`${row.starting_at} ${row.group.model}: ${row.usage.total_tokens}`);
}
```
```csharp C#
using Anthropic.Models.Beta.Organization.Analytics;
using Anthropic.Models.Beta.Organization.Analytics.Usage;
AnthropicClient client = new();
var page = await client.Beta.Organization.Analytics.Usage.List(
new()
{
StartingAt = DateTimeOffset.Parse("2026-09-01T00:00:00Z"),
EndingAt = DateTimeOffset.Parse("2026-09-08T00:00:00Z"),
TimeBucketWidth = BetaAnalyticsTimeBucketWidth.Day,
GroupBy = [BetaAnalyticsUsageGroupBy.Model],
Limit = 10,
}
);
await foreach (var row in page.Paginate())
{
Console.WriteLine($"{row.StartingAt} {row.Group.Model}: {row.Usage.TotalTokens}");
}
```
```go Go
client := anthropic.NewClient()
rows := client.Beta.Organization.Analytics.Usage.ListAutoPaging(context.Background(), anthropic.BetaOrganizationAnalyticsUsageListParams{
StartingAt: time.Date(2026, time.September, 1, 0, 0, 0, 0, time.UTC),
EndingAt: anthropic.Time(time.Date(2026, time.September, 8, 0, 0, 0, 0, time.UTC)),
TimeBucketWidth: anthropic.BetaAnalyticsTimeBucketWidthDay,
GroupBy: []anthropic.BetaAnalyticsUsageGroupBy{anthropic.BetaAnalyticsUsageGroupByModel},
Limit: anthropic.Int(10),
})
for rows.Next() {
row := rows.Current()
fmt.Printf("%s %s: %d\n", row.StartingAt.Format(time.RFC3339), row.Group.Model, row.Usage.TotalTokens)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
```
```java Java
import com.anthropic.models.beta.organization.analytics.BetaAnalyticsTimeBucketWidth;
import com.anthropic.models.beta.organization.analytics.usage.BetaAnalyticsUsageGroupBy;
import com.anthropic.models.beta.organization.analytics.usage.UsageListParams;
import java.time.OffsetDateTime;
void main() {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
var params = UsageListParams.builder()
.startingAt(OffsetDateTime.parse("2026-09-01T00:00:00Z"))
.endingAt(OffsetDateTime.parse("2026-09-08T00:00:00Z"))
.timeBucketWidth(BetaAnalyticsTimeBucketWidth.DAY)
.addGroupBy(BetaAnalyticsUsageGroupBy.MODEL)
.limit(10)
.build();
var rows = client.beta().organization().analytics().usage().list(params);
for (var row : rows.autoPager()) {
IO.println(row.startingAt() + " " + row.group().model().orElse(null) + ": " + row.usage().totalTokens());
}
}
```
```php PHP
$client = new Client();
$rows = $client->beta->organization->analytics->usage->list(
startingAt: new \DateTimeImmutable('2026-09-01T00:00:00Z'),
endingAt: new \DateTimeImmutable('2026-09-08T00:00:00Z'),
timeBucketWidth: '1d',
groupBy: ['model'],
limit: 10,
);
foreach ($rows->pagingEachItem() as $row) {
$startingAt = $row->startingAt->format(\DateTimeInterface::ATOM);
echo "{$startingAt} {$row->group->model}: {$row->usage->totalTokens}\n";
}
```
```ruby Ruby
client = Anthropic::Client.new
page = client.beta.organization.analytics.usage.list(
starting_at: Time.utc(2026, 9, 1),
ending_at: Time.utc(2026, 9, 8),
time_bucket_width: :"1d",
group_by: [:model],
limit: 10
)
page.auto_paging_each do |row|
puts "#{row.starting_at} #{row.group.model}: #{row.usage.total_tokens}"
end
```
</CodeGroup>
The response has one row for each model and day that has usage, largest `total_tokens` first. This example shows a single row:
```json
{
"data": [
{
"starting_at": "2026-09-03T00:00:00Z",
"ending_at": "2026-09-04T00:00:00Z",
"group": {
"product": null,
"model": "claude-sonnet-5",
"context_window": null,
"inference_geo": null,
"speed": null,
"slack_channel_id": null,
"claude_tag_category": null,
"claude_tag_user_id": null,
"rbac_group_id": null,
"workspace_id": null,
"service_tier": null,
"user_profile_id": null,
"agent_id": null,
"environment_id": null,
"deployment_id": null,
"session_id": null,
"actor": null,
"actor_type": null,
"api_key_id": null
},
"usage": {
"uncached_input_tokens": 1284500,
"cache_creation": {
"ephemeral_1h_input_tokens": 0,
"ephemeral_5m_input_tokens": 215300
},
"cache_read_input_tokens": 3200000,
"output_tokens": 891000,
"total_tokens": 5590800,
"server_tool_use": {
"web_search_requests": 12
},
"requests": 4210
}
}
],
"has_more": true,
"next_page": "page_V2mQ4dkt9HcbX3pLr...",
"data_refreshed_at": "2026-09-18T16:02:11Z"
}
```
<Tip>
**Set a User-Agent header for integrations**
If you’re building an integration, set your User-Agent header to help Anthropic understand usage patterns:
```text wrap
User-Agent: YourApp/1.0.0 (https://yourapp.com)
```
</Tip>
## How results are shaped
* **Every row has three parts:** `starting_at` and `ending_at` give the period the row covers, `group` holds every dimension, and `usage` (or `cost` on the cost endpoint) holds the metrics.
* **Dimensions are null unless grouped:** A dimension in `group` is `null` unless you list it in `group_by[]`. A grouped dimension is also `null` on rows that have no value for it, such as `model` on code execution usage. `group_by[]` takes up to five dimensions.
* **One row for each combination:** Each row is one combination of the grouped dimensions, and every combination that has usage or cost appears exactly once across the pages of a query. With no `group_by[]` and no `time_bucket_width`, the response is a single row that totals the whole range.
* **Time buckets are optional:** Set `time_bucket_width` to `1m`, `1h`, or `1d` to split each combination by UTC bucket; each row’s `starting_at` and `ending_at` are then its bucket’s bounds. Buckets with no usage or cost produce no rows.
* **Ranked by default:** Rows are ordered by the `order_by` metric across the whole range, largest first by default (`order=asc` reverses it). To build a time series, set `time_bucket_width` and `order_by=time`. Rows then come back one time bucket after another, newest bucket first by default (`order=asc` puts the oldest first), with the largest rows first within each bucket. Fill empty buckets with zeros.
* **Filters work alongside grouping:** Most dimensions you can group by have a matching list filter in bracket notation, such as `models[]=claude-opus-5-5`. Repeat the parameter to pass several values, up to 100. Multiple values for the same filter are combined with OR, and different filters are combined with AND. Filters and `group_by[]` are independent; you can filter by any dimension with or without grouping by it, or the reverse.
Dimensions such as `model` and `actor` apply to every organization. Some, such as `api_key_id`, apply only to Claude Console organizations, and others, such as `slack_channel_id`, apply only to Claude Enterprise organizations. A dimension that doesn’t apply to your organization is `null` on every row and its filter matches nothing; the exception is `rbac_group_id`, which returns an error instead when teams aren’t available to your organization. The [usage](https://platform.claude.com/docs/en/api/beta/organization/analytics/usage/list) and [cost](https://platform.claude.com/docs/en/api/beta/organization/analytics/cost/list) API reference lists every dimension, filter, and value.
### Actors
The `actor` dimension is who a request is attributed to: a user, a service account, a federated cloud identity (an AWS or Google Cloud principal, for organizations that access Claude through their cloud platform), or, when none of those is behind the request, the API key itself. When you group by `actor`, each row’s `actor` is an object whose `type` says which kind it is. Usage that can’t be attributed to any identity has `actor: null`.
[Personal keys and service account keys](https://platform.claude.com/docs/en/manage-claude/authentication#key-types) act as the user or service account they’re linked to, so their requests show that identity as the `actor` and the key in `api_key_id`. Legacy workspace keys aren’t linked to an identity, so the key appears as both the `actor` and the `api_key_id`. The exception is the key Claude Code creates when a member signs in with their Claude Console account: it lives in the [Claude Code workspace](https://platform.claude.com/docs/en/manage-claude/workspaces#claude-code-workspace), and its usage is attributed to that member. Requests made without an API key, such as from the Claude Console or with a [Workload Identity Federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation) token, have `api_key_id: null`; a federated workload’s `actor` is its service account. To include usage with no API key in an `api_key_ids[]` filter, add an empty entry: `api_key_ids[]=`.
The `api_key_ids[]` and `actor_ids[]` filters answer different questions. `api_key_ids[]=apikey_...` matches every request the key authenticated, whoever it is attributed to. `actor_ids[]=apikey_...` matches only requests attributed to the key itself.
## Usage endpoint
`GET /v1/organizations/analytics/usage` returns token counts by type. `order_by` accepts `total_tokens` (the default), `output_tokens`, `uncached_input_tokens`, `requests`, or `time`.
For example, to see a week of usage for one workspace and one API key, broken down by service tier (one row for each tier, covering the whole week):
<CodeGroup>
```bash cURL
curl --globoff "https://api.anthropic.com/v1/organizations/analytics/usage?\
starting_at=2026-09-01T00:00:00Z&\
ending_at=2026-09-08T00:00:00Z&\
workspace_ids[]=wrkspc_01JwQvzr7rXLA5AGx3HKfFUJ&\
api_key_ids[]=apikey_01Rj2N8SVvo6BePZj99NhmiT&\
group_by[]=service_tier" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: analytics-usage-cost-2026-08-24" \
Cut at 300 lines. The page has the rest.
No line in this hunk matches that.