---
title: User Cost Report
url: https://platform.claude.com/docs/en/api/go/beta/organization/analytics/user_cost_report
---

# User Cost Report

## Get Per-User Cost

`client.Beta.Organization.Analytics.UserCostReport.List(ctx, query) (*PageCursor[BetaAnalyticsCostUsersItem], error)`

**GET** `/v1/organizations/analytics/user_cost_report`

Get per-user cost in USD across a date range.

Returns one row per user, ranked by spend. Use this to see which users
account for the most cost. Only cost attributable to a seat user is
included; for organization-wide totals including direct API-key and
automation traffic, use the bucketed
`/v1/organizations/analytics/cost_report` endpoint. Available to
organizations on a Claude Enterprise plan. Requires an API key with the
`read:analytics` scope.

### Parameters

- `query BetaOrganizationAnalyticsUserCostReportListParams`

  - `StartingAt Time` (query parameter)

    Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.

    format: date-time

  - `BucketWidth BetaOrganizationAnalyticsUserCostReportListParamsBucketWidth Optional` (query parameter)

    Time-bucket granularity. When set, each row's `starting_at` and `ending_at` are populated and one actor may span several rows (one per time bucket with usage). The time bucket counts toward `limit`, so one page can return multiple rows for the same actor. `ending_at` is required when `bucket_width` is set, and with `bucket_width="1m"` the range may span at most 24 hours. When omitted, each row aggregates the full `[starting_at, ending_at)` range.

    - `const BetaOrganizationAnalyticsUserCostReportListParamsBucketWidthDay BetaOrganizationAnalyticsUserCostReportListParamsBucketWidth = "1d"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsBucketWidthHour BetaOrganizationAnalyticsUserCostReportListParamsBucketWidth = "1h"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsBucketWidthMinute BetaOrganizationAnalyticsUserCostReportListParamsBucketWidth = "1m"`

  - `ClaudeTagCategories []BetaAnalyticsClaudeTagCategory Optional` (query parameter)

    Filter to Claude Tag (Claude in Slack) usage in specific spend categories. Usage with no category never matches. `dm` usage is reported under the user's product rather than `claude-tag`, so combining this filter with `products[]=claude-tag` excludes it. Use `group_by[]=claude_tag_category` to break out per-category values.

    maxItems: 100

    - `const BetaAnalyticsClaudeTagCategoryDm BetaAnalyticsClaudeTagCategory = "dm"`

    - `const BetaAnalyticsClaudeTagCategoryEngaged BetaAnalyticsClaudeTagCategory = "engaged"`

    - `const BetaAnalyticsClaudeTagCategoryMonitoring BetaAnalyticsClaudeTagCategory = "monitoring"`

    - `const BetaAnalyticsClaudeTagCategoryProactive BetaAnalyticsClaudeTagCategory = "proactive"`

    - `const BetaAnalyticsClaudeTagCategoryScheduled BetaAnalyticsClaudeTagCategory = "scheduled"`

  - `ClaudeTagUserIDs []string Optional` (query parameter)

    Filter to Claude Tag (Claude in Slack) usage attributed to specific Slack users, by Slack user ID (for example `U0123ABCDEF`), not claude.ai user ID. Usage that is not Claude Tag, and Claude Tag usage not attributed to a single user, never matches. Use `group_by[]=claude_tag_user_id` to break out per-user values.

    maxItems: 100

  - `ContextWindows []BetaAnalyticsContextWindow Optional` (query parameter)

    Filter to specific context-window pricing tiers. Use `group_by[]=context_window` to break out per-tier values.

    maxItems: 100

    - `const BetaAnalyticsContextWindowFrom0To200k BetaAnalyticsContextWindow = "0-200k"`

    - `const BetaAnalyticsContextWindowFrom200kTo1M BetaAnalyticsContextWindow = "200k-1M"`

  - `EndingAt param.Opt[Time] Optional` (query parameter)

    End of range, exclusive. When omitted, defaults to the earlier of now and `starting_at` + 31 days. The range may span at most 31 days.

    format: date-time

  - `ExcludeDeletedUsers param.Opt[bool] Optional` (query parameter)

    If true, omit rows for users who are deleted (`deleted: true`). A page may contain fewer than `limit` rows; use `has_more` and `next_page` to paginate as usual.

  - `GroupBy []string Optional` (query parameter)

    Break each actor's row out by the given dimensions. Accepts the same values as the bucketed `/cost_report` endpoint. The `product`, `model`, `context_window`, `inference_geo`, and `speed` dimensions — and the time bucket, when `bucket_width` is set — count toward `limit`. `cost_type` and `token_type` do not: `cost_type` returns one row per cost component (tokens, web search, code execution); `token_type` returns one row per token type, each with `cost_type: "tokens"`; combining both returns the per-token-type rows plus the web-search and code-execution rows. A page can therefore contain more rows than `limit` when `cost_type` or `token_type` is requested.

    maxItems: 100

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByClaudeTagCategory BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "claude_tag_category"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByClaudeTagUserID BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "claude_tag_user_id"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByContextWindow BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "context_window"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByCostType BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "cost_type"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByInferenceGeo BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "inference_geo"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByModel BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "model"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByProduct BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "product"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByRBACGroupID BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "rbac_group_id"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupBySlackChannelID BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "slack_channel_id"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupBySpeed BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "speed"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsGroupByTokenType BetaOrganizationAnalyticsUserCostReportListParamsGroupBy = "token_type"`

  - `InferenceGeos []BetaAnalyticsInferenceGeoFilter Optional` (query parameter)

    Filter to specific inference regions. `not_available` matches rows where the region is unset. Use `group_by[]=inference_geo` to break out per-region values.

    maxItems: 100

    - `const BetaAnalyticsInferenceGeoFilterGlobal BetaAnalyticsInferenceGeoFilter = "global"`

    - `const BetaAnalyticsInferenceGeoFilterNotAvailable BetaAnalyticsInferenceGeoFilter = "not_available"`

    - `const BetaAnalyticsInferenceGeoFilterUs BetaAnalyticsInferenceGeoFilter = "us"`

  - `Limit param.Opt[int64] Optional` (query parameter)

    Number of rows per page (1-1000, default 20). One row per actor unless `group_by[]` or `bucket_width` splits an actor across rows; `cost_type`/`token_type` fan-out rows (cost endpoint only) are the exception — they do not count toward this limit, so `data` can exceed it.

    minimum: 1, maximum: 1000

  - `Models []string Optional` (query parameter)

    Models to include. Defaults to all models. Use `group_by[]=model` to break out per-model values.

    maxItems: 100

  - `Order BetaOrganizationAnalyticsUserCostReportListParamsOrder Optional` (query parameter)

    Sort direction. Defaults to `desc`.

    - `const BetaOrganizationAnalyticsUserCostReportListParamsOrderAsc BetaOrganizationAnalyticsUserCostReportListParamsOrder = "asc"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsOrderDesc BetaOrganizationAnalyticsUserCostReportListParamsOrder = "desc"`

  - `OrderBy BetaOrganizationAnalyticsUserCostReportListParamsOrderBy Optional` (query parameter)

    Metric to rank actors by. Defaults to `amount`.

    - `const BetaOrganizationAnalyticsUserCostReportListParamsOrderByAmount BetaOrganizationAnalyticsUserCostReportListParamsOrderBy = "amount"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsOrderByListAmount BetaOrganizationAnalyticsUserCostReportListParamsOrderBy = "list_amount"`

  - `Page param.Opt[string] Optional` (query parameter)

    Opaque cursor from a previous response's `next_page` field.

  - `Products []BetaAnalyticsProductFilter Optional` (query parameter)

    Product surfaces to include. Defaults to all products.

    maxItems: 100

    - `const BetaAnalyticsProductFilterChat BetaAnalyticsProductFilter = "chat"`

    - `const BetaAnalyticsProductFilterChatCoworkUnified BetaAnalyticsProductFilter = "chat_cowork_unified"`

    - `const BetaAnalyticsProductFilterClaudeTag BetaAnalyticsProductFilter = "claude-tag"`

    - `const BetaAnalyticsProductFilterClaudeCode BetaAnalyticsProductFilter = "claude_code"`

    - `const BetaAnalyticsProductFilterClaudeDesign BetaAnalyticsProductFilter = "claude_design"`

    - `const BetaAnalyticsProductFilterClaudeInChrome BetaAnalyticsProductFilter = "claude_in_chrome"`

    - `const BetaAnalyticsProductFilterCowork BetaAnalyticsProductFilter = "cowork"`

    - `const BetaAnalyticsProductFilterOfficeAgent BetaAnalyticsProductFilter = "office_agent"`

  - `RBACGroupIDs []string Optional` (query parameter)

    Filter to usage attributed to specific RBAC groups. Accepts tagged RBAC group IDs (`rbac_group_...`) or bare group UUIDs. A row matches when the user belonged to any of the listed groups on the (UTC) day the usage occurred; usage with no group attribution never matches.

    maxItems: 100

  - `SlackChannelIDs []string Optional` (query parameter)

    Filter to usage originating from specific Slack channels. Use `group_by[]=slack_channel_id` to break out per-channel values.

    maxItems: 100

  - `Speeds []string Optional` (query parameter)

    Filter to fast or standard inference mode. Use `group_by[]=speed` to break out per-mode values.

    maxItems: 100

    - `const BetaOrganizationAnalyticsUserCostReportListParamsSpeedFast BetaOrganizationAnalyticsUserCostReportListParamsSpeed = "fast"`

    - `const BetaOrganizationAnalyticsUserCostReportListParamsSpeedStandard BetaOrganizationAnalyticsUserCostReportListParamsSpeed = "standard"`

  - `UserIDs []string Optional` (query parameter)

    Filter to specific users by tagged user ID.

    maxItems: 100

### Returns

- `type BetaAnalyticsCostUsersItem`

  - `Actor BetaAnalyticsUserActor`

    The user this row's usage or cost is attributed to. Always a `user_actor`.

    - `Type UserActor`

      Actor type. Always `"user_actor"`.

    - `Deleted bool`

      True when the account has been deleted, or when the user is no longer a member of the organization or its associated organizations (for example, their membership was removed or they were deprovisioned via your identity provider). `email_address` stays populated for removed users and is null when the account has been deleted. `name` follows the rules described on that field. The `user_id` is still populated for reconciliation.

    - `EmailAddress string`

      The user's email address, including for users who are no longer members of the organization or its associated organizations. Null when the account has been deleted (check `deleted`) and for system-minted service accounts, which have no person's mailbox behind them (check `name`).

    - `Name string`

      The user's full name. Null when the user has not set a name. Returns `"Deleted User"` when the account itself has been deleted, or when the user is no longer a member of the organization or its associated organizations and the organization has chosen to hide the names of removed users. Otherwise, the name stays populated for removed users. Rows for system-minted service accounts render the service name (for example, `"Claude Security"` for usage by Anthropic's security-patching service) or null.

    - `UserID string`

      Tagged user ID.

  - `Amount string`

    Amount (post-discount, pre-credit) in fractional cents (minor units).

  - `ClaudeTagCategory BetaAnalyticsClaudeTagCategory`

    Claude Tag (Claude in Slack) spend category: `engaged` (a person addressed Claude in a channel or thread), `proactive` (Claude responded without being addressed), `scheduled` (a scheduled routine ran), `monitoring` (Claude watching a channel it was asked to monitor), or `dm` (direct messages with Claude). Populated only when `claude_tag_category` is in `group_by[]`; null for usage that is not Claude Tag. Direct-message usage is billed to the individual user and is reported under that user's product, not under `claude-tag`. New categories may be added over time.

    - `const BetaAnalyticsClaudeTagCategoryDm BetaAnalyticsClaudeTagCategory = "dm"`

    - `const BetaAnalyticsClaudeTagCategoryEngaged BetaAnalyticsClaudeTagCategory = "engaged"`

    - `const BetaAnalyticsClaudeTagCategoryMonitoring BetaAnalyticsClaudeTagCategory = "monitoring"`

    - `const BetaAnalyticsClaudeTagCategoryProactive BetaAnalyticsClaudeTagCategory = "proactive"`

    - `const BetaAnalyticsClaudeTagCategoryScheduled BetaAnalyticsClaudeTagCategory = "scheduled"`

  - `ClaudeTagUserID string`

    Slack user ID (for example `U0123ABCDEF`) of the member the Claude Tag (Claude in Slack) usage is attributed to, not a claude.ai user ID. Populated only when `claude_tag_user_id` is in `group_by[]`; null for usage that is not Claude Tag and for Claude Tag usage that is not attributed to a single user (for example `monitoring`, and `proactive` usage Claude initiated), so per-user rows can sum to less than the Claude Tag total. Cannot be combined with `group_by[]=rbac_group_id` or the `rbac_group_ids[]` filter.

  - `ContextWindow BetaAnalyticsContextWindow`

    Context-window pricing tier of the usage or cost. Null unless `context_window` is in `group_by[]`; it can also be null on grouped rows with no context-window tier, such as code execution.

    - `const BetaAnalyticsContextWindowFrom0To200k BetaAnalyticsContextWindow = "0-200k"`

    - `const BetaAnalyticsContextWindowFrom200kTo1M BetaAnalyticsContextWindow = "200k-1M"`

  - `CostType BetaAnalyticsCostType`

    Cost component breakdown; null when returning the combined total.

    - `const BetaAnalyticsCostTypeCodeExecution BetaAnalyticsCostType = "code_execution"`

    - `const BetaAnalyticsCostTypeTokens BetaAnalyticsCostType = "tokens"`

    - `const BetaAnalyticsCostTypeWebSearch BetaAnalyticsCostType = "web_search"`

  - `Currency string`

    Currency code for the cost amount. Currently always `"USD"`.

    default: USD

  - `EndingAt Time`

    End of the row's UTC time bucket (exclusive), as an RFC 3339 timestamp; equal to `starting_at` plus one `bucket_width`. Null unless `bucket_width` is set.

    format: date-time

  - `InferenceGeo BetaAnalyticsCostUsersItemInferenceGeo`

    Inference region of the usage or cost. Null unless `inference_geo` is in `group_by[]`; it can also be null on grouped rows where the region is not set (the rows that `inference_geos[]=not_available` matches).

    - `const BetaAnalyticsCostUsersItemInferenceGeoGlobal BetaAnalyticsCostUsersItemInferenceGeo = "global"`

    - `const BetaAnalyticsCostUsersItemInferenceGeoUs BetaAnalyticsCostUsersItemInferenceGeo = "us"`

  - `ListAmount string`

    List-price amount (pre-discount) in fractional cents.

  - `Model string`

    Model that produced the usage or cost, as a model name in the form the `models[]` filter accepts (for example, `claude-opus-5-5`). Null unless `model` is in `group_by[]`; it can also be null on grouped rows whose usage or cost is not attributed to a specific model, such as code execution.

  - `Product string`

    Product surface that produced the usage or cost. Null unless product is in `group_by[]`; it can also be null on grouped rows whose usage cannot be attributed to a known surface. Values include `chat`, `claude_code`, `cowork`, `office_agent`, `claude_in_chrome`, `claude_design`, `claude-tag`, and `chat_cowork_unified`. `claude-tag` is Claude Tag, the Claude product in Slack. `chat_cowork_unified` is Chat and Cowork unified, Cowork's features inside claude.ai chat: chat and Cowork usage by a member who has it turned on is reported under this value instead of `chat` or `cowork`. It is accepted as a filter only on deployments that offer Chat and Cowork unified. Some unattributed usage is reported as "other".

  - `RBACGroupID string`

    RBAC group (team) the usage is attributed to, in the public tagged `rbac_group_...` spelling — the same spelling the activity resources use for this key, so the same team has one id across resources and it round-trips as an `rbac_group_ids[]` filter value. Populated only when `rbac_group_id` is in `group_by[]`. Any-membership semantics: a user in several groups contributes their full usage to each of those groups' rows, so the named-group rows overlap and their sum can exceed the org total. A null value is the single unassigned row: users in no group on that (UTC) day. For the true org total, run the same query without `group_by[]`.

  - `Requests int64`

    Number of API requests in this row's scope. Null when `group_by` includes `cost_type` or `token_type` (the count has no per-component attribution; read it from the ungrouped response). For sandbox / code-execution events, this counts execution spans rather than HTTP requests (these rows surface with `product: null`).

  - `SlackChannelID string`

    Slack channel the usage originated from. Populated only when `slack_channel_id` is in `group_by[]`; null for usage outside Slack (and for rows recorded before channel attribution was enabled).

  - `Speed BetaAnalyticsCostUsersItemSpeed`

    Inference speed mode of the usage or cost: `fast` or `standard`. Null unless `speed` is in `group_by[]`.

    - `const BetaAnalyticsCostUsersItemSpeedFast BetaAnalyticsCostUsersItemSpeed = "fast"`

    - `const BetaAnalyticsCostUsersItemSpeedStandard BetaAnalyticsCostUsersItemSpeed = "standard"`

  - `StartingAt Time`

    Start of the row's UTC time bucket (inclusive), as an RFC 3339 timestamp. Null unless `bucket_width` is set; without `bucket_width`, each row aggregates the full requested range.

    format: date-time

  - `TokenType BetaAnalyticsTokenType`

    Token type when `cost_type` is `tokens`; null otherwise.

    - `const BetaAnalyticsTokenTypeCacheCreationEphemeral1hInputTokens BetaAnalyticsTokenType = "cache_creation.ephemeral_1h_input_tokens"`

    - `const BetaAnalyticsTokenTypeCacheCreationEphemeral5mInputTokens BetaAnalyticsTokenType = "cache_creation.ephemeral_5m_input_tokens"`

    - `const BetaAnalyticsTokenTypeCacheReadInputTokens BetaAnalyticsTokenType = "cache_read_input_tokens"`

    - `const BetaAnalyticsTokenTypeOutputTokens BetaAnalyticsTokenType = "output_tokens"`

    - `const BetaAnalyticsTokenTypeUncachedInputTokens BetaAnalyticsTokenType = "uncached_input_tokens"`

### Example

```go
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/anthropics/anthropic-sdk-go"
	"github.com/anthropics/anthropic-sdk-go/option"
)

func main() {
	client := anthropic.NewClient(
		option.WithAPIKey("my-anthropic-api-key"),
	)
	page, err := client.Beta.Organization.Analytics.UserCostReport.List(context.TODO(), anthropic.BetaOrganizationAnalyticsUserCostReportListParams{
		StartingAt: time.Now(),
	})
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("%+v\n", page)
}
```

#### Response (200)

```json
{
  "data": [
    {
      "actor": {
        "deleted": true,
        "email": "jane@example.com",
        "email_address": "jane@example.com",
        "name": "Jane Smith",
        "type": "user_actor",
        "user_id": "user_01AbCdEfGhIjKlMnOpQrSt"
      },
      "amount": "41280.000000",
      "claude_tag_category": "dm",
      "claude_tag_user_id": "U0123ABCDEF",
      "context_window": "0-200k",
      "cost_type": "code_execution",
      "currency": "USD",
      "ending_at": "2019-12-27T18:11:19.117Z",
      "inference_geo": "global",
      "list_amount": "51600.000000",
      "model": "claude-opus-5-5",
      "product": "chat",
      "rbac_group_id": "rbac_group_012rppKaSVsmTo6NqRDXQXNF",
      "requests": 128,
      "slack_channel_id": "C0123ABCDEF",
      "speed": "fast",
      "starting_at": "2019-12-27T18:11:19.117Z",
      "token_type": "cache_creation.ephemeral_1h_input_tokens"
    }
  ],
  "data_refreshed_at": "2019-12-27T18:11:19.117Z",
  "has_more": true,
  "next_page": "next_page",
  "organization_id": "org_013FP9SaFPBg7Kw7fetjn6cF"
}
```
