One read of Claude Developer Platformapi-20260814T043121Z
565 pages moved out of 565 read.
What this read moved
51-75 of 565, page 3 of 23This capture is too large to show at once. Changes 51-75 of 565 are below, significant first; the rest are on the following screens.
agents-and-tools/tool-use/tool-runner First recorded · 1728 lines, first recorded
## Basic usage ## Iterating over the tool runner ## Advanced usage ### Taking over message history ### Automatic context management ### Debugging tool execution ### Intercepting tool errors ### Modifying tool results ## Streaming ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: Tool runner (SDK)
url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-runner
description: Use the SDK's tool runner to handle the agentic loop, error wrapping, and type safety automatically.
---
The tool runner handles the agentic loop, error wrapping, and type safety so you don't have to. When you need human-in-the-loop approval, custom logging, or conditional execution, use the [manual loop](https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls) instead.
Instead of manually handling tool calls, tool results, and conversation management, the tool runner automatically:
* Runs tools when Claude calls them
* Handles the request/response cycle
* Manages conversation state
* Provides type safety and validation
<Note>
The tool runner is in beta and available in the [Python SDK](https://github.com/anthropics/anthropic-sdk-python/blob/main/tools.md), [TypeScript SDK](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/helpers.md#tool-helpers), [C# SDK](https://github.com/anthropics/anthropic-sdk-csharp/blob/main/examples/ToolRunnerExample/Program.cs), [Go SDK](https://github.com/anthropics/anthropic-sdk-go/blob/main/tools.md), [Java SDK](https://github.com/anthropics/anthropic-sdk-java/blob/main/anthropic-java-example/src/main/java/com/anthropic/example/BetaToolRunnerExample.java), [PHP SDK](https://github.com/anthropics/anthropic-sdk-php/blob/main/examples/beta/beta_tool_runner.php), and [Ruby SDK](https://github.com/anthropics/anthropic-sdk-ruby/blob/main/helpers.md#3-auto-looping-tool-runner-beta).
</Note>
## Basic usage
Define tools using the SDK helpers, then use the tool runner to run them.
Depending on the SDK's tool signature, a tool returns its result as a string or as content blocks (text, image, or document blocks), so a tool can return multimodal results. A returned string becomes a single text content block. To return structured data, such as a JSON object or a number, encode it as a string first.
<Tabs>
<Tab title="Python">
Use the `@beta_tool` decorator to define tools with type hints and docstrings.
<Note>
If you're using the async client, replace `@beta_tool` with `@beta_async_tool` and define the function with `async def`.
</Note>
```python
import json
from anthropic import Anthropic, beta_tool
client = Anthropic()
@beta_tool
def get_weather(location: str, unit: str = "fahrenheit") -> str:
"""Get the current weather in a given location.
Args:
location: The city and state, e.g. San Francisco, CA
unit: Temperature unit, either 'celsius' or 'fahrenheit'
"""
return json.dumps({"temperature": "20°C", "condition": "Sunny"})
@beta_tool
def calculate_sum(a: int, b: int) -> str:
"""Add two numbers together.
Args:
a: First number
b: Second number
"""
return str(a + b)
runner = client.beta.messages.tool_runner(
model="claude-opus-5",
max_tokens=1024,
tools=[get_weather, calculate_sum],
messages=[
{
"role": "user",
"content": "What's the weather like in Paris? Also, what's 15 + 27?",
}
],
)
for message in runner:
print(message)
```
The `@beta_tool` decorator inspects the function arguments and docstring to derive the JSON schema for you.
</Tab>
<Tab title="TypeScript">
Use `betaZodTool()` for type-safe tool definitions with Zod validation, or `betaTool()` for JSON Schema-based definitions.
TypeScript offers two approaches for defining tools:
**Using Zod (recommended)** - Use `betaZodTool()` for type-safe tool definitions with Zod validation (requires Zod 3.25.0 or higher):
```typescript
import Anthropic from "@anthropic-ai/sdk";
import { betaZodTool } from "@anthropic-ai/sdk/helpers/beta/zod";
import { z } from "zod";
const client = new Anthropic();
const getWeatherTool = betaZodTool({
name: "get_weather",
description: "Get the current weather in a given location",
inputSchema: z.object({
location: z.string().describe("The city and state, e.g. San Francisco, CA"),
unit: z.enum(["celsius", "fahrenheit"]).default("fahrenheit").describe("Temperature unit")
}),
run: async (input) => {
return JSON.stringify({ temperature: "20°C", condition: "Sunny" });
}
});
const finalMessage = await client.beta.messages.toolRunner({
model: "claude-opus-5",
max_tokens: 1024,
tools: [getWeatherTool],
messages: [{ role: "user", content: "What's the weather like in Paris?" }]
});
for (const block of finalMessage.content) {
if (block.type === "text") {
console.log(block.text);
}
}
```
**Using JSON Schema** - Use `betaTool()` for type-safe tool definitions without Zod:
<Note>
The input generated by Claude is not validated at runtime. Perform validation inside the `run` function if needed.
</Note>
```typescript
import Anthropic from "@anthropic-ai/sdk";
import { betaTool } from "@anthropic-ai/sdk/helpers/beta/json-schema";
const client = new Anthropic();
const calculateSumTool = betaTool({
name: "calculate_sum",
description: "Add two numbers together",
inputSchema: {
type: "object",
properties: {
a: { type: "number", description: "First number" },
b: { type: "number", description: "Second number" }
},
required: ["a", "b"]
},
run: async (input) => {
return String(input.a + input.b);
}
});
const finalMessage = await client.beta.messages.toolRunner({
model: "claude-opus-5",
max_tokens: 1024,
tools: [calculateSumTool],
messages: [{ role: "user", content: "What's 15 + 27?" }]
});
for (const block of finalMessage.content) {
if (block.type === "text") {
console.log(block.text);
}
}
```
</Tab>
<Tab title="C#">
Define each tool as a `BetaRunnableTool`, providing a `Definition` with a JSON schema and a `Run` delegate that runs when Claude calls the tool.
```csharp
using System.Text.Json;
using Anthropic;
using Anthropic.Helpers.Beta;
using Anthropic.Models.Beta.Messages;
using MessageCreateParams = Anthropic.Models.Beta.Messages.MessageCreateParams;
using InputSchema = Anthropic.Models.Beta.Messages.InputSchema;
using Role = Anthropic.Models.Beta.Messages.Role;
using Model = Anthropic.Models.Messages.Model;
var client = new AnthropicClient();
var getWeatherTool = new BetaRunnableTool
{
Name = "get_weather",
Definition = new BetaTool
{
Name = "get_weather",
Description = "Get the current weather in a given location.",
InputSchema = new InputSchema
{
Properties = new Dictionary<string, JsonElement>
{
["location"] = JsonSerializer.SerializeToElement(
new { type = "string", description = "The city and state, e.g. San Francisco, CA" }
),
},
Required = ["location"],
},
},
Run = (toolUse, _) =>
{
var location = toolUse.Input["location"].GetString();
return Task.FromResult<BetaToolResultBlockParamContent>(
$"Weather in {location}: 20°C, sunny"
);
},
};
var calculateSumTool = new BetaRunnableTool
{
Name = "calculate_sum",
Definition = new BetaTool
{
Name = "calculate_sum",
Description = "Add two numbers together.",
InputSchema = new InputSchema
{
Properties = new Dictionary<string, JsonElement>
{
["a"] = JsonSerializer.SerializeToElement(new { type = "number" }),
["b"] = JsonSerializer.SerializeToElement(new { type = "number" }),
},
Required = ["a", "b"],
},
},
Run = (toolUse, _) =>
{
var a = toolUse.Input["a"].GetDouble();
var b = toolUse.Input["b"].GetDouble();
return Task.FromResult<BetaToolResultBlockParamContent>($"{a + b}");
},
};
var runner = client.Beta.Messages.ToolRunner(
new MessageCreateParams
{
Model = Model.ClaudeOpus5,
MaxTokens = 1024,
Messages =
[
new()
{
Role = Role.User,
Content = "What's the weather like in Paris? Also, what's 15 + 27?",
},
],
},
[getWeatherTool, calculateSumTool]
);
await foreach (var message in runner)
{
Console.WriteLine(message);
}
```
</Tab>
<Tab title="Go">
Define a tool with `toolrunner.NewBetaToolFromJSONSchema`. The handler's input type is a struct with `jsonschema:` tags. The SDK reflects on it to generate the JSON schema.
```go
package main
import (
"context"
"fmt"
"log"
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/toolrunner"
)
type GetWeatherInput struct {
Location string `json:"location" jsonschema:"required,description=The city and state, e.g. San Francisco, CA"`
Unit string `json:"unit,omitempty" jsonschema:"enum=celsius,enum=fahrenheit,description=Temperature unit"`
}
type CalculateSumInput struct {
A int `json:"a" jsonschema:"required,description=First number"`
B int `json:"b" jsonschema:"required,description=Second number"`
}
func main() {
client := anthropic.NewClient()
ctx := context.Background()
getWeather, err := toolrunner.NewBetaToolFromJSONSchema(
"get_weather",
"Get the current weather in a given location.",
func(ctx context.Context, input GetWeatherInput) (anthropic.BetaToolResultBlockParamContentUnion, error) {
return anthropic.BetaToolResultBlockParamContentUnion{
OfText: &anthropic.BetaTextBlockParam{Text: "20°C, Sunny"},
}, nil
},
)
if err != nil {
log.Fatal(err)
}
calculateSum, err := toolrunner.NewBetaToolFromJSONSchema(
"calculate_sum",
"Add two numbers together.",
func(ctx context.Context, input CalculateSumInput) (anthropic.BetaToolResultBlockParamContentUnion, error) {
Cut at 300 lines. The page has the rest.
agents-and-tools/tool-use/tool-search-tool First recorded · 870 lines, first recorded
## Model compatibility ## How tool search works ## Quick start ## Tool definition ### Deferred tool loading ## Response format ### Understanding the response ### Continuing the conversation ## MCP integration ## Custom tool search implementation ## Error handling ### HTTP errors (400 status) ### Tool result errors (200 status) ### Common mistakes ## Prompt caching ## Streaming ## Batch requests ## Limits and best practices ### Limits ### When to use tool search ### Optimization tips ## Usage ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: Tool search tool
url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool
description: Scale to hundreds or thousands of tools by letting Claude search your tool catalog and load only the tools it needs.
---
The tool search tool lets Claude work with hundreds or thousands of tools by discovering and loading them on demand. Instead of loading all tool definitions into the context window up front, Claude searches your tool catalog (including tool names, descriptions, argument names, and argument descriptions) and loads only the tools it needs.
Loading every tool definition up front causes two problems as a tool library grows:
* **Context bloat:** A typical multiserver setup (GitHub, Slack, Sentry, Grafana, and Splunk) can consume \~55k tokens in definitions before Claude does any work. Tool search typically reduces this by over 85 percent, loading only the 3–5 tools Claude needs for a given request.
* **Tool selection accuracy:** Claude's ability to pick the right tool degrades once you exceed 30–50 available tools. Because tool search loads only a focused set of relevant tools on demand, selection accuracy stays high even across thousands of tools.
Tool search is generally available on the Claude API. For supported models, see [Model compatibility](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool#model-compatibility).
<Tip>
For background on the scaling challenges that tool search solves, see [Advanced tool use](https://www.anthropic.com/engineering/advanced-tool-use). Tool search's on-demand loading is also an instance of the broader just-in-time retrieval principle described in [Effective context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents).
</Tip>
Tool search runs as a server-side tool, but you can also implement your own client-side tool search. See [Custom tool search implementation](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool#custom-tool-search-implementation) for details.
<Note>
Share feedback on this feature through the [feedback form](https://forms.gle/MhcGFFwLxuwnWTkYA).
</Note>
<Note>
For how zero data retention (ZDR) applies to this feature, see [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention).
</Note>
<Warning>
On Amazon Bedrock, server-side tool search is available only through the [InvokeModel API](https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-runtime_example_bedrock-runtime_InvokeModel_AnthropicClaude_section.html), not the Converse API.
</Warning>
<Note>
On [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws), server-side tool search works identically to the Claude API. Claude Platform on AWS uses the Anthropic Messages API directly, so there is no InvokeModel or Converse distinction.
</Note>
## Model compatibility
Both tool search variants are available on the following models:
| Model | Tool versions |
| ---------------------------------------------- | ------------------------------------------------------------------- |
| Claude Fable 5 (claude-fable-5) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Mythos 5 (claude-mythos-5) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Opus 5 (claude-opus-5) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Opus 4.8 (claude-opus-4-8) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Opus 4.7 (claude-opus-4-7) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Opus 4.6 (claude-opus-4-6) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Sonnet 4.6 (claude-sonnet-4-6) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Opus 4.5 (claude-opus-4-5-20251101) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Sonnet 4.5 (claude-sonnet-4-5-20250929) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
| Claude Haiku 4.5 (claude-haiku-4-5-20251001) | `tool_search_tool_regex_20251119`, `tool_search_tool_bm25_20251119` |
Claude Opus 4.1 and earlier models don't support the tool search tool.
## How tool search works
There are two tool search variants:
* **Regex** (`tool_search_tool_regex_20251119`): Claude constructs regex patterns to search for tools.
* **BM25** (`tool_search_tool_bm25_20251119`): Claude uses natural language queries to search for tools.
When you enable the tool search tool:
1. You include a tool search tool (for example, `tool_search_tool_regex_20251119` or `tool_search_tool_bm25_20251119`) in your `tools` list.
2. You provide every tool definition in the `tools` array and set `defer_loading: true` on the tools that shouldn't load up front. At least one tool, normally the tool search tool itself, must stay non-deferred.
3. Initially, Claude's context contains only the tool search tool and any non-deferred tools.
4. When Claude needs additional tools, it searches using a tool search tool.
5. The API runs the search and returns the matching tools as `tool_reference` blocks (up to 5 by default; Claude can set a `limit` in its search input).
6. The API automatically expands these references into full tool definitions.
7. Claude selects from the discovered tools and calls them.
## Quick start
The following example includes the tool search tool and two deferred tools:
<CodeGroup>
```bash cURL
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "content-type: application/json" \
--data '{
"model": "claude-opus-5",
"max_tokens": 2048,
"messages": [
{
"role": "user",
"content": "What is the weather in San Francisco?"
}
],
"tools": [
{
"type": "tool_search_tool_regex_20251119",
"name": "tool_search_tool_regex"
},
{
"name": "get_weather",
"description": "Get the weather at a specific location",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string"},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
},
"defer_loading": true
},
{
"name": "search_files",
"description": "Search through files in the workspace",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"},
"file_types": {
"type": "array",
"items": {"type": "string"}
}
},
"required": ["query"]
},
"defer_loading": true
}
]
}'
```
```bash CLI
ant messages create <<'YAML'
model: claude-opus-5
max_tokens: 2048
messages:
- role: user
content: What is the weather in San Francisco?
tools:
- type: tool_search_tool_regex_20251119
name: tool_search_tool_regex
- name: get_weather
description: Get the weather at a specific location
input_schema:
type: object
properties:
location:
type: string
unit:
type: string
enum: [celsius, fahrenheit]
required: [location]
defer_loading: true
- name: search_files
description: Search through files in the workspace
input_schema:
type: object
properties:
query:
type: string
file_types:
type: array
items:
type: string
required: [query]
defer_loading: true
YAML
```
```python Python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
max_tokens=2048,
messages=[{"role": "user", "content": "What is the weather in San Francisco?"}],
tools=[
{"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"},
{
"name": "get_weather",
"description": "Get the weather at a specific location",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
"defer_loading": True,
},
{
"name": "search_files",
"description": "Search through files in the workspace",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string"},
"file_types": {"type": "array", "items": {"type": "string"}},
},
"required": ["query"],
},
"defer_loading": True,
},
],
)
print(response)
```
```typescript TypeScript
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-opus-5",
max_tokens: 2048,
messages: [
{
role: "user",
content: "What is the weather in San Francisco?"
}
],
tools: [
{
type: "tool_search_tool_regex_20251119",
name: "tool_search_tool_regex"
},
{
name: "get_weather",
description: "Get the weather at a specific location",
input_schema: {
type: "object" as const,
properties: {
location: { type: "string" },
unit: {
type: "string",
enum: ["celsius", "fahrenheit"]
}
},
required: ["location"]
},
defer_loading: true
},
{
name: "search_files",
description: "Search through files in the workspace",
input_schema: {
type: "object" as const,
properties: {
query: { type: "string" },
file_types: {
type: "array",
items: { type: "string" }
}
},
required: ["query"]
},
defer_loading: true
}
]
});
console.log(response);
```
```csharp C#
AnthropicClient client = new();
var parameters = new MessageCreateParams
{
Model = Model.ClaudeOpus5,
MaxTokens = 2048,
Messages = [
new() {
Role = Role.User,
Content = "What is the weather in San Francisco?"
}
],
Tools = [
new ToolUnion(new ToolSearchToolRegex20251119
{
Type = ToolSearchToolRegex20251119Type.ToolSearchToolRegex20251119
}),
new ToolUnion(new Tool()
{
Name = "get_weather",
Description = "Get the weather at a specific location",
InputSchema = new InputSchema()
{
Properties = new Dictionary<string, JsonElement>
{
["location"] = JsonSerializer.SerializeToElement(new { type = "string" }),
["unit"] = JsonSerializer.SerializeToElement(new { type = "string", @enum = new[] { "celsius", "fahrenheit" } }),
},
Required = ["location"],
},
DeferLoading = true,
}),
Cut at 300 lines. The page has the rest.
agents-and-tools/tool-use/tool-use-with-prompt-caching First recorded · 106 lines, first recorded
## cache\_control on tool definitions ## defer\_loading and cache preservation ## What invalidates your cache ## Server tool results are cached automatically ## Per-tool interaction table ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: Tool use with prompt caching
url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-use-with-prompt-caching
description: Cache tool definitions across turns and understand what invalidates your cache.
---
This page covers prompt caching for tool definitions: where to place `cache_control` breakpoints, how `defer_loading` preserves your cache, and what invalidates it. For general prompt caching, see [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching).
## cache\_control on tool definitions
Place `cache_control: {"type": "ephemeral"}` on the last tool in your `tools` array. This caches the entire tool-definitions prefix, from the first tool through the marked breakpoint:
```json
{
"tools": [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": { "type": "string" }
},
"required": ["location"]
}
},
{
"name": "get_time",
"description": "Get the current time in a given time zone",
"input_schema": {
"type": "object",
"properties": {
"timezone": { "type": "string" }
},
"required": ["timezone"]
},
"cache_control": { "type": "ephemeral" }
}
]
}
```
For `mcp_toolset`, the `cache_control` breakpoint lands on the last tool in the set. You don't control tool order within an MCP toolset, so place the breakpoint on the `mcp_toolset` entry itself and the API applies it to the final expanded tool.
## defer\_loading and cache preservation
Deferred tools are not included in the system-prompt prefix. When the model discovers a deferred tool through [tool search](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool), the definition is appended inline as a `tool_reference` block in the conversation history. The prefix is untouched, so prompt caching is preserved.
This means adding tools dynamically through tool search does not break your cache. You can start a conversation with a small set of always-loaded tools (cached), let the model discover additional tools as needed, and keep the same cache hit across every turn.
`defer_loading` also acts independently of grammar construction for [strict mode](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use). The grammar builds from the full toolset regardless of which tools are deferred, so prompt caching and grammar caching are both preserved when tools load dynamically.
## What invalidates your cache
The cache follows a prefix hierarchy (`tools` → `system` → `messages`), so a change at one level invalidates that level and everything after it:
| Change | Invalidates |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Modifying tool definitions | Entire cache (tools, system, messages) |
| Toggling web search or citations | System and messages caches |
| Changing `tool_choice` | Messages cache |
| Changing `disable_parallel_tool_use` | Messages cache |
| Toggling images present/absent | Messages cache |
| Changing thinking parameters | Messages cache always; tool and system caches too on models that render the thinking configuration ahead of them ([details](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching)) |
| Changing `output_config.effort` | Same as thinking parameters; setting the model's default explicitly is equivalent to omitting it |
<Note>
If you need to vary `tool_choice` mid-conversation, consider placing cache breakpoints before the variation point.
</Note>
## Server tool results are cached automatically
When your request has prompt caching enabled and Claude uses a [server tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools) such as web search, web fetch, or code execution, the API automatically places a cache breakpoint on the server tool result before running the next iteration of the agentic loop. This lets later iterations within the same request read the growing prefix from cache instead of reprocessing it.
This automatic breakpoint always uses the default 5-minute TTL, independent of any TTL you set on your own `cache_control` markers. In the response `usage`, these writes appear under `cache_creation.ephemeral_5m_input_tokens`, so you may see 5-minute cache writes even when every `cache_control` you set uses a 1-hour TTL.
This behavior only applies when your request already has at least one `cache_control` marker. Requests without prompt caching do not receive the automatic breakpoint.
## Per-tool interaction table
| Tool | Caching considerations |
| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| [Web search](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool) | Enabling or disabling invalidates the system and messages caches |
| [Web fetch](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool) | Enabling or disabling invalidates the system and messages caches |
| [Code execution](https://platform.claude.com/docs/en/agents-and-tools/tool-use/code-execution-tool) | Container state is independent of prompt cache |
| [Tool search](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool) | Discovered tools load as `tool_reference` blocks, preserving prefix cache |
| [Computer use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool) | Screenshot presence affects messages cache |
| [Text editor](https://platform.claude.com/docs/en/agents-and-tools/tool-use/text-editor-tool) | Standard client tool, no special caching interaction |
| [Bash](https://platform.claude.com/docs/en/agents-and-tools/tool-use/bash-tool) | Standard client tool, no special caching interaction |
| [Memory](https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool) | Standard client tool, no special caching interaction |
## Next steps
<CardGroup cols={3}>
<Card title="Prompt caching" icon="database" href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">
Learn the full prompt caching model, including TTLs and pricing.
</Card>
<Card title="Tool search" icon="magnifying-glass" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool">
Load tools on demand without breaking your cache.
</Card>
<Card title="Tool reference" icon="book" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference">
Browse all available tools and their parameters.
</Card>
</CardGroup>
agents-and-tools/tool-use/troubleshooting-tool-use First recorded · 79 lines, first recorded
## Claude calls the wrong tool ## Claude invents tool parameters ## Parallel tool calls don't work ## Cache keeps invalidating ## Errors at request time ## Error: thinking blocks cannot be modified ## Claude flags tool results as prompt injection ## JSON escaping differences (Opus 4.6+) ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: Troubleshooting tool use
url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/troubleshooting-tool-use
description: Fix the most common tool-use errors with symptom-to-fix diagnostic tables.
---
Symptom-to-fix tables for the most common tool-use errors. Each fix cross-references the page that owns the feature.
## Claude calls the wrong tool
| Symptom | Likely cause | Fix |
| ------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Claude calls tool A when you wanted tool B | Description ambiguity | Sharpen descriptions. Differentiate tools by WHEN to use them, not only WHAT they do. See [Define tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools). |
| Claude never calls your tool | Tool name collision or overly-generic schema | Check for duplicate names across your tool list. Add `input_examples` to make the intended use concrete. |
| Claude calls with wrong parameter types | Model guessing at ambiguous schema | Add `strict: true` (if your schema is in the supported subset) or add `input_examples`. |
## Claude invents tool parameters
| Symptom | Likely cause | Fix |
| ------------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| Parameter that doesn't exist in your schema | Model over-generation without strict mode | Add `strict: true` if your schema is in the [supported subset](https://platform.claude.com/docs/en/agents-and-tools/tool-use/strict-tool-use). |
| Parameter values outside your enum | Missing strict mode or too-large enum | Shrink the enum or add `input_examples` showing valid choices. |
## Parallel tool calls don't work
| Symptom | Likely cause | Fix |
| ------------------------------------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Claude calls tools sequentially when parallel would be better | Message history formatting | Send multiple `tool_result` blocks in ONE user message, not one per turn. See [Parallel tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/parallel-tool-use). |
| `disable_parallel_tool_use` seems ignored | Set too late in the conversation | Must be set on the request that returns `tool_use`. Setting it on a later request has no effect on earlier tool calls. |
## Cache keeps invalidating
| Symptom | Likely cause | Fix |
| ------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Every request is a cache miss | `tool_choice`, the thinking configuration, or `output_config.effort` varying between requests | Keep `tool_choice` stable or place the `cache_control` breakpoint before the variation point; hold the thinking configuration and effort level constant for the life of a cached conversation. See [Tool use with prompt caching](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-use-with-prompt-caching) and [Thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching). |
| Adding a tool mid-conversation breaks cache | Tool prepended to the tools array | Use `defer_loading: true` with tool search to append the tool inline instead of modifying the array head. |
## Errors at request time
| Error | Cause | Fix |
| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tool_use ids were found without tool_result blocks immediately after` | Missing `tool_result` for some `tool_use` ids, or `tool_result` is not the first content block in the user message | Return one `tool_result` for every `tool_use` block in the assistant response. Put `tool_result` blocks before any text. See [Handle tool calls](https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls) and [Parallel tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/parallel-tool-use). |
| `was found without a corresponding <name>_tool_result block` | The previous assistant turn has a `server_tool_use` block with no result block (most often, Claude called it alongside a client tool), and either your next user message ended that turn (for example, with text after the `tool_result` blocks) or the resume request no longer defines that server tool (the message then ends with `but no <name> tool was provided`) | Send a user message containing only the `tool_result` blocks for the client `tool_use` ids and keep the same `tools` array. See [Stop reasons and fallback](https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons#tool-use). |
| `Input schema is not compatible with strict mode: string patterns are not supported` | Using `pattern` with `strict: true` | Remove the pattern or drop `strict: true`. The `pattern` keyword is not in the supported JSON Schema subset yet. |
| `All tools have defer_loading: true` | No tools visible to the model | At least one tool must be immediately loaded. The tool search tool itself must never have `defer_loading: true`. |
## Error: thinking blocks cannot be modified
If a request fails with a 400 `invalid_request_error` whose message contains `` `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified `` when continuing a conversation after a tool call, your application is altering the assistant's thinking blocks before sending them back. Send the entire assistant message back unchanged, then append your `tool_result`.
See [Thinking blocks cannot be modified](https://platform.claude.com/docs/en/api/errors#thinking-blocks-cannot-be-modified) for the full error and fix steps.
## Claude flags tool results as prompt injection
| Symptom | Likely cause | Fix |
| -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Claude refuses to act on a tool result, or asks the user to confirm instructions that came from it | Your own instructions are being delivered inside the `tool_result` content | Claude is trained to treat instructions inside tool results as potentially untrusted third-party content. Move your instructions out of the tool result: send them in a `user` turn after the `tool_result` block, or, on supported models, in a [mid-conversation system message](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages). Keep the tool result to just the data. See [Mitigate jailbreaks and prompt injections](https://platform.claude.com/docs/en/test-and-evaluate/strengthen-guardrails/mitigate-jailbreaks#indirect-prompt-injection). |
## JSON escaping differences (Opus 4.6+)
| Symptom | Cause | Fix |
| -------------------------------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| String comparison on tool inputs fails with newer models | Unicode and forward-slash escaping differs between model versions | Parse with `json.loads()` or `JSON.parse()`. Never do raw string matching on serialized input. |
## Next steps
<CardGroup cols={3}>
<Card title="Define tools" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools">
Write schemas and descriptions that steer Claude toward the right tool.
</Card>
<Card title="Handle tool calls" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/handle-tool-calls">
Execute tools and return results in the required message format.
</Card>
<Card title="Tool reference" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference">
Full directory of Anthropic-schema tools and their version strings.
</Card>
</CardGroup>
agents-and-tools/tool-use/web-fetch-tool First recorded · 968 lines, first recorded
## How web fetch works ### When Claude fetches ### Dynamic filtering ## How to use web fetch ## Tool definition ### Max uses ### Domain filtering ### Content limits ### Cache bypass ### Response inclusion ### Citations ## Response ### Fetch results ### Errors ## URL validation ## Combined search and fetch ## Prompt caching ## Streaming ## Batch requests ## Usage and pricing ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: Web fetch tool
url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool
description: Fetch and read content from specific URLs to augment Claude's context with live web content.
---
<Note>
For how zero data retention (ZDR) applies to this feature, see [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention).
</Note>
The web fetch tool allows Claude to retrieve full content from specified web pages and PDF documents.
The latest web fetch tool version (`web_fetch_20260318`) supports **dynamic filtering** with Claude Fable 5, Claude Opus 4.8, Claude Mythos 5, [Claude Mythos Preview](https://anthropic.com/glasswing), Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, and Claude Sonnet 4.6. Claude can write and execute code to filter fetched content before it reaches the context window, keeping only relevant information and discarding the rest. This reduces token consumption while maintaining response quality. `web_fetch_20260318` also adds [response inclusion](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool#response-inclusion) control for agentic workflows. The previous versions (`web_fetch_20260309` for dynamic filtering and [cache bypass](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool#cache-bypass), `web_fetch_20260209` for dynamic filtering only, `web_fetch_20250910` for basic fetch) remain available.
Web fetch (with and without dynamic filtering) is available on the Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws), and [Microsoft Foundry](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry). On Microsoft Foundry, web fetch requires a [Hosted on Anthropic deployment](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry#additional-features-not-supported-when-hosted-on-azure). It is not currently available on Amazon Bedrock or Google Cloud.
<Note>
For [Claude Mythos Preview](https://anthropic.com/glasswing), web fetch is available on the Claude API and Microsoft Foundry. It is not currently available for Mythos Preview on Amazon Bedrock or Google Cloud.
</Note>
<Note>
Use the [feedback form](https://forms.gle/NhWcgmkcvPCMmPE86) to provide feedback on the quality of the model responses, the API itself, or the quality of the documentation.
</Note>
For Zero Data Retention eligibility and the `allowed_callers` workaround, see [Server tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#zdr-and-allowed-callers).
<Warning>
Enabling the web fetch tool in environments where Claude processes untrusted input alongside sensitive data poses data exfiltration risks. Only use this tool in trusted environments or when handling non-sensitive data.
To minimize exfiltration risks, Claude is not allowed to dynamically construct URLs. Claude can only fetch URLs that have been explicitly provided by the user or that come from previous web search or web fetch results. However, there is still residual risk that you should carefully consider when using this tool.
If data exfiltration is a concern, consider:
* Disabling the web fetch tool entirely
* Using the `max_uses` parameter to limit the number of requests
* Using the `allowed_domains` parameter to restrict to known safe domains
</Warning>
For model support, see the [Tool reference](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference).
## How web fetch works
Web fetch is a [server tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools): the API fetches the content during the request and inserts the results into the conversation. You don't run anything or return a `tool_result`. The exception is when Claude calls web fetch and one of your client tools in the same group of parallel tool calls: the API returns the response with `stop_reason: "tool_use"` before that fetch has run, then runs the fetch when you send back the client `tool_result` blocks. See [Mixing server tools and client tools in one turn](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#mixing-server-tools-and-client-tools-in-one-turn).
When you add the web fetch tool to your API request:
1. Claude determines when to fetch content based on the prompt and available URLs.
2. The API retrieves the full text content from the specified URL.
3. For PDFs, the API returns the content as base64-encoded data and processes it like a directly attached PDF document.
4. Claude analyzes the fetched content and provides a response with optional citations.
<Note>
The web fetch tool currently does not support websites dynamically rendered with JavaScript.
</Note>
### When Claude fetches
Claude fetches when the request points at a specific page or document:
* A URL is provided in the conversation (or a previous tool result)
* The user names a specific resource (a particular article, README, pricing page, or documentation section) without a URL, and the [web search tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool) is also enabled so Claude can locate it first (see [Combined search and fetch](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool#combined-search-and-fetch))
Claude does **not** fetch for general-knowledge or open-ended questions that don't reference a specific page. "Summarize this article: `<url>`" triggers a fetch. "What are best practices for REST API design?" is answered directly.
### Dynamic filtering
Fetching full web pages and PDFs can quickly consume tokens, especially when only specific information is needed from large documents. With `web_fetch_20260209` or later, Claude can write and execute code to filter the fetched content before loading it into context.
This dynamic filtering is particularly useful for:
* Extracting specific sections from long documents
* Processing structured data from web pages
* Filtering relevant information from PDFs
* Reducing token costs when working with large documents
<Note>
Dynamic filtering runs on the [code execution tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/code-execution-tool), which the API enables automatically for the request. You don't need to add the code execution tool to the `tools` array.
</Note>
To enable dynamic filtering, use `web_fetch_20260209` or any later version. The following examples use `web_fetch_20260318`:
<CodeGroup>
```bash cURL
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-4-8",
"max_tokens": 4096,
"messages": [
{
"role": "user",
"content": "Fetch the content at https://example.com/research-paper and extract the key findings."
}
],
"tools": [{
"type": "web_fetch_20260318",
"name": "web_fetch"
}]
}'
```
```bash CLI
ant messages create <<'YAML'
model: claude-opus-4-8
max_tokens: 4096
messages:
- role: user
content: >-
Fetch the content at https://example.com/research-paper
and extract the key findings.
tools:
- type: web_fetch_20260318
name: web_fetch
YAML
```
```python Python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Fetch the content at https://example.com/research-paper and extract the key findings.",
}
],
tools=[{"type": "web_fetch_20260318", "name": "web_fetch"}],
)
print(response)
```
```typescript TypeScript
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 4096,
messages: [
{
role: "user",
content:
"Fetch the content at https://example.com/research-paper and extract the key findings."
}
],
tools: [{ type: "web_fetch_20260318", name: "web_fetch" }]
});
console.log(response);
```
```csharp C#
AnthropicClient client = new();
var parameters = new MessageCreateParams
{
Model = Model.ClaudeOpus4_8,
MaxTokens = 4096,
Messages = [new() { Role = Role.User, Content = "Fetch the content at https://example.com/research-paper and extract the key findings." }],
Tools = [new ToolUnion(new WebFetchTool20260318())]
};
var message = await client.Messages.Create(parameters);
Console.WriteLine(message);
```
```go Go
client := anthropic.NewClient()
response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
Model: anthropic.ModelClaudeOpus4_8,
MaxTokens: 4096,
Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock("Fetch the content at https://example.com/research-paper and extract the key findings.")),
},
Tools: []anthropic.ToolUnionParam{
{OfWebFetchTool20260318: &anthropic.WebFetchTool20260318Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response)
```
```java Java
import com.anthropic.models.messages.WebFetchTool20260318;
void main() {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_4_8)
.maxTokens(4096L)
.addUserMessage("Fetch the content at https://example.com/research-paper and extract the key findings.")
.addTool(WebFetchTool20260318.builder().build())
.build();
Message response = client.messages().create(params);
IO.println(response);
}
```
```php PHP
$client = new Client();
$message = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Fetch the content at https://example.com/research-paper and extract the key findings.']
],
model: 'claude-opus-4-8',
tools: [[
'type' => 'web_fetch_20260318',
'name' => 'web_fetch',
]],
);
echo $message;
```
```ruby Ruby
client = Anthropic::Client.new
message = client.messages.create(
model: "claude-opus-4-8",
max_tokens: 4096,
messages: [
{ role: "user", content: "Fetch the content at https://example.com/research-paper and extract the key findings." }
],
tools: [{
type: "web_fetch_20260318",
name: "web_fetch"
}]
)
puts message
```
</CodeGroup>
## How to use web fetch
Provide the web fetch tool in your API request:
<CodeGroup>
```bash cURL
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-4-8",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Please analyze the content at https://example.com/article"
}
],
"tools": [{
"type": "web_fetch_20250910",
"name": "web_fetch",
"max_uses": 5
}]
}'
```
```bash CLI
ant messages create \
--model claude-opus-4-8 \
--max-tokens 1024 \
--message '{role: user, content: "Please analyze the content at https://example.com/article"}' \
--tool '{type: web_fetch_20250910, name: web_fetch, max_uses: 5}'
```
```python Python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Please analyze the content at https://example.com/article",
}
],
tools=[{"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5}],
)
print(response)
```
```typescript TypeScript
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-opus-4-8",
max_tokens: 1024,
messages: [
Cut at 300 lines. The page has the rest.
agents-and-tools/tool-use/web-search-tool First recorded · 683 lines, first recorded
## How web search works ### When Claude searches ### Dynamic filtering ## How to use web search ## Tool definition ### Max uses ### Domain filtering ### Localization ### Response inclusion ## Response ### Search results ### Citations ### Errors ### `pause_turn` stop reason ## Prompt caching ## Streaming ## Batch requests ## Usage and pricing ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: Web search tool
url: https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool
description: Give Claude access to current web content with cited sources, optional dynamic filtering, and domain controls.
---
<Note>
For how zero data retention (ZDR) applies to this feature, see [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention).
</Note>
The web search tool gives Claude direct access to real-time web content, allowing it to answer questions with up-to-date information beyond its knowledge cutoff. The response includes citations for sources drawn from search results.
With `web_search_20260209` and later versions, Claude can write and run code that filters the search results before they reach the context window (**dynamic filtering**), keeping only relevant information. Dynamic filtering is available with Claude 4.6 and later models and [Claude Mythos Preview](https://anthropic.com/glasswing).
Three versions of the web search tool are available:
* `web_search_20250305`: basic web search
* `web_search_20260209`: adds [dynamic filtering](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool#dynamic-filtering)
* `web_search_20260318`: adds [response inclusion](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool#response-inclusion) control for agentic workflows
The examples on this page use `web_search_20250305` for basic search and `web_search_20260318` for dynamic filtering.
<Note>
For [Claude Mythos Preview](https://anthropic.com/glasswing), web search is supported on the Claude API, Google Cloud, and Microsoft Foundry. Web search is not available for Mythos Preview on Amazon Bedrock or [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws).
</Note>
For web search's Zero Data Retention eligibility and the related `allowed_callers` configuration, see [Server tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools#zdr-and-allowed-callers).
For model support, see the [Tool reference](https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-reference).
## How web search works
When you add the web search tool to your API request:
1. Claude determines when to search based on the prompt.
2. The API runs the searches and provides Claude with the results. This process can repeat multiple times throughout a single request.
3. At the end of its turn, Claude provides a final response with cited sources.
### When Claude searches
Claude searches when the request depends on information that is current, changing, or outside its training data:
* Recent events, news, or announcements
* Current prices, rates, scores, or statistics
* Information about specific organizations, people, or products that might have changed
* Explicit requests to search or look something up
Claude answers directly without searching when the request draws on stable knowledge:
* Established facts, math, science fundamentals, or coding concepts
* Creative writing or brainstorming
* Analysis of content already provided in the conversation
* Conversational turns and greetings
Triggering is steerable through your system prompt: you can encourage Claude to search more readily or to prefer answering directly. For a hard constraint, use `max_uses` to cap the number of searches for each request.
### Dynamic filtering
With basic web search, every search result is loaded into Claude's context window, and much of that content can be irrelevant to the request. With `web_search_20260209` or later, Claude instead writes and runs code that filters the results first, so only relevant content reaches the context window. This reduces token use on search-heavy requests.
Dynamic filtering runs web search from inside [code execution](https://platform.claude.com/docs/en/agents-and-tools/tool-use/code-execution-tool): on `web_search_20260209` and later, the tool's `allowed_callers` field defaults to `["code_execution_20260120"]`, and when dynamic filtering runs, the API provisions the code execution it needs for the request automatically. You don't need to add the code execution tool to `tools` yourself. There are no additional charges for code execution calls made this way beyond the standard token costs.
To call web search directly, without dynamic filtering, set `allowed_callers: ["direct"]`. Models that don't support programmatic tool calling require this setting. Without it, the API returns a 400 error that tells you to set it.
<Note>
The web search tool (with and without dynamic filtering) is available on the Claude API, [Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws), and [Microsoft Foundry](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry). On Microsoft Foundry, web search requires a [Hosted on Anthropic deployment](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry#additional-features-not-supported-when-hosted-on-azure). On Google Cloud, only the basic web search tool (without dynamic filtering) is available. Web search is not available on Amazon Bedrock.
</Note>
The following examples use `web_search_20260318`:
<CodeGroup>
```bash cURL
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-5",
"max_tokens": 4096,
"messages": [
{
"role": "user",
"content": "Search for the current prices of AAPL and GOOGL, then calculate which has a better P/E ratio."
}
],
"tools": [{
"type": "web_search_20260318",
"name": "web_search"
}]
}'
```
```bash CLI
ant messages create <<'YAML'
model: claude-opus-5
max_tokens: 4096
messages:
- role: user
content: >-
Search for the current prices of AAPL and GOOGL, then calculate
which has a better P/E ratio.
tools:
- type: web_search_20260318
name: web_search
YAML
```
```python Python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Search for the current prices of AAPL and GOOGL, then calculate which has a better P/E ratio.",
}
],
tools=[{"type": "web_search_20260318", "name": "web_search"}],
)
print(response)
```
```typescript TypeScript
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-opus-5",
max_tokens: 4096,
messages: [
{
role: "user",
content:
"Search for the current prices of AAPL and GOOGL, then calculate which has a better P/E ratio."
}
],
tools: [{ type: "web_search_20260318", name: "web_search" }]
});
console.log(response);
```
```csharp C#
AnthropicClient client = new();
var parameters = new MessageCreateParams
{
Model = Model.ClaudeOpus5,
MaxTokens = 4096,
Messages = [new() { Role = Role.User, Content = "Search for the current prices of AAPL and GOOGL, then calculate which has a better P/E ratio." }],
Tools = [new ToolUnion(new WebSearchTool20260318())]
};
var message = await client.Messages.Create(parameters);
Console.WriteLine(message);
```
```go Go
client := anthropic.NewClient()
response, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
Model: anthropic.ModelClaudeOpus5,
MaxTokens: 4096,
Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock("Search for the current prices of AAPL and GOOGL, then calculate which has a better P/E ratio.")),
},
Tools: []anthropic.ToolUnionParam{
{OfWebSearchTool20260318: &anthropic.WebSearchTool20260318Param{}},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(response)
```
```java Java
import com.anthropic.models.messages.WebSearchTool20260318;
void main() {
AnthropicClient client = AnthropicOkHttpClient.fromEnv();
MessageCreateParams params = MessageCreateParams.builder()
.model(Model.CLAUDE_OPUS_5)
.maxTokens(4096L)
.addUserMessage("Search for the current prices of AAPL and GOOGL, then calculate which has a better P/E ratio.")
.addTool(WebSearchTool20260318.builder().build())
.build();
Message response = client.messages().create(params);
IO.println(response);
}
```
```php PHP
$client = new Client();
$message = $client->messages->create(
maxTokens: 4096,
messages: [
['role' => 'user', 'content' => 'Search for the current prices of AAPL and GOOGL, then calculate which has a better P/E ratio.'],
],
model: 'claude-opus-5',
tools: [
[
'type' => 'web_search_20260318',
'name' => 'web_search',
],
],
);
echo $message;
```
```ruby Ruby
client = Anthropic::Client.new
message = client.messages.create(
model: "claude-opus-5",
max_tokens: 4096,
messages: [
{ role: "user", content: "Search for the current prices of AAPL and GOOGL, then calculate which has a better P/E ratio." }
],
tools: [{
type: "web_search_20260318",
name: "web_search"
}]
)
puts message
```
</CodeGroup>
## How to use web search
<Note>
Web search is enabled for your organization unless an administrator has disabled it in the [Claude Console](https://platform.claude.com/settings/privacy), where they can also restrict which domains it searches. If it's disabled, a request that includes the tool fails with a 400 `invalid_request_error` that says web search is not enabled, rather than an [error code](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool#errors) inside a search result.
</Note>
Provide the web search tool in your API request:
<CodeGroup>
```bash cURL
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-opus-5",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "What is the weather in NYC?"
}
],
"tools": [{
"type": "web_search_20250305",
"name": "web_search",
"max_uses": 5
}]
}'
```
```bash CLI
ant messages create \
--model claude-opus-5 \
--max-tokens 1024 \
--message '{role: user, content: What is the weather in NYC?}' \
--tool '{type: web_search_20250305, name: web_search, max_uses: 5}'
```
```python Python
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5",
max_tokens=1024,
messages=[{"role": "user", "content": "What's the weather in NYC?"}],
tools=[{"type": "web_search_20250305", "name": "web_search", "max_uses": 5}],
)
print(response)
```
```typescript TypeScript
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-opus-5",
max_tokens: 1024,
messages: [
{
role: "user",
content: "What's the weather in NYC?"
}
],
tools: [
{
type: "web_search_20250305",
name: "web_search",
Cut at 300 lines. The page has the rest.
api/admin First recorded · 18736 lines, first recorded
# Admin # Organizations ## Get Current Organization ### Returns ### Example #### Response ## Domain Types ### Organization # Invites ## Create Invite ### Body Parameters ### Returns ### Example #### Response ## Get Invite ### Path Parameters ### Returns ### Example #### Response ## List Invites ### Query Parameters ### Returns ### Example #### Response ## Delete Invite ### Path Parameters ### Returns ### Example #### Response ## Domain Types ### Invite ### Invite Delete Response # Users ## Get User ### Path Parameters ### Returns ### Example #### Response ## List Users ### Query Parameters ### Returns ### Example #### Response ## Update User ### Path Parameters ### Body Parameters ### Returns ### Example #### Response ## Remove User ### Path Parameters ### Returns ### Example #### Response ## Domain Types ### User ### User Delete Response # RBAC Groups ## List RBAC Groups ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Get RBAC Group ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Create RBAC Group ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Update RBAC Group ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Delete RBAC Group ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Rbac Group ### Rbac Group Deleted # Members ## List RBAC Group Members ### Path Parameters ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Add RBAC Group Member ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Remove RBAC Group Member ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Rbac Group Member ### Rbac Group Member Deleted # RBAC Roles ## List RBAC Roles ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Get RBAC Role ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Rbac Role # Permissions ## List RBAC Role Permissions ### Path Parameters ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Rbac Role Permission # Workspaces ## Create Workspace ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Get Workspace ### Path Parameters ### Returns ### Example #### Response ## List Workspaces ### Query Parameters ### Returns ### Example #### Response ## Update Workspace ### Path Parameters ### Body Parameters ### Returns ### Example #### Response ## Archive Workspace ### Path Parameters ### Returns ### Example #### Response # Members ## Create Workspace Member ### Path Parameters ### Body Parameters ### Returns ### Example #### Response ## Get Workspace Member ### Path Parameters ### Returns ### Example #### Response ## List Workspace Members ### Path Parameters ### Query Parameters ### Returns ### Example #### Response ## Update Workspace Member ### Path Parameters ### Body Parameters ### Returns ### Example #### Response ## Delete Workspace Member ### Path Parameters ### Returns ### Example #### Response ## Domain Types ### Workspace Member ### Member Delete Response # Rate Limits ## List Workspace Rate Limits ### Path Parameters ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Rate Limit List Response # Service Accounts ## Create Service Account Workspace Member ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Get Service Account Workspace Member ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## List Service Account Workspace Members ### Path Parameters ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Update Service Account Workspace Member ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Delete Service Account Workspace Member ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Service Account Create Response ### Service Account Retrieve Response ### Service Account List Response ### Service Account Update Response ### Service Account Delete Response # API Keys ## Retrieve API Key (Admin API) ### Path Parameters ### Returns ### Example #### Response ## List API Keys ### Query Parameters ### Returns ### Example #### Response ## Update API Key ### Path Parameters ### Body Parameters ### Returns ### Example #### Response # External Keys ## Create External Key ### Body Parameters ### Returns ### Example #### Response ## List External Keys ### Query Parameters ### Returns ### Example #### Response ## Get External Key ### Path Parameters ### Returns ### Example #### Response ## Update External Key ### Path Parameters ### Body Parameters ### Returns ### Example #### Response ## Delete External Key ### Path Parameters ### Returns ### Example #### Response ## Validate External Key ### Path Parameters ### Returns ### Example #### Response ## Domain Types ### External Key Create Response ### External Key List Response ### External Key Retrieve Response ### External Key Update Response ### External Key Delete Response ### External Key Validate Response # Usage Report ## Get Messages Usage Report ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Get Claude Code Usage Report ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Claude Code Usage Report ### Messages Usage Report # Cost Report ## Get Cost Report ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Cost Report # Analytics ## Get Activity Summaries ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Activity Summary ### Analytics User ### Analytics User Actor ### Connector Office Product Metrics ### Office Product Metrics ### Skill Office Product Metrics ### Tool Action Counts # Usage ## Get Token Usage Over Time ### Query Parameters ### Returns ### Example #### Response ## Get Per-User Token Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Usage Bucket ### User Usage # Cost ## Get Cost Over Time ### Query Parameters ### Returns ### Example #### Response ## Get Per-User Cost ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Cost Bucket ### User Cost # Users ## List User Activity ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### User Activity # Skills ## Get Skill Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Skill Usage # Connectors ## Get Connector Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Connector Usage # Chat Projects ## Get Chat Project Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Chat Project Usage # Plugins ## Get Plugin Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Plugin Usage # Artifacts ## Get Artifact Activity ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Artifact Usage # Spend Limits ## Set Spend Limit ### Body Parameters ### Returns ### Example #### Response ## Get Spend Limit ### Path Parameters ### Returns ### Example #### Response ## Delete Spend Limit ### Path Parameters ### Returns ### Example #### Response ## List Effective Spend Limits ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Spend Limit ### Spend Summary ### Spend Limit Delete Response # Increase Requests ## List Spend Limit Increase Requests ### Query Parameters ### Returns ### Example #### Response ## Get Spend Limit Increase Request ### Path Parameters ### Returns ### Example #### Response ## Approve Spend Limit Increase Request ### Path Parameters ### Body Parameters ### Returns ### Example #### Response ## Deny Spend Limit Increase Request ### Path Parameters ### Body Parameters ### Returns ### Example #### Response ## Domain Types ### Spend Limit Increase Request ### Increase Request Approve Response # Rate Limits ## List Organization Rate Limits ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Rate Limit List Response # Service Accounts ## Create Service Account ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Get Service Account ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## List Service Accounts ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Update Service Account ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Archive Service Account ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Service Account # Workspaces ## Add Workspace To Service Account ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## List Workspaces For Service Account ### Path Parameters ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Remove Workspace From Service Account ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Workspace Create Response ### Workspace List Response ### Workspace Delete Response # Federation Issuers ## Create Federation Issuer ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Get Federation Issuer ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## List Federation Issuers ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Update Federation Issuer ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Archive Federation Issuer ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Federation Issuer # Federation Rules ## Create Federation Rule ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Get Federation Rule ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## List Federation Rules ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Update Federation Rule ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Archive Federation Rule ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Federation Rule # Workspaces ## List Federation Rule Workspaces ### Path Parameters ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Add Federation Rule Workspace ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Remove Federation Rule Workspace ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Workspace List Response ### Workspace Create Response ### Workspace Delete Response # MCP Tunnels ## Get Tunnel ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## List Tunnels ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Reveal Tunnel Token ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Rotate Tunnel Token ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Archive Tunnel ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### MCP Tunnel Retrieve Response ### MCP Tunnel List Response ### MCP Tunnel Reveal Token Response ### MCP Tunnel Rotate Token Response ### MCP Tunnel Archive Response # Tunnel Certificates ## Create Tunnel Certificate ### Path Parameters ### Header Parameters ### Body Parameters ### Returns ### Example #### Response ## Get Tunnel Certificate ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## List Tunnel Certificates ### Path Parameters ### Query Parameters ### Header Parameters ### Returns ### Example #### Response ## Archive Tunnel Certificate ### Path Parameters ### Header Parameters ### Returns ### Example #### Response ## Domain Types ### Tunnel Certificate Create Response ### Tunnel Certificate Retrieve Response ### Tunnel Certificate List Response ### Tunnel Certificate Archive Response
This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.
The first capture of this source. The page was already there, and this is what it said.
---
title: Admin
url: https://platform.claude.com/docs/en/api/admin
---
# Admin
# Organizations
## Get Current Organization
**get** `/v1/organizations/me`
Retrieve information about the organization associated with the authenticated API key.
### Returns
- `Organization object { id, name, type }`
- `id: string`
ID of the Organization.
- `name: string`
Name of the Organization.
- `type: "organization"`
Object type.
For Organizations, this is always `"organization"`.
- `"organization"`
### Example
```http
curl https://api.anthropic.com/v1/organizations/me \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"id": "12345678-1234-5678-1234-567812345678",
"name": "Organization Name",
"type": "organization"
}
```
## Domain Types
### Organization
- `Organization object { id, name, type }`
- `id: string`
ID of the Organization.
- `name: string`
Name of the Organization.
- `type: "organization"`
Object type.
For Organizations, this is always `"organization"`.
- `"organization"`
# Invites
## Create Invite
**post** `/v1/organizations/invites`
For Claude Enterprise organizations, this endpoint's availability is in beta.
On plans that draw members from a finite pool of purchased seats, the invite automatically consumes a seat from the lowest tier with availability; there is no seat-tier parameter. When no seat is free the request fails with a 400 error rather than purchasing a seat.
### Body Parameters
- `email: string`
Email of the User.
- `role: "billing" or "claude_code_user" or "developer" or 2 more`
Role for the invited User.
The accepted values depend on the organization type. Console and API organizations accept `user`, `developer`, `billing`, and `claude_code_user`; `admin` cannot be assigned through the API. Claude Enterprise organizations (beta) accept `user` and `managed`.
- `"billing"`
- `"claude_code_user"`
- `"developer"`
- `"managed"`
- `"user"`
- `rbac_group_ids: optional array of string`
RBAC group IDs to assign to the User when the Invite is accepted. A non-empty array is accepted only for a Claude Enterprise organization with RBAC groups (beta), and requires the key to carry the `write:rbac_groups` scope.
### Returns
- `Invite object { id, accepted_at, email, 6 more }`
- `id: string`
ID of the Invite.
- `accepted_at: string or null`
RFC 3339 datetime string indicating when the Invite was accepted, or null.
- `email: string`
Email of the User being invited.
- `expires_at: string`
RFC 3339 datetime string indicating when the Invite expires.
- `invited_at: string`
RFC 3339 datetime string indicating when the Invite was created.
- `rbac_group_ids: array of string`
RBAC group IDs recorded on the Invite (beta, Claude Enterprise organizations), to be assigned to the User when the Invite is accepted. `[]` when none.
- `role: "admin" or "billing" or "claude_code_user" or 6 more`
Organization role of the User.
- `"admin"`
- `"billing"`
- `"claude_code_user"`
- `"developer"`
- `"managed"`
- `"membership_admin"`
- `"owner"`
- `"primary_owner"`
- `"user"`
- `status: "accepted" or "deleted" or "expired" or "pending"`
Status of the Invite.
- `"accepted"`
- `"deleted"`
- `"expired"`
- `"pending"`
- `type: "invite"`
Object type.
For Invites, this is always `"invite"`.
- `"invite"`
### Example
```http
curl https://api.anthropic.com/v1/organizations/invites \
-H 'Content-Type: application/json' \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN" \
-d '{
"email": "[email protected]",
"role": "user"
}'
```
#### Response
```json
{
"id": "invite_015gWxCN9Hfg2QhZwTK7Mdeu",
"accepted_at": "2019-12-27T18:11:19.117Z",
"email": "[email protected]",
"expires_at": "2024-11-20T23:58:27.427722Z",
"invited_at": "2024-10-30T23:58:27.427722Z",
"rbac_group_ids": [
"string"
],
"role": "user",
"status": "pending",
"type": "invite"
}
```
## Get Invite
**get** `/v1/organizations/invites/{invite_id}`
For Claude Enterprise organizations, this endpoint's availability is in beta.
### Path Parameters
- `invite_id: string`
ID of the Invite.
### Returns
- `Invite object { id, accepted_at, email, 6 more }`
- `id: string`
ID of the Invite.
- `accepted_at: string or null`
RFC 3339 datetime string indicating when the Invite was accepted, or null.
- `email: string`
Email of the User being invited.
- `expires_at: string`
RFC 3339 datetime string indicating when the Invite expires.
- `invited_at: string`
RFC 3339 datetime string indicating when the Invite was created.
- `rbac_group_ids: array of string`
RBAC group IDs recorded on the Invite (beta, Claude Enterprise organizations), to be assigned to the User when the Invite is accepted. `[]` when none.
- `role: "admin" or "billing" or "claude_code_user" or 6 more`
Organization role of the User.
- `"admin"`
- `"billing"`
- `"claude_code_user"`
- `"developer"`
- `"managed"`
- `"membership_admin"`
- `"owner"`
- `"primary_owner"`
- `"user"`
- `status: "accepted" or "deleted" or "expired" or "pending"`
Status of the Invite.
- `"accepted"`
- `"deleted"`
- `"expired"`
- `"pending"`
- `type: "invite"`
Object type.
For Invites, this is always `"invite"`.
- `"invite"`
### Example
```http
curl https://api.anthropic.com/v1/organizations/invites/$INVITE_ID \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
Cut at 300 lines. The page has the rest.
api/admin/analytics First recorded · 4288 lines, first recorded
# Analytics ## Get Activity Summaries ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Activity Summary ### Analytics User ### Analytics User Actor ### Connector Office Product Metrics ### Office Product Metrics ### Skill Office Product Metrics ### Tool Action Counts # Usage ## Get Token Usage Over Time ### Query Parameters ### Returns ### Example #### Response ## Get Per-User Token Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Usage Bucket ### User Usage # Cost ## Get Cost Over Time ### Query Parameters ### Returns ### Example #### Response ## Get Per-User Cost ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Cost Bucket ### User Cost # Users ## List User Activity ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### User Activity # Skills ## Get Skill Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Skill Usage # Connectors ## Get Connector Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Connector Usage # Chat Projects ## Get Chat Project Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Chat Project Usage # Plugins ## Get Plugin Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Plugin Usage # Artifacts ## Get Artifact Activity ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Artifact Usage
The first capture of this source. The page was already there, and this is what it said.
---
title: Analytics
url: https://platform.claude.com/docs/en/api/admin/analytics
---
# Analytics
## Get Activity Summaries
**get** `/v1/organizations/analytics/summaries`
Get organization-wide activity summaries for a date range.
Returns one entry per day in [starting_date, ending_date). Data is
typically available with a 1-day lag and may be revised by a few percent
over the following days: when ending_date is omitted it defaults to the
most recent available day + 1, so the last entry covers the most recent
available day. The series can be scoped to an RBAC group via
filter[]=rbac_group_id:<id>. Available to organizations on a Claude
Enterprise plan. Requires an API key with the `read:analytics` scope.
### Query Parameters
- `starting_date: string`
UTC date in YYYY-MM-DD format. Start of the date range (inclusive). Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive). Data is typically available with a 1-day lag, so this can be at most today — which is also the default when omitted, making the last entry cover the most recent available day. Data may be revised by a few percent over the following days. The range may span at most 366 days.
- `filter: optional array of string`
Filters as 'dimension:value'. Only rbac_group_id is supported (e.g. filter[]=rbac_group_id:<id>); repeat the param to OR across groups. Scopes the whole day series to members of the matching group(s), re-aggregated from member-level activity — org-wide seat/invite fields and the adoption rates derived from them are null on scoped rows. rbac_group_id accepts the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each UTC day (time-of-usage attribution). At most 100 entries.
### Returns
- `ActivitySummary object { summaries }`
Response for GET /v1/organizations/analytics/summaries.
- `summaries: array of object { assigned_seat_count, cowork_daily_active_user_count, cowork_monthly_active_user_count, 26 more }`
- `assigned_seat_count: number or null`
Number of seats currently assigned to members. Null when the response is scoped to an RBAC group — seat assignment is org-wide and has no per-group analogue.
- `cowork_daily_active_user_count: number`
Number of users with Cowork activity on the requested day
- `cowork_monthly_active_user_count: number`
Number of users with Cowork activity in the 30-day rolling window
- `cowork_weekly_active_user_count: number`
Number of users with Cowork activity in the 7-day rolling window
- `daily_active_user_count: number`
Number of users with token consumption on the requested day
- `daily_adoption_rate: number or null`
Percentage of assigned seats with activity on the requested day (`DAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `ending_at: string`
End time in UTC of aggregation period (e.g. 2026-01-16T00:00:00Z)
- `monthly_active_user_count: number`
Number of users with token consumption in the 30-day rolling window
- `monthly_adoption_rate: number or null`
Percentage of assigned seats with activity in the 30-day rolling window (`MAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `pending_invite_count: number or null`
Number of pending invitations to join the organization. Null when the response is scoped to an RBAC group.
- `starting_at: string`
Start time in UTC of aggregation period (e.g. 2026-01-15T00:00:00Z)
- `weekly_active_user_count: number`
Number of users with token consumption in the 7-day rolling window
- `weekly_adoption_rate: number or null`
Percentage of assigned seats with activity in the 7-day rolling window (`WAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `chat_daily_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `chat_monthly_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `chat_weekly_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_daily_active_user_count: optional number or null`
Number of users with Claude Code activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_monthly_active_user_count: optional number or null`
Number of users with Claude Code activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_weekly_active_user_count: optional number or null`
Number of users with Claude Code activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_design_daily_active_user_count: optional number or null`
Number of users with Claude Design activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_design_monthly_active_user_count: optional number or null`
Number of users with Claude Design activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_design_weekly_active_user_count: optional number or null`
Number of users with Claude Design activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `office_agent_daily_active_user_count: optional number or null`
Number of users with Claude in Office activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `office_agent_monthly_active_user_count: optional number or null`
Number of users with Claude in Office activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `office_agent_weekly_active_user_count: optional number or null`
Number of users with Claude in Office activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `science_daily_active_user_count: optional number or null`
Number of users with Claude Science activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `science_entitled_user_count: optional number or null`
Number of users with a Claude Science seat entitlement (per-seat RBAC) at the time of the daily snapshot. The funnel top; independent of the org-level Claude Science toggle. Null when the response is scoped to an RBAC group — entitlement is org-wide and has no per-group analogue. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `science_monthly_active_user_count: optional number or null`
Number of users with Claude Science activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `science_weekly_active_user_count: optional number or null`
Number of users with Claude Science activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/summaries \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"summaries": [
{
"assigned_seat_count": 0,
"cowork_daily_active_user_count": 0,
"cowork_monthly_active_user_count": 0,
"cowork_weekly_active_user_count": 0,
"daily_active_user_count": 0,
"daily_adoption_rate": 0,
"ending_at": "ending_at",
"monthly_active_user_count": 0,
"monthly_adoption_rate": 0,
"pending_invite_count": 0,
"starting_at": "starting_at",
"weekly_active_user_count": 0,
"weekly_adoption_rate": 0,
"chat_daily_active_user_count": 0,
"chat_monthly_active_user_count": 0,
"chat_weekly_active_user_count": 0,
"claude_code_daily_active_user_count": 0,
"claude_code_monthly_active_user_count": 0,
"claude_code_weekly_active_user_count": 0,
"claude_design_daily_active_user_count": 0,
"claude_design_monthly_active_user_count": 0,
"claude_design_weekly_active_user_count": 0,
"office_agent_daily_active_user_count": 0,
"office_agent_monthly_active_user_count": 0,
"office_agent_weekly_active_user_count": 0,
"science_daily_active_user_count": 0,
"science_entitled_user_count": 0,
"science_monthly_active_user_count": 0,
"science_weekly_active_user_count": 0
}
]
}
```
## Domain Types
### Activity Summary
- `ActivitySummary object { summaries }`
Response for GET /v1/organizations/analytics/summaries.
- `summaries: array of object { assigned_seat_count, cowork_daily_active_user_count, cowork_monthly_active_user_count, 26 more }`
- `assigned_seat_count: number or null`
Number of seats currently assigned to members. Null when the response is scoped to an RBAC group — seat assignment is org-wide and has no per-group analogue.
- `cowork_daily_active_user_count: number`
Number of users with Cowork activity on the requested day
- `cowork_monthly_active_user_count: number`
Number of users with Cowork activity in the 30-day rolling window
- `cowork_weekly_active_user_count: number`
Number of users with Cowork activity in the 7-day rolling window
- `daily_active_user_count: number`
Number of users with token consumption on the requested day
- `daily_adoption_rate: number or null`
Percentage of assigned seats with activity on the requested day (`DAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `ending_at: string`
End time in UTC of aggregation period (e.g. 2026-01-16T00:00:00Z)
- `monthly_active_user_count: number`
Number of users with token consumption in the 30-day rolling window
- `monthly_adoption_rate: number or null`
Percentage of assigned seats with activity in the 30-day rolling window (`MAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `pending_invite_count: number or null`
Number of pending invitations to join the organization. Null when the response is scoped to an RBAC group.
- `starting_at: string`
Start time in UTC of aggregation period (e.g. 2026-01-15T00:00:00Z)
- `weekly_active_user_count: number`
Number of users with token consumption in the 7-day rolling window
- `weekly_adoption_rate: number or null`
Percentage of assigned seats with activity in the 7-day rolling window (`WAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `chat_daily_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `chat_monthly_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `chat_weekly_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_daily_active_user_count: optional number or null`
Number of users with Claude Code activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_monthly_active_user_count: optional number or null`
Number of users with Claude Code activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_weekly_active_user_count: optional number or null`
Number of users with Claude Code activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_design_daily_active_user_count: optional number or null`
Number of users with Claude Design activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_design_monthly_active_user_count: optional number or null`
Number of users with Claude Design activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
Cut at 300 lines. The page has the rest.
api/admin/analytics/artifacts First recorded · 180 lines, first recorded
# Artifacts ## Get Artifact Activity ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Artifact Usage
The first capture of this source. The page was already there, and this is what it said.
---
title: Artifacts
url: https://platform.claude.com/docs/en/api/admin/analytics/artifacts
---
# Artifacts
## Get Artifact Activity
**get** `/v1/organizations/analytics/artifacts`
Get artifact-creation activity for a given day, broken out by MIME type.
Returns the full (artifact_type, is_shared) cube for the organization;
`next_page` is null except for grouped queries, which paginate. The cube
can be broken out per member or per RBAC group via group_by[], and scoped
via filter[]. Requires an API key with the `read:analytics` scope.
### Query Parameters
- `date: string`
UTC date in YYYY-MM-DD format. The day to get artifact activity for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: artifact_type, is_shared, rbac_group_id, user_id. Value forms: artifact_type is a canonical artifact MIME type (e.g. text/markdown) or 'other'; is_shared is 'true' or 'false'; rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "rbac_group_id" or "user_id"`
Dimensions to break results out by: user_id and/or rbac_group_id. The ungrouped artifact-type cube is finite and returned in full; grouped queries multiply the cube and paginate via next_page. rbac_group_id attributes a user to every group they held at any point during the requested UTC day, so grouped rows are not an exclusive partition. At most 100 entries.
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Maximum rows to return (1-1000, default 100). The ungrouped artifact-type cube is finite and returned in full; limit is the page size only when group_by[] multiplies the cube.
- `page: optional string`
Opaque cursor from a previous response's next_page field. Only valid with group_by[] — the ungrouped cube is never paginated.
### Returns
- `ArtifactUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/artifacts.
`next_page` is null on ungrouped queries — the artifact-type cube is
finite and returned in full. Grouped queries (`group_by[]` on `user_id` /
`rbac_group_id`) multiply the cube and paginate like the other analytics
list endpoints.
- `data: array of object { artifact_type, artifacts_created_count, distinct_user_count, 6 more }`
- `artifact_type: string`
Canonical artifact MIME type (e.g. text/markdown, application/vnd.ant.react, image/svg+xml), or 'other'.
- `artifacts_created_count: number`
Number of artifacts created in this bucket on the requested day
- `distinct_user_count: number`
Number of distinct users who created artifacts in this bucket on the requested day
- `is_shared: boolean`
Whether the artifacts in this bucket have ever been shared.
- `published_artifacts_created_count: number`
Number of those artifacts that have been published
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: optional string or null`
Cursor for the next page of a grouped query; always null for the ungrouped artifact-type cube, which is returned in full.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/artifacts \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"artifact_type": "artifact_type",
"artifacts_created_count": 0,
"distinct_user_count": 0,
"is_shared": true,
"published_artifacts_created_count": 0,
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"user_id": "user_id"
}
],
"next_page": "next_page"
}
```
## Domain Types
### Artifact Usage
- `ArtifactUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/artifacts.
`next_page` is null on ungrouped queries — the artifact-type cube is
finite and returned in full. Grouped queries (`group_by[]` on `user_id` /
`rbac_group_id`) multiply the cube and paginate like the other analytics
list endpoints.
- `data: array of object { artifact_type, artifacts_created_count, distinct_user_count, 6 more }`
- `artifact_type: string`
Canonical artifact MIME type (e.g. text/markdown, application/vnd.ant.react, image/svg+xml), or 'other'.
- `artifacts_created_count: number`
Number of artifacts created in this bucket on the requested day
- `distinct_user_count: number`
Number of distinct users who created artifacts in this bucket on the requested day
- `is_shared: boolean`
Whether the artifacts in this bucket have ever been shared.
- `published_artifacts_created_count: number`
Number of those artifacts that have been published
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: optional string or null`
Cursor for the next page of a grouped query; always null for the ungrouped artifact-type cube, which is returned in full.
api/admin/analytics/artifacts/list First recorded · 123 lines, first recorded
## Get Artifact Activity ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Artifact Activity
url: https://platform.claude.com/docs/en/api/admin/analytics/artifacts/list
---
## Get Artifact Activity
**get** `/v1/organizations/analytics/artifacts`
Get artifact-creation activity for a given day, broken out by MIME type.
Returns the full (artifact_type, is_shared) cube for the organization;
`next_page` is null except for grouped queries, which paginate. The cube
can be broken out per member or per RBAC group via group_by[], and scoped
via filter[]. Requires an API key with the `read:analytics` scope.
### Query Parameters
- `date: string`
UTC date in YYYY-MM-DD format. The day to get artifact activity for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: artifact_type, is_shared, rbac_group_id, user_id. Value forms: artifact_type is a canonical artifact MIME type (e.g. text/markdown) or 'other'; is_shared is 'true' or 'false'; rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "rbac_group_id" or "user_id"`
Dimensions to break results out by: user_id and/or rbac_group_id. The ungrouped artifact-type cube is finite and returned in full; grouped queries multiply the cube and paginate via next_page. rbac_group_id attributes a user to every group they held at any point during the requested UTC day, so grouped rows are not an exclusive partition. At most 100 entries.
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Maximum rows to return (1-1000, default 100). The ungrouped artifact-type cube is finite and returned in full; limit is the page size only when group_by[] multiplies the cube.
- `page: optional string`
Opaque cursor from a previous response's next_page field. Only valid with group_by[] — the ungrouped cube is never paginated.
### Returns
- `ArtifactUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/artifacts.
`next_page` is null on ungrouped queries — the artifact-type cube is
finite and returned in full. Grouped queries (`group_by[]` on `user_id` /
`rbac_group_id`) multiply the cube and paginate like the other analytics
list endpoints.
- `data: array of object { artifact_type, artifacts_created_count, distinct_user_count, 6 more }`
- `artifact_type: string`
Canonical artifact MIME type (e.g. text/markdown, application/vnd.ant.react, image/svg+xml), or 'other'.
- `artifacts_created_count: number`
Number of artifacts created in this bucket on the requested day
- `distinct_user_count: number`
Number of distinct users who created artifacts in this bucket on the requested day
- `is_shared: boolean`
Whether the artifacts in this bucket have ever been shared.
- `published_artifacts_created_count: number`
Number of those artifacts that have been published
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: optional string or null`
Cursor for the next page of a grouped query; always null for the ungrouped artifact-type cube, which is returned in full.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/artifacts \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"artifact_type": "artifact_type",
"artifacts_created_count": 0,
"distinct_user_count": 0,
"is_shared": true,
"published_artifacts_created_count": 0,
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"user_id": "user_id"
}
],
"next_page": "next_page"
}
```
api/admin/analytics/chat_projects First recorded · 241 lines, first recorded
# Chat Projects ## Get Chat Project Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Chat Project Usage
The first capture of this source. The page was already there, and this is what it said.
---
title: Chat Projects
url: https://platform.claude.com/docs/en/api/admin/analytics/chat_projects
---
# Chat Projects
## Get Chat Project Usage
**get** `/v1/organizations/analytics/apps/chat/projects`
Get per-project activity for a given day, with cursor-based pagination.
Returns activity metrics for each project in the organization, sorted by
project ID. Use group_by[] to break projects out per member or per RBAC
group, and filter[] to scope results; the parameter descriptions list the
supported dimensions. Available to organizations on a Claude Enterprise
plan. Requires an API key with the `read:analytics` scope.
### Query Parameters
- `date: optional string`
UTC date in YYYY-MM-DD format. The day to get project activity for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive); only valid with starting_date. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day), so this can be at most today — which is also the default when omitted, resolved once when the first page is served and reused for the rest of the pagination sequence. At most 366 days after starting_date.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: project_id, rbac_group_id, user_id. Value forms: project_id takes a tagged project id (claude_proj_...); rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "rbac_group_id" or "user_id"`
Dimensions to break results out by (e.g. group_by[]=user_id). Supported on this endpoint: rbac_group_id, user_id. Grouped rows carry the requested dimension values as additional fields and paginate like ungrouped responses via next_page; an unsupported dimension returns 400. rbac_group_id attributes a user to every group they held at any point during each covered UTC day, so grouped rows are not an exclusive partition and can sum above org-level totals. At most 100 entries.
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Number of results per page (1-1000, default 100).
- `order: optional "asc" or "desc"`
Sort direction: 'asc' or 'desc'. Defaults to 'asc' for the endpoint's sort column and to 'desc' when order_by names a metric (a top-N ranking). Applies to order_by, or to the endpoint's default sort field when order_by is omitted.
- `"asc"`
- `"desc"`
- `order_by: optional string`
Sort field. Restricted to the endpoint's sort column plus its rankable metrics (metrics default to descending; a few metrics rank in date-range mode only, per the endpoint's documented orderable set).
- `page: optional string`
Opaque cursor from a previous response's next_page field.
- `starting_date: optional string`
UTC date in YYYY-MM-DD format. Start of a date range (inclusive). Enables rollup mode: one row per entity aggregated over the whole range — addable counters are summed across days, and a distinct count is never summed where summing could double-count (a field's range value is recomputed exactly over the window, approximate via HLL with typical error under 2%, null, or — for the creation-event counts, whose per-day values cannot overlap — a per-day sum that is itself exact; each field's own description says which). Use either date or starting_date, not both. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
### Returns
- `ChatProjectUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/apps/chat/projects.
- `data: array of object { distinct_user_count, message_count, project_id, 8 more }`
- `distinct_user_count: number`
Number of distinct users who used the project on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `message_count: number`
Number of messages sent in the project on the requested day
- `project_id: string`
Tagged project identifier (e.g. claude_proj_...)
- `project_name: string`
Name of the project
- `created_at: optional string or null`
Project creation timestamp, RFC 3339. Null if the project was deleted before attribution was recorded.
- `created_by: optional AnalyticsUser or null`
User identifier.
- `id: string`
Tagged user identifier (e.g. `user_...`)
- `email_address: string`
Email address of the user
- `type: optional "user"`
Object type. Always `user`.
- `"user"`
- `distinct_conversation_count: optional number or null`
Number of distinct conversations in the project. Null on aggregated rows where a distinct count cannot be computed.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/apps/chat/projects \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"distinct_user_count": 0,
"message_count": 0,
"project_id": "project_id",
"project_name": "project_name",
"created_at": "created_at",
"created_by": {
"id": "id",
"email_address": "email_address",
"type": "user"
},
"distinct_conversation_count": 0,
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"user_id": "user_id"
}
],
"next_page": "next_page"
}
```
## Domain Types
### Chat Project Usage
- `ChatProjectUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/apps/chat/projects.
- `data: array of object { distinct_user_count, message_count, project_id, 8 more }`
- `distinct_user_count: number`
Number of distinct users who used the project on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `message_count: number`
Number of messages sent in the project on the requested day
- `project_id: string`
Tagged project identifier (e.g. claude_proj_...)
- `project_name: string`
Name of the project
- `created_at: optional string or null`
Project creation timestamp, RFC 3339. Null if the project was deleted before attribution was recorded.
- `created_by: optional AnalyticsUser or null`
User identifier.
- `id: string`
Tagged user identifier (e.g. `user_...`)
- `email_address: string`
Email address of the user
- `type: optional "user"`
Object type. Always `user`.
- `"user"`
- `distinct_conversation_count: optional number or null`
Number of distinct conversations in the project. Null on aggregated rows where a distinct count cannot be computed.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
api/admin/analytics/chat_projects/list First recorded · 167 lines, first recorded
## Get Chat Project Usage ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Chat Project Usage
url: https://platform.claude.com/docs/en/api/admin/analytics/chat_projects/list
---
## Get Chat Project Usage
**get** `/v1/organizations/analytics/apps/chat/projects`
Get per-project activity for a given day, with cursor-based pagination.
Returns activity metrics for each project in the organization, sorted by
project ID. Use group_by[] to break projects out per member or per RBAC
group, and filter[] to scope results; the parameter descriptions list the
supported dimensions. Available to organizations on a Claude Enterprise
plan. Requires an API key with the `read:analytics` scope.
### Query Parameters
- `date: optional string`
UTC date in YYYY-MM-DD format. The day to get project activity for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive); only valid with starting_date. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day), so this can be at most today — which is also the default when omitted, resolved once when the first page is served and reused for the rest of the pagination sequence. At most 366 days after starting_date.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: project_id, rbac_group_id, user_id. Value forms: project_id takes a tagged project id (claude_proj_...); rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "rbac_group_id" or "user_id"`
Dimensions to break results out by (e.g. group_by[]=user_id). Supported on this endpoint: rbac_group_id, user_id. Grouped rows carry the requested dimension values as additional fields and paginate like ungrouped responses via next_page; an unsupported dimension returns 400. rbac_group_id attributes a user to every group they held at any point during each covered UTC day, so grouped rows are not an exclusive partition and can sum above org-level totals. At most 100 entries.
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Number of results per page (1-1000, default 100).
- `order: optional "asc" or "desc"`
Sort direction: 'asc' or 'desc'. Defaults to 'asc' for the endpoint's sort column and to 'desc' when order_by names a metric (a top-N ranking). Applies to order_by, or to the endpoint's default sort field when order_by is omitted.
- `"asc"`
- `"desc"`
- `order_by: optional string`
Sort field. Restricted to the endpoint's sort column plus its rankable metrics (metrics default to descending; a few metrics rank in date-range mode only, per the endpoint's documented orderable set).
- `page: optional string`
Opaque cursor from a previous response's next_page field.
- `starting_date: optional string`
UTC date in YYYY-MM-DD format. Start of a date range (inclusive). Enables rollup mode: one row per entity aggregated over the whole range — addable counters are summed across days, and a distinct count is never summed where summing could double-count (a field's range value is recomputed exactly over the window, approximate via HLL with typical error under 2%, null, or — for the creation-event counts, whose per-day values cannot overlap — a per-day sum that is itself exact; each field's own description says which). Use either date or starting_date, not both. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
### Returns
- `ChatProjectUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/apps/chat/projects.
- `data: array of object { distinct_user_count, message_count, project_id, 8 more }`
- `distinct_user_count: number`
Number of distinct users who used the project on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `message_count: number`
Number of messages sent in the project on the requested day
- `project_id: string`
Tagged project identifier (e.g. claude_proj_...)
- `project_name: string`
Name of the project
- `created_at: optional string or null`
Project creation timestamp, RFC 3339. Null if the project was deleted before attribution was recorded.
- `created_by: optional AnalyticsUser or null`
User identifier.
- `id: string`
Tagged user identifier (e.g. `user_...`)
- `email_address: string`
Email address of the user
- `type: optional "user"`
Object type. Always `user`.
- `"user"`
- `distinct_conversation_count: optional number or null`
Number of distinct conversations in the project. Null on aggregated rows where a distinct count cannot be computed.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/apps/chat/projects \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"distinct_user_count": 0,
"message_count": 0,
"project_id": "project_id",
"project_name": "project_name",
"created_at": "created_at",
"created_by": {
"id": "id",
"email_address": "email_address",
"type": "user"
},
"distinct_conversation_count": 0,
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"user_id": "user_id"
}
],
"next_page": "next_page"
}
```
api/admin/analytics/connectors First recorded · 342 lines, first recorded
# Connectors ## Get Connector Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Connector Usage
The first capture of this source. The page was already there, and this is what it said.
---
title: Connectors
url: https://platform.claude.com/docs/en/api/admin/analytics/connectors
---
# Connectors
## Get Connector Usage
**get** `/v1/organizations/analytics/connectors`
Get per-connector usage for a given day, with cursor-based pagination.
Returns connector usage metrics for the organization, sorted by connector
name. Connector names are normalized from their various sources — for
example, "Atlassian MCP server" and "mcp-atlassian" both appear as
"atlassian". Use group_by[] to break usage out per member, per RBAC
group, or per product surface, and filter[] to scope results; the
parameter descriptions list the supported dimensions. Available to
organizations on a Claude Enterprise plan. Requires an API key with the
`read:analytics` scope.
### Query Parameters
- `date: optional string`
UTC date in YYYY-MM-DD format. The day to get connector usage for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive); only valid with starting_date. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day), so this can be at most today — which is also the default when omitted, resolved once when the first page is served and reused for the rest of the pagination sequence. At most 366 days after starting_date.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: connector_name, product, rbac_group_id, user_id. Value forms: connector_name matches case-insensitively, a display name such as 'GitHub MCP' also matches its normalized stored form ('github'), and for rows whose connector_name is an opaque connector id the connector's display name (connector_display_name) also matches; product is one of chat, claude_code, cowork, or office_agent; rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "product" or "rbac_group_id" or "user_id"`
Dimensions to break results out by (e.g. group_by[]=user_id). Supported on this endpoint: product, rbac_group_id, user_id. Grouped rows carry the requested dimension values as additional fields and paginate like ungrouped responses via next_page; an unsupported dimension returns 400. rbac_group_id attributes a user to every group they held at any point during each covered UTC day, so grouped rows are not an exclusive partition and can sum above org-level totals. At most 100 entries.
- `"product"`
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Number of results per page (1-1000, default 100).
- `order: optional "asc" or "desc"`
Sort direction: 'asc' or 'desc'. Defaults to 'asc' for the endpoint's sort column and to 'desc' when order_by names a metric (a top-N ranking). Applies to order_by, or to the endpoint's default sort field when order_by is omitted.
- `"asc"`
- `"desc"`
- `order_by: optional string`
Sort field. Restricted to the endpoint's sort column plus its rankable metrics (metrics default to descending; a few metrics rank in date-range mode only, per the endpoint's documented orderable set).
- `page: optional string`
Opaque cursor from a previous response's next_page field.
- `starting_date: optional string`
UTC date in YYYY-MM-DD format. Start of a date range (inclusive). Enables rollup mode: one row per entity aggregated over the whole range — addable counters are summed across days, and a distinct count is never summed where summing could double-count (a field's range value is recomputed exactly over the window, approximate via HLL with typical error under 2%, null, or — for the creation-event counts, whose per-day values cannot overlap — a per-day sum that is itself exact; each field's own description says which). Use either date or starting_date, not both. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
### Returns
- `ConnectorUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/connectors.
- `data: array of object { chat_metrics, claude_code_metrics, connector_name, 13 more }`
- `chat_metrics: object { distinct_conversation_connector_used_count }`
Claude.ai activity metrics for a single connector on a given day.
- `distinct_conversation_connector_used_count: number or null`
Number of distinct conversations in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `claude_code_metrics: object { distinct_session_connector_used_count }`
Claude Code activity metrics for a single connector on a given day.
- `distinct_session_connector_used_count: number or null`
Number of distinct Claude Code sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `connector_name: string`
Name of the connector. Some rows carry an opaque connector id here instead of a readable name; connector_display_name holds the resolved name for those rows.
- `cowork_metrics: object { distinct_session_connector_used_count }`
Cowork activity metrics for a single connector on a given day.
- `distinct_session_connector_used_count: number or null`
Number of distinct Cowork sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users who used the connector on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `office_metrics: object { excel, outlook, powerpoint, word }`
Office Agent activity metrics for a single connector on a given day, broken out by Office product.
- `excel: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `distinct_session_connector_used_count: number or null`
Number of distinct Office Agent sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `outlook: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `powerpoint: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `word: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `connector_display_name: optional string or null`
Human-readable display name for rows whose connector_name is an opaque connector id rather than a readable name, resolved at request time from the organization's connectors (including connectors that have since been removed). connector_name remains the row's stable key for sorting and pagination, and filter[]=connector_name:<value> also matches these rows by display name. Display names are not unique, and the same connector's claude.ai usage can appear under a separate row with a readable connector_name. Null when connector_name is already a readable name, when the id cannot be resolved to one of the organization's connectors, or when display-name resolution is not enabled for this organization.
- `individual_auth_distinct_user_count: optional number or null`
Number of distinct users whose use of this connector on the requested day ran on their own individual credential, connected through their own consent flow. Companion bucket to managed_auth_distinct_user_count, which carries the measurement, attribution, and null rules. Users whose requests used no stored credential count in neither bucket.
- `managed_auth_distinct_user_count: optional number or null`
Number of distinct users whose use of this connector on the requested day ran on Enterprise Managed Auth (an organization-managed credential provisioned through the organization's identity provider), read from the token record each request used. Null, never 0, when managed-auth reporting is not enabled for the organization, the value cannot be attributed to the row, no credentialed requests and no managed-token mint events (a managed credential being provisioned for a user's use of the connector) were observed that day, or the day predates 2026-07-01, the first day the backing data exists (forward-only data, no backfill). When credentialed requests or mint events were observed and attributed, both managed-auth fields populate, reporting 0 for a bucket with no users; the two counts are independent, not a partition — a user whose requests that day used both kinds of credential counts in both. Mint events carry user but not surface attribution, so they count as observed auth activity on user_id and rbac_group_id cuts — attributed to the user the credential was provisioned for — but never on a cut that references product (group or filter). Date-range rollup mode (starting_date/ending_date) computes both fields exactly over the window — distinct users with at least one qualifying day — when the whole window starts on or after 2026-07-01, with the null-versus-0 and mint-event rules applying with the window in place of the day; a range starting earlier reports every managed-auth field as null, never a partial-window value.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `read_call_count: optional number or null`
Number of connector tool calls on the requested day whose trusted read-only annotation marked them read-only. Call count, not distinct users. Every call recorded on a classified surface lands in exactly one of read_call_count, write_call_count, or unclassified_call_count, so the three sum to the day's classified calls. Classification is forward-only per surface: claude.ai from 2026-06-01, Claude Code from 2026-05-30, Claude in Office from 2026-05-29, Cowork from 2026-06-02 (Cowork clients predating annotation forwarding land in unclassified_call_count). Null, never 0, when the value cannot be stated: the read/write split is not enabled for this organization, or the day predates 2026-05-29. For a date-range total, sum the per-day values, but treat a window that extends before 2026-05-29 as null rather than summing only its covered days — date-range rollup mode (starting_date/ending_date) applies both rules server-side.
- `unclassified_call_count: optional number or null`
Number of connector tool calls on the requested day with no trusted read-only annotation — the annotation is optional in the MCP spec and is discarded when connector access controls are active, so unclassified calls are common. This field shows how much of the day's classified activity the read/write split actually covers. Call count, not distinct users. One of the three call-classification buckets; see read_call_count for the per-surface data-start dates, null conditions, and date-range guidance.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `write_call_count: optional number or null`
Number of connector tool calls on the requested day whose trusted read-only annotation marked them not read-only. Call count, not distinct users. One of the three call-classification buckets; see read_call_count for the per-surface data-start dates, null conditions, and date-range guidance.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/connectors \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"chat_metrics": {
"distinct_conversation_connector_used_count": 0
},
"claude_code_metrics": {
"distinct_session_connector_used_count": 0
},
"connector_name": "connector_name",
"cowork_metrics": {
"distinct_session_connector_used_count": 0
},
"distinct_user_count": 0,
"office_metrics": {
"excel": {
"distinct_session_connector_used_count": 0
},
"outlook": {
"distinct_session_connector_used_count": 0
},
"powerpoint": {
"distinct_session_connector_used_count": 0
},
"word": {
"distinct_session_connector_used_count": 0
}
},
"connector_display_name": "connector_display_name",
"individual_auth_distinct_user_count": 0,
"managed_auth_distinct_user_count": 0,
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"read_call_count": 0,
"unclassified_call_count": 0,
"user_id": "user_id",
"write_call_count": 0
}
],
"next_page": "next_page"
}
```
## Domain Types
### Connector Usage
- `ConnectorUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/connectors.
- `data: array of object { chat_metrics, claude_code_metrics, connector_name, 13 more }`
- `chat_metrics: object { distinct_conversation_connector_used_count }`
Claude.ai activity metrics for a single connector on a given day.
- `distinct_conversation_connector_used_count: number or null`
Number of distinct conversations in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `claude_code_metrics: object { distinct_session_connector_used_count }`
Claude Code activity metrics for a single connector on a given day.
- `distinct_session_connector_used_count: number or null`
Number of distinct Claude Code sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `connector_name: string`
Name of the connector. Some rows carry an opaque connector id here instead of a readable name; connector_display_name holds the resolved name for those rows.
- `cowork_metrics: object { distinct_session_connector_used_count }`
Cowork activity metrics for a single connector on a given day.
- `distinct_session_connector_used_count: number or null`
Number of distinct Cowork sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users who used the connector on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `office_metrics: object { excel, outlook, powerpoint, word }`
Office Agent activity metrics for a single connector on a given day, broken out by Office product.
- `excel: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `distinct_session_connector_used_count: number or null`
Number of distinct Office Agent sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `outlook: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `powerpoint: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `word: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `connector_display_name: optional string or null`
Cut at 300 lines. The page has the rest.
api/admin/analytics/connectors/list First recorded · 230 lines, first recorded
## Get Connector Usage ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Connector Usage
url: https://platform.claude.com/docs/en/api/admin/analytics/connectors/list
---
## Get Connector Usage
**get** `/v1/organizations/analytics/connectors`
Get per-connector usage for a given day, with cursor-based pagination.
Returns connector usage metrics for the organization, sorted by connector
name. Connector names are normalized from their various sources — for
example, "Atlassian MCP server" and "mcp-atlassian" both appear as
"atlassian". Use group_by[] to break usage out per member, per RBAC
group, or per product surface, and filter[] to scope results; the
parameter descriptions list the supported dimensions. Available to
organizations on a Claude Enterprise plan. Requires an API key with the
`read:analytics` scope.
### Query Parameters
- `date: optional string`
UTC date in YYYY-MM-DD format. The day to get connector usage for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive); only valid with starting_date. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day), so this can be at most today — which is also the default when omitted, resolved once when the first page is served and reused for the rest of the pagination sequence. At most 366 days after starting_date.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: connector_name, product, rbac_group_id, user_id. Value forms: connector_name matches case-insensitively, a display name such as 'GitHub MCP' also matches its normalized stored form ('github'), and for rows whose connector_name is an opaque connector id the connector's display name (connector_display_name) also matches; product is one of chat, claude_code, cowork, or office_agent; rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "product" or "rbac_group_id" or "user_id"`
Dimensions to break results out by (e.g. group_by[]=user_id). Supported on this endpoint: product, rbac_group_id, user_id. Grouped rows carry the requested dimension values as additional fields and paginate like ungrouped responses via next_page; an unsupported dimension returns 400. rbac_group_id attributes a user to every group they held at any point during each covered UTC day, so grouped rows are not an exclusive partition and can sum above org-level totals. At most 100 entries.
- `"product"`
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Number of results per page (1-1000, default 100).
- `order: optional "asc" or "desc"`
Sort direction: 'asc' or 'desc'. Defaults to 'asc' for the endpoint's sort column and to 'desc' when order_by names a metric (a top-N ranking). Applies to order_by, or to the endpoint's default sort field when order_by is omitted.
- `"asc"`
- `"desc"`
- `order_by: optional string`
Sort field. Restricted to the endpoint's sort column plus its rankable metrics (metrics default to descending; a few metrics rank in date-range mode only, per the endpoint's documented orderable set).
- `page: optional string`
Opaque cursor from a previous response's next_page field.
- `starting_date: optional string`
UTC date in YYYY-MM-DD format. Start of a date range (inclusive). Enables rollup mode: one row per entity aggregated over the whole range — addable counters are summed across days, and a distinct count is never summed where summing could double-count (a field's range value is recomputed exactly over the window, approximate via HLL with typical error under 2%, null, or — for the creation-event counts, whose per-day values cannot overlap — a per-day sum that is itself exact; each field's own description says which). Use either date or starting_date, not both. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
### Returns
- `ConnectorUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/connectors.
- `data: array of object { chat_metrics, claude_code_metrics, connector_name, 13 more }`
- `chat_metrics: object { distinct_conversation_connector_used_count }`
Claude.ai activity metrics for a single connector on a given day.
- `distinct_conversation_connector_used_count: number or null`
Number of distinct conversations in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `claude_code_metrics: object { distinct_session_connector_used_count }`
Claude Code activity metrics for a single connector on a given day.
- `distinct_session_connector_used_count: number or null`
Number of distinct Claude Code sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `connector_name: string`
Name of the connector. Some rows carry an opaque connector id here instead of a readable name; connector_display_name holds the resolved name for those rows.
- `cowork_metrics: object { distinct_session_connector_used_count }`
Cowork activity metrics for a single connector on a given day.
- `distinct_session_connector_used_count: number or null`
Number of distinct Cowork sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users who used the connector on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `office_metrics: object { excel, outlook, powerpoint, word }`
Office Agent activity metrics for a single connector on a given day, broken out by Office product.
- `excel: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `distinct_session_connector_used_count: number or null`
Number of distinct Office Agent sessions in which the connector was used. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `outlook: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `powerpoint: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `word: ConnectorOfficeProductMetrics`
Office Agent activity metrics for a single connector on a given day within one Office product.
- `connector_display_name: optional string or null`
Human-readable display name for rows whose connector_name is an opaque connector id rather than a readable name, resolved at request time from the organization's connectors (including connectors that have since been removed). connector_name remains the row's stable key for sorting and pagination, and filter[]=connector_name:<value> also matches these rows by display name. Display names are not unique, and the same connector's claude.ai usage can appear under a separate row with a readable connector_name. Null when connector_name is already a readable name, when the id cannot be resolved to one of the organization's connectors, or when display-name resolution is not enabled for this organization.
- `individual_auth_distinct_user_count: optional number or null`
Number of distinct users whose use of this connector on the requested day ran on their own individual credential, connected through their own consent flow. Companion bucket to managed_auth_distinct_user_count, which carries the measurement, attribution, and null rules. Users whose requests used no stored credential count in neither bucket.
- `managed_auth_distinct_user_count: optional number or null`
Number of distinct users whose use of this connector on the requested day ran on Enterprise Managed Auth (an organization-managed credential provisioned through the organization's identity provider), read from the token record each request used. Null, never 0, when managed-auth reporting is not enabled for the organization, the value cannot be attributed to the row, no credentialed requests and no managed-token mint events (a managed credential being provisioned for a user's use of the connector) were observed that day, or the day predates 2026-07-01, the first day the backing data exists (forward-only data, no backfill). When credentialed requests or mint events were observed and attributed, both managed-auth fields populate, reporting 0 for a bucket with no users; the two counts are independent, not a partition — a user whose requests that day used both kinds of credential counts in both. Mint events carry user but not surface attribution, so they count as observed auth activity on user_id and rbac_group_id cuts — attributed to the user the credential was provisioned for — but never on a cut that references product (group or filter). Date-range rollup mode (starting_date/ending_date) computes both fields exactly over the window — distinct users with at least one qualifying day — when the whole window starts on or after 2026-07-01, with the null-versus-0 and mint-event rules applying with the window in place of the day; a range starting earlier reports every managed-auth field as null, never a partial-window value.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `read_call_count: optional number or null`
Number of connector tool calls on the requested day whose trusted read-only annotation marked them read-only. Call count, not distinct users. Every call recorded on a classified surface lands in exactly one of read_call_count, write_call_count, or unclassified_call_count, so the three sum to the day's classified calls. Classification is forward-only per surface: claude.ai from 2026-06-01, Claude Code from 2026-05-30, Claude in Office from 2026-05-29, Cowork from 2026-06-02 (Cowork clients predating annotation forwarding land in unclassified_call_count). Null, never 0, when the value cannot be stated: the read/write split is not enabled for this organization, or the day predates 2026-05-29. For a date-range total, sum the per-day values, but treat a window that extends before 2026-05-29 as null rather than summing only its covered days — date-range rollup mode (starting_date/ending_date) applies both rules server-side.
- `unclassified_call_count: optional number or null`
Number of connector tool calls on the requested day with no trusted read-only annotation — the annotation is optional in the MCP spec and is discarded when connector access controls are active, so unclassified calls are common. This field shows how much of the day's classified activity the read/write split actually covers. Call count, not distinct users. One of the three call-classification buckets; see read_call_count for the per-surface data-start dates, null conditions, and date-range guidance.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `write_call_count: optional number or null`
Number of connector tool calls on the requested day whose trusted read-only annotation marked them not read-only. Call count, not distinct users. One of the three call-classification buckets; see read_call_count for the per-surface data-start dates, null conditions, and date-range guidance.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/connectors \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"chat_metrics": {
"distinct_conversation_connector_used_count": 0
},
"claude_code_metrics": {
"distinct_session_connector_used_count": 0
},
"connector_name": "connector_name",
"cowork_metrics": {
"distinct_session_connector_used_count": 0
},
"distinct_user_count": 0,
"office_metrics": {
"excel": {
"distinct_session_connector_used_count": 0
},
"outlook": {
"distinct_session_connector_used_count": 0
},
"powerpoint": {
"distinct_session_connector_used_count": 0
},
"word": {
"distinct_session_connector_used_count": 0
}
},
"connector_display_name": "connector_display_name",
"individual_auth_distinct_user_count": 0,
"managed_auth_distinct_user_count": 0,
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"read_call_count": 0,
"unclassified_call_count": 0,
"user_id": "user_id",
"write_call_count": 0
}
],
"next_page": "next_page"
}
```
api/admin/analytics/cost First recorded · 848 lines, first recorded
# Cost ## Get Cost Over Time ### Query Parameters ### Returns ### Example #### Response ## Get Per-User Cost ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Cost Bucket ### User Cost
The first capture of this source. The page was already there, and this is what it said.
---
title: Cost
url: https://platform.claude.com/docs/en/api/admin/analytics/cost
---
# Cost
## Get Cost Over Time
**get** `/v1/organizations/analytics/cost_report`
Get cost in USD over time across a date range.
Returns cost bucketed by minute, hour, or day, optionally broken down by
product, model, context window, inference region, speed, cost type, or
token type. Available to organizations on a Claude Enterprise plan.
Requires an API key with the `read:analytics` scope.
### Query Parameters
- `starting_at: string`
Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.
- `bucket_width: optional "1d" or "1h" or "1m"`
Time bucket granularity.
- `"1d"`
- `"1h"`
- `"1m"`
- `context_windows: optional array of "0-200k" or "200k-1M"`
Filter to specific context-window pricing tiers. Use `group_by[]=context_window` to break out per-tier values.
- `"0-200k"`
- `"200k-1M"`
- `ending_at: optional string`
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.
- `group_by: optional array of "context_window" or "cost_type" or "inference_geo" or 6 more`
Dimensions to break each time bucket out by. Defaults to no grouping (one total per bucket). Each bucket reports at most its top 100 groups; a group beyond that cap has no row in that bucket (there is no remainder row), so grouped buckets are not exhaustive when a dimension has more than 100 distinct values.
- `"context_window"`
- `"cost_type"`
- `"inference_geo"`
- `"model"`
- `"product"`
- `"rbac_group_id"`
- `"slack_channel_id"`
- `"speed"`
- `"token_type"`
- `inference_geos: optional array of "global" or "not_available" or "us"`
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.
- `"global"`
- `"not_available"`
- `"us"`
- `limit: optional number`
Maximum number of time buckets per page. Defaults and caps vary by bucket_width (1d: default 7, max 31; 1h: default 24, max 168; 1m: default 60, max 256).
- `models: optional array of string`
Models to include. Defaults to all models. Use `group_by[]=model` to break out per-model values.
- `page: optional string`
Opaque cursor from a previous response's `next_page` field.
- `products: optional array of string`
Product surfaces to include. Defaults to all products. Use `group_by[]=product` to break out per-product values. Values include "chat", "claude_code", "cowork", "office_agent", "claude_in_chrome", "claude_design", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it.
- `rbac_group_ids: optional array of string`
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.
- `slack_channel_ids: optional array of string`
Filter to usage originating from specific Slack channels. Use `group_by[]=slack_channel_id` to break out per-channel values.
- `speeds: optional array of "fast" or "standard"`
Filter to fast or standard inference mode. Use `group_by[]=speed` to break out per-mode values.
- `"fast"`
- `"standard"`
- `user_ids: optional array of string`
Filter to specific users by tagged user ID.
### Returns
- `CostBucket object { data, data_refreshed_at, has_more, 2 more }`
- `data: array of object { ending_at, results, starting_at }`
Time buckets for this page, oldest first: one per `bucket_width` interval, including intervals with no data (their `results` list is empty). A page holds at most `limit` buckets.
- `ending_at: string`
End of the time bucket (exclusive) in RFC 3339 format.
- `results: array of object { amount, context_window, cost_type, 10 more }`
Rows for this time bucket. Empty when the bucket has no data; otherwise a single combined row when `group_by[]` is omitted, or one row per group (subject to the per-bucket group cap described on the `group_by[]` parameter).
- `amount: string`
Amount (post-discount, pre-credit) in fractional cents.
- `context_window: "0-200k" or "200k-1M" or null`
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.
- `"0-200k"`
- `"200k-1M"`
- `cost_type: "code_execution" or "tokens" or "web_search" or null`
Cost component when `group_by[]=cost_type`; null otherwise (amount is the combined total).
- `"code_execution"`
- `"tokens"`
- `"web_search"`
- `currency: "USD"`
Currency code for the cost amount. Currently always `"USD"`.
- `"USD"`
- `inference_geo: "global" or "us" or null`
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).
- `"global"`
- `"us"`
- `list_amount: string`
List-price amount (pre-discount) in fractional cents.
- `model: string or null`
Model that produced the usage or cost, as a model name in the form the `models[]` filter accepts (for example, `claude-opus-4-6`). 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 or null`
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", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it. Some unattributed usage is reported as "other".
- `rbac_group_id: string or null`
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 with no group_by.
- `requests: number or null`
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`).
- `slack_channel_id: string or null`
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: "fast" or "standard" or null`
Inference speed mode of the usage or cost: `fast` or `standard`. Null unless `speed` is in `group_by[]`.
- `"fast"`
- `"standard"`
- `token_type: "cache_creation.ephemeral_1h_input_tokens" or "cache_creation.ephemeral_5m_input_tokens" or "cache_read_input_tokens" or 2 more or null`
Token type when `group_by[]=token_type` and `cost_type=tokens`; null otherwise.
- `"cache_creation.ephemeral_1h_input_tokens"`
- `"cache_creation.ephemeral_5m_input_tokens"`
- `"cache_read_input_tokens"`
- `"output_tokens"`
- `"uncached_input_tokens"`
- `starting_at: string`
Start of the time bucket (inclusive) in RFC 3339 format.
- `data_refreshed_at: string or null`
RFC 3339 timestamp of the export this response was served from. Null when no export yet covers any part of the requested range, in which case every bucket's `results` list is empty. Buckets beyond this watermark are incomplete; for stable results, set `ending_at` to this value or earlier. Data is typically refreshed every 4 hours but not final until about 30 days after the usage date (late-arriving events, reconciliation adjustments).
- `has_more: boolean`
Whether another page is available. When true, pass `next_page` as the `page` parameter to fetch it.
- `next_page: string or null`
Opaque cursor for the next page, or null when `has_more` is false. Pass it as the `page` parameter, keeping the other parameters unchanged. A cursor can expire after the underlying data refreshes; the request then returns HTTP 410 and pagination must restart from the first page.
- `organization_id: string`
ID of the Organization.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/cost_report \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"ending_at": "2019-12-27T18:11:19.117Z",
"results": [
{
"amount": "amount",
"context_window": "0-200k",
"cost_type": "code_execution",
"currency": "USD",
"inference_geo": "global",
"list_amount": "list_amount",
"model": "claude-opus-4-6",
"product": "chat",
"rbac_group_id": "rbac_group_012rppKaSVsmTo6NqRDXQXNF",
"requests": 0,
"slack_channel_id": "C0123ABCDEF",
"speed": "fast",
"token_type": "cache_creation.ephemeral_1h_input_tokens"
}
],
"starting_at": "2019-12-27T18:11:19.117Z"
}
],
"data_refreshed_at": "2019-12-27T18:11:19.117Z",
"has_more": true,
"next_page": "next_page",
"organization_id": "org_013FP9SaFPBg7Kw7fetjn6cF"
}
```
## Get Per-User Cost
**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.
### Query Parameters
- `starting_at: string`
Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.
- `bucket_width: optional "1d" or "1h" or "1m"`
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.
- `"1d"`
Cut at 300 lines. The page has the rest.
api/admin/analytics/cost/list First recorded · 271 lines, first recorded
## Get Cost Over Time ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Cost Over Time
url: https://platform.claude.com/docs/en/api/admin/analytics/cost/list
---
## Get Cost Over Time
**get** `/v1/organizations/analytics/cost_report`
Get cost in USD over time across a date range.
Returns cost bucketed by minute, hour, or day, optionally broken down by
product, model, context window, inference region, speed, cost type, or
token type. Available to organizations on a Claude Enterprise plan.
Requires an API key with the `read:analytics` scope.
### Query Parameters
- `starting_at: string`
Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.
- `bucket_width: optional "1d" or "1h" or "1m"`
Time bucket granularity.
- `"1d"`
- `"1h"`
- `"1m"`
- `context_windows: optional array of "0-200k" or "200k-1M"`
Filter to specific context-window pricing tiers. Use `group_by[]=context_window` to break out per-tier values.
- `"0-200k"`
- `"200k-1M"`
- `ending_at: optional string`
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.
- `group_by: optional array of "context_window" or "cost_type" or "inference_geo" or 6 more`
Dimensions to break each time bucket out by. Defaults to no grouping (one total per bucket). Each bucket reports at most its top 100 groups; a group beyond that cap has no row in that bucket (there is no remainder row), so grouped buckets are not exhaustive when a dimension has more than 100 distinct values.
- `"context_window"`
- `"cost_type"`
- `"inference_geo"`
- `"model"`
- `"product"`
- `"rbac_group_id"`
- `"slack_channel_id"`
- `"speed"`
- `"token_type"`
- `inference_geos: optional array of "global" or "not_available" or "us"`
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.
- `"global"`
- `"not_available"`
- `"us"`
- `limit: optional number`
Maximum number of time buckets per page. Defaults and caps vary by bucket_width (1d: default 7, max 31; 1h: default 24, max 168; 1m: default 60, max 256).
- `models: optional array of string`
Models to include. Defaults to all models. Use `group_by[]=model` to break out per-model values.
- `page: optional string`
Opaque cursor from a previous response's `next_page` field.
- `products: optional array of string`
Product surfaces to include. Defaults to all products. Use `group_by[]=product` to break out per-product values. Values include "chat", "claude_code", "cowork", "office_agent", "claude_in_chrome", "claude_design", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it.
- `rbac_group_ids: optional array of string`
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.
- `slack_channel_ids: optional array of string`
Filter to usage originating from specific Slack channels. Use `group_by[]=slack_channel_id` to break out per-channel values.
- `speeds: optional array of "fast" or "standard"`
Filter to fast or standard inference mode. Use `group_by[]=speed` to break out per-mode values.
- `"fast"`
- `"standard"`
- `user_ids: optional array of string`
Filter to specific users by tagged user ID.
### Returns
- `CostBucket object { data, data_refreshed_at, has_more, 2 more }`
- `data: array of object { ending_at, results, starting_at }`
Time buckets for this page, oldest first: one per `bucket_width` interval, including intervals with no data (their `results` list is empty). A page holds at most `limit` buckets.
- `ending_at: string`
End of the time bucket (exclusive) in RFC 3339 format.
- `results: array of object { amount, context_window, cost_type, 10 more }`
Rows for this time bucket. Empty when the bucket has no data; otherwise a single combined row when `group_by[]` is omitted, or one row per group (subject to the per-bucket group cap described on the `group_by[]` parameter).
- `amount: string`
Amount (post-discount, pre-credit) in fractional cents.
- `context_window: "0-200k" or "200k-1M" or null`
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.
- `"0-200k"`
- `"200k-1M"`
- `cost_type: "code_execution" or "tokens" or "web_search" or null`
Cost component when `group_by[]=cost_type`; null otherwise (amount is the combined total).
- `"code_execution"`
- `"tokens"`
- `"web_search"`
- `currency: "USD"`
Currency code for the cost amount. Currently always `"USD"`.
- `"USD"`
- `inference_geo: "global" or "us" or null`
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).
- `"global"`
- `"us"`
- `list_amount: string`
List-price amount (pre-discount) in fractional cents.
- `model: string or null`
Model that produced the usage or cost, as a model name in the form the `models[]` filter accepts (for example, `claude-opus-4-6`). 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 or null`
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", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it. Some unattributed usage is reported as "other".
- `rbac_group_id: string or null`
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 with no group_by.
- `requests: number or null`
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`).
- `slack_channel_id: string or null`
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: "fast" or "standard" or null`
Inference speed mode of the usage or cost: `fast` or `standard`. Null unless `speed` is in `group_by[]`.
- `"fast"`
- `"standard"`
- `token_type: "cache_creation.ephemeral_1h_input_tokens" or "cache_creation.ephemeral_5m_input_tokens" or "cache_read_input_tokens" or 2 more or null`
Token type when `group_by[]=token_type` and `cost_type=tokens`; null otherwise.
- `"cache_creation.ephemeral_1h_input_tokens"`
- `"cache_creation.ephemeral_5m_input_tokens"`
- `"cache_read_input_tokens"`
- `"output_tokens"`
- `"uncached_input_tokens"`
- `starting_at: string`
Start of the time bucket (inclusive) in RFC 3339 format.
- `data_refreshed_at: string or null`
RFC 3339 timestamp of the export this response was served from. Null when no export yet covers any part of the requested range, in which case every bucket's `results` list is empty. Buckets beyond this watermark are incomplete; for stable results, set `ending_at` to this value or earlier. Data is typically refreshed every 4 hours but not final until about 30 days after the usage date (late-arriving events, reconciliation adjustments).
- `has_more: boolean`
Whether another page is available. When true, pass `next_page` as the `page` parameter to fetch it.
- `next_page: string or null`
Opaque cursor for the next page, or null when `has_more` is false. Pass it as the `page` parameter, keeping the other parameters unchanged. A cursor can expire after the underlying data refreshes; the request then returns HTTP 410 and pagination must restart from the first page.
- `organization_id: string`
ID of the Organization.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/cost_report \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"ending_at": "2019-12-27T18:11:19.117Z",
"results": [
{
"amount": "amount",
"context_window": "0-200k",
"cost_type": "code_execution",
"currency": "USD",
"inference_geo": "global",
"list_amount": "list_amount",
"model": "claude-opus-4-6",
"product": "chat",
"rbac_group_id": "rbac_group_012rppKaSVsmTo6NqRDXQXNF",
"requests": 0,
"slack_channel_id": "C0123ABCDEF",
"speed": "fast",
"token_type": "cache_creation.ephemeral_1h_input_tokens"
}
],
"starting_at": "2019-12-27T18:11:19.117Z"
}
],
"data_refreshed_at": "2019-12-27T18:11:19.117Z",
"has_more": true,
"next_page": "next_page",
"organization_id": "org_013FP9SaFPBg7Kw7fetjn6cF"
}
```
api/admin/analytics/cost/list_by_user First recorded · 319 lines, first recorded
## Get Per-User Cost ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Per-User Cost
url: https://platform.claude.com/docs/en/api/admin/analytics/cost/list_by_user
---
## Get Per-User Cost
**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.
### Query Parameters
- `starting_at: string`
Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.
- `bucket_width: optional "1d" or "1h" or "1m"`
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.
- `"1d"`
- `"1h"`
- `"1m"`
- `context_windows: optional array of "0-200k" or "200k-1M"`
Filter to specific context-window pricing tiers. Use `group_by[]=context_window` to break out per-tier values.
- `"0-200k"`
- `"200k-1M"`
- `ending_at: optional string`
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.
- `exclude_deleted_users: optional boolean`
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.
- `group_by: optional array of "context_window" or "cost_type" or "inference_geo" or 6 more`
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.
- `"context_window"`
- `"cost_type"`
- `"inference_geo"`
- `"model"`
- `"product"`
- `"rbac_group_id"`
- `"slack_channel_id"`
- `"speed"`
- `"token_type"`
- `inference_geos: optional array of "global" or "not_available" or "us"`
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.
- `"global"`
- `"not_available"`
- `"us"`
- `limit: optional number`
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.
- `models: optional array of string`
Models to include. Defaults to all models. Use `group_by[]=model` to break out per-model values.
- `order: optional "asc" or "desc"`
Sort direction. Defaults to `desc`.
- `"asc"`
- `"desc"`
- `order_by: optional "amount" or "list_amount"`
Metric to rank actors by. Defaults to `amount`.
- `"amount"`
- `"list_amount"`
- `page: optional string`
Opaque cursor from a previous response's `next_page` field.
- `products: optional array of string`
Product surfaces to include. Defaults to all products. Values include "chat", "claude_code", "cowork", "office_agent", "claude_in_chrome", "claude_design", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it.
- `rbac_group_ids: optional array of string`
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.
- `slack_channel_ids: optional array of string`
Filter to usage originating from specific Slack channels. Use `group_by[]=slack_channel_id` to break out per-channel values.
- `speeds: optional array of "fast" or "standard"`
Filter to fast or standard inference mode. Use `group_by[]=speed` to break out per-mode values.
- `"fast"`
- `"standard"`
- `user_ids: optional array of string`
Filter to specific users by tagged user ID.
### Returns
- `UserCost object { data, data_refreshed_at, has_more, 2 more }`
- `data: array of object { actor, amount, context_window, 13 more }`
Rows for this page, ranked by `order_by` in the `order` direction. One row per user, or several per user when `group_by[]` or `bucket_width` breaks that user's usage or cost out across rows. Rows split out by `cost_type` or `token_type` (cost endpoint only) stay adjacent and are ranked as one unit.
- `actor: AnalyticsUserActor`
The user this row's usage or cost is attributed to. Always a `user_actor`.
- `deleted: boolean`
True when the user is no longer a member of the organization or its associated organizations: either their membership was removed (for example, deprovisioned via your identity provider) or the account itself has been deleted. The flag reflects organization membership, not account status. `name` and `email` stay populated for removed members; `name` is `"Deleted User"` and `email` null when the account has been deleted. The `user_id` is still populated for reconciliation.
- `email: string or null`
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 or null`
The user's current name, including for users who are no longer members of the organization or its associated organizations. Null when the user has not set a name. Returns `"Deleted User"` when the account itself has been deleted. Rows for system-minted service accounts render the service name (for example, `"Claude Security"` for usage by Anthropic's security-patching service) or null.
- `type: "user_actor"`
Actor type. Always `"user_actor"`.
- `"user_actor"`
- `user_id: string`
Tagged user ID.
- `amount: string`
Amount (post-discount, pre-credit) in fractional cents (minor units).
- `context_window: "0-200k" or "200k-1M" or null`
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.
- `"0-200k"`
- `"200k-1M"`
- `cost_type: "code_execution" or "tokens" or "web_search" or null`
Cost component breakdown; null when returning the combined total.
- `"code_execution"`
- `"tokens"`
- `"web_search"`
- `currency: "USD"`
Currency code for the cost amount. Currently always `"USD"`.
- `"USD"`
- `ending_at: string or null`
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.
- `inference_geo: "global" or "us" or null`
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).
- `"global"`
- `"us"`
- `list_amount: string`
List-price amount (pre-discount) in fractional cents.
- `model: string or null`
Model that produced the usage or cost, as a model name in the form the `models[]` filter accepts (for example, `claude-opus-4-6`). 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 or null`
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", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it. Some unattributed usage is reported as "other".
- `rbac_group_id: string or null`
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 with no group_by.
- `requests: number or null`
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`).
- `slack_channel_id: string or null`
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: "fast" or "standard" or null`
Inference speed mode of the usage or cost: `fast` or `standard`. Null unless `speed` is in `group_by[]`.
- `"fast"`
- `"standard"`
- `starting_at: string or null`
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.
- `token_type: "cache_creation.ephemeral_1h_input_tokens" or "cache_creation.ephemeral_5m_input_tokens" or "cache_read_input_tokens" or 2 more or null`
Token type when cost_type=tokens; null otherwise.
- `"cache_creation.ephemeral_1h_input_tokens"`
- `"cache_creation.ephemeral_5m_input_tokens"`
- `"cache_read_input_tokens"`
- `"output_tokens"`
- `"uncached_input_tokens"`
- `data_refreshed_at: string or null`
RFC 3339 timestamp of the export this response was served from. Null when no export yet covers any part of the requested range, in which case `data` is empty. Data beyond this watermark is incomplete; for stable results, set `ending_at` to this value or earlier. Data is typically refreshed every 4 hours but not final until about 30 days after the usage date (late-arriving events, reconciliation adjustments).
- `has_more: boolean`
Whether another page is available. When true, pass `next_page` as the `page` parameter to fetch it.
- `next_page: string or null`
Opaque cursor for the next page, or null when `has_more` is false. Pass it as the `page` parameter, keeping the other parameters unchanged. A cursor can expire after the underlying data refreshes; the request then returns HTTP 410 and pagination must restart from the first page.
- `organization_id: string`
ID of the Organization.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/user_cost_report \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"actor": {
"deleted": true,
"email": "[email protected]",
"name": "Jane Smith",
"type": "user_actor",
"user_id": "user_01AbCdEfGhIjKlMnOpQrSt"
},
"amount": "41280.000000",
"context_window": "0-200k",
"cost_type": "code_execution",
"currency": "USD",
Cut at 300 lines. The page has the rest.
api/admin/analytics/plugins First recorded · 237 lines, first recorded
# Plugins ## Get Plugin Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Plugin Usage
The first capture of this source. The page was already there, and this is what it said.
---
title: Plugins
url: https://platform.claude.com/docs/en/api/admin/analytics/plugins
---
# Plugins
## Get Plugin Usage
**get** `/v1/organizations/analytics/plugins`
Get per-plugin install + invocation usage for a given day, with pagination.
Returns plugin usage metrics for the organization across Cowork and Claude
Code, sorted by plugin name. The `plugin_name` value `third-party` is
an aggregate bucket, not a plugin: it collects plugin activity, from
either surface, for which the reporting client did not provide a plugin
name — so an organization's own plugins can contribute both to their own
named rows and to this bucket. Use group_by[] to break usage out per
member, per RBAC group, or per product surface (Cowork / Claude Code),
and filter[] to scope results; the parameter descriptions list the
supported dimensions. Requires an API key with the
`read:analytics` scope. `starting_date` / `ending_date` select
range-rollup mode like /skills.
### Query Parameters
- `date: optional string`
UTC date in YYYY-MM-DD format. The day to get plugin usage for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive); only valid with starting_date. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day), so this can be at most today — which is also the default when omitted, resolved once when the first page is served and reused for the rest of the pagination sequence. At most 366 days after starting_date.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: plugin_name, product, rbac_group_id, user_id. Value forms: plugin_name matches case-insensitively; product is claude_code or cowork (the only surfaces with plugin attribution); rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "product" or "rbac_group_id" or "user_id"`
Dimensions to break results out by (e.g. group_by[]=user_id). Supported on this endpoint: product, rbac_group_id, user_id. On this endpoint product takes the values claude_code or cowork only (the surfaces with plugin attribution). Grouped rows carry the requested dimension values as additional fields and paginate like ungrouped responses via next_page; an unsupported dimension returns 400. rbac_group_id attributes a user to every group they held at any point during each covered UTC day, so grouped rows are not an exclusive partition and can sum above org-level totals. At most 100 entries.
- `"product"`
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Number of results per page (1-1000, default 100).
- `order: optional "asc" or "desc"`
Sort direction: 'asc' or 'desc'. Defaults to 'asc' for the endpoint's sort column and to 'desc' when order_by names a metric (a top-N ranking). Applies to order_by, or to the endpoint's default sort field when order_by is omitted.
- `"asc"`
- `"desc"`
- `order_by: optional string`
Sort field. Restricted to the endpoint's sort column plus its rankable metrics (metrics default to descending; a few metrics rank in date-range mode only, per the endpoint's documented orderable set).
- `page: optional string`
Opaque cursor from a previous response's next_page field.
- `starting_date: optional string`
UTC date in YYYY-MM-DD format. Start of a date range (inclusive). Enables rollup mode: one row per entity aggregated over the whole range — addable counters are summed across days, and a distinct count is never summed where summing could double-count (a field's range value is recomputed exactly over the window, approximate via HLL with typical error under 2%, null, or — for the creation-event counts, whose per-day values cannot overlap — a per-day sum that is itself exact; each field's own description says which). Use either date or starting_date, not both. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
### Returns
- `PluginUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/plugins.
- `data: array of object { claude_code_metrics, cowork_metrics, distinct_user_count, 8 more }`
- `claude_code_metrics: object { distinct_session_plugin_used_count }`
Claude Code activity metrics for a single plugin on a given day.
- `distinct_session_plugin_used_count: number or null`
Number of distinct Claude Code sessions in which the plugin was invoked. Null on aggregated rows where a distinct count cannot be computed.
- `cowork_metrics: object { distinct_session_plugin_used_count }`
Cowork activity metrics for a single plugin on a given day.
- `distinct_session_plugin_used_count: number or null`
Number of distinct Cowork sessions in which the plugin was invoked. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users with recorded install or invocation activity for the plugin on the requested day (install-only users count), or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `install_count: number or null`
Number of distinct users who installed the plugin on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `invocation_count: number`
Number of plugin invocations on the requested day
- `plugin_name: string`
Name of the plugin
- `plugin_id: optional string or null`
Stable plugin identifier when available (e.g. serena@claude-plugins-official). Null for third-party Claude Code plugins (redacted at the source) and Cowork slash commands that carry only a hashed id.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/plugins \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"claude_code_metrics": {
"distinct_session_plugin_used_count": 0
},
"cowork_metrics": {
"distinct_session_plugin_used_count": 0
},
"distinct_user_count": 0,
"install_count": 0,
"invocation_count": 0,
"plugin_name": "plugin_name",
"plugin_id": "plugin_id",
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"user_id": "user_id"
}
],
"next_page": "next_page"
}
```
## Domain Types
### Plugin Usage
- `PluginUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/plugins.
- `data: array of object { claude_code_metrics, cowork_metrics, distinct_user_count, 8 more }`
- `claude_code_metrics: object { distinct_session_plugin_used_count }`
Claude Code activity metrics for a single plugin on a given day.
- `distinct_session_plugin_used_count: number or null`
Number of distinct Claude Code sessions in which the plugin was invoked. Null on aggregated rows where a distinct count cannot be computed.
- `cowork_metrics: object { distinct_session_plugin_used_count }`
Cowork activity metrics for a single plugin on a given day.
- `distinct_session_plugin_used_count: number or null`
Number of distinct Cowork sessions in which the plugin was invoked. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users with recorded install or invocation activity for the plugin on the requested day (install-only users count), or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `install_count: number or null`
Number of distinct users who installed the plugin on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `invocation_count: number`
Number of plugin invocations on the requested day
- `plugin_name: string`
Name of the plugin
- `plugin_id: optional string or null`
Stable plugin identifier when available (e.g. serena@claude-plugins-official). Null for third-party Claude Code plugins (redacted at the source) and Cowork slash commands that carry only a hashed id.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
api/admin/analytics/plugins/list First recorded · 169 lines, first recorded
## Get Plugin Usage ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Plugin Usage
url: https://platform.claude.com/docs/en/api/admin/analytics/plugins/list
---
## Get Plugin Usage
**get** `/v1/organizations/analytics/plugins`
Get per-plugin install + invocation usage for a given day, with pagination.
Returns plugin usage metrics for the organization across Cowork and Claude
Code, sorted by plugin name. The `plugin_name` value `third-party` is
an aggregate bucket, not a plugin: it collects plugin activity, from
either surface, for which the reporting client did not provide a plugin
name — so an organization's own plugins can contribute both to their own
named rows and to this bucket. Use group_by[] to break usage out per
member, per RBAC group, or per product surface (Cowork / Claude Code),
and filter[] to scope results; the parameter descriptions list the
supported dimensions. Requires an API key with the
`read:analytics` scope. `starting_date` / `ending_date` select
range-rollup mode like /skills.
### Query Parameters
- `date: optional string`
UTC date in YYYY-MM-DD format. The day to get plugin usage for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive); only valid with starting_date. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day), so this can be at most today — which is also the default when omitted, resolved once when the first page is served and reused for the rest of the pagination sequence. At most 366 days after starting_date.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: plugin_name, product, rbac_group_id, user_id. Value forms: plugin_name matches case-insensitively; product is claude_code or cowork (the only surfaces with plugin attribution); rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "product" or "rbac_group_id" or "user_id"`
Dimensions to break results out by (e.g. group_by[]=user_id). Supported on this endpoint: product, rbac_group_id, user_id. On this endpoint product takes the values claude_code or cowork only (the surfaces with plugin attribution). Grouped rows carry the requested dimension values as additional fields and paginate like ungrouped responses via next_page; an unsupported dimension returns 400. rbac_group_id attributes a user to every group they held at any point during each covered UTC day, so grouped rows are not an exclusive partition and can sum above org-level totals. At most 100 entries.
- `"product"`
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Number of results per page (1-1000, default 100).
- `order: optional "asc" or "desc"`
Sort direction: 'asc' or 'desc'. Defaults to 'asc' for the endpoint's sort column and to 'desc' when order_by names a metric (a top-N ranking). Applies to order_by, or to the endpoint's default sort field when order_by is omitted.
- `"asc"`
- `"desc"`
- `order_by: optional string`
Sort field. Restricted to the endpoint's sort column plus its rankable metrics (metrics default to descending; a few metrics rank in date-range mode only, per the endpoint's documented orderable set).
- `page: optional string`
Opaque cursor from a previous response's next_page field.
- `starting_date: optional string`
UTC date in YYYY-MM-DD format. Start of a date range (inclusive). Enables rollup mode: one row per entity aggregated over the whole range — addable counters are summed across days, and a distinct count is never summed where summing could double-count (a field's range value is recomputed exactly over the window, approximate via HLL with typical error under 2%, null, or — for the creation-event counts, whose per-day values cannot overlap — a per-day sum that is itself exact; each field's own description says which). Use either date or starting_date, not both. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
### Returns
- `PluginUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/plugins.
- `data: array of object { claude_code_metrics, cowork_metrics, distinct_user_count, 8 more }`
- `claude_code_metrics: object { distinct_session_plugin_used_count }`
Claude Code activity metrics for a single plugin on a given day.
- `distinct_session_plugin_used_count: number or null`
Number of distinct Claude Code sessions in which the plugin was invoked. Null on aggregated rows where a distinct count cannot be computed.
- `cowork_metrics: object { distinct_session_plugin_used_count }`
Cowork activity metrics for a single plugin on a given day.
- `distinct_session_plugin_used_count: number or null`
Number of distinct Cowork sessions in which the plugin was invoked. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users with recorded install or invocation activity for the plugin on the requested day (install-only users count), or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `install_count: number or null`
Number of distinct users who installed the plugin on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values.
- `invocation_count: number`
Number of plugin invocations on the requested day
- `plugin_name: string`
Name of the plugin
- `plugin_id: optional string or null`
Stable plugin identifier when available (e.g. serena@claude-plugins-official). Null for third-party Claude Code plugins (redacted at the source) and Cowork slash commands that carry only a hashed id.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/plugins \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"claude_code_metrics": {
"distinct_session_plugin_used_count": 0
},
"cowork_metrics": {
"distinct_session_plugin_used_count": 0
},
"distinct_user_count": 0,
"install_count": 0,
"invocation_count": 0,
"plugin_name": "plugin_name",
"plugin_id": "plugin_id",
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"user_id": "user_id"
}
],
"next_page": "next_page"
}
```
api/admin/analytics/retrieve_summaries First recorded · 204 lines, first recorded
## Get Activity Summaries ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Activity Summaries
url: https://platform.claude.com/docs/en/api/admin/analytics/retrieve_summaries
---
## Get Activity Summaries
**get** `/v1/organizations/analytics/summaries`
Get organization-wide activity summaries for a date range.
Returns one entry per day in [starting_date, ending_date). Data is
typically available with a 1-day lag and may be revised by a few percent
over the following days: when ending_date is omitted it defaults to the
most recent available day + 1, so the last entry covers the most recent
available day. The series can be scoped to an RBAC group via
filter[]=rbac_group_id:<id>. Available to organizations on a Claude
Enterprise plan. Requires an API key with the `read:analytics` scope.
### Query Parameters
- `starting_date: string`
UTC date in YYYY-MM-DD format. Start of the date range (inclusive). Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive). Data is typically available with a 1-day lag, so this can be at most today — which is also the default when omitted, making the last entry cover the most recent available day. Data may be revised by a few percent over the following days. The range may span at most 366 days.
- `filter: optional array of string`
Filters as 'dimension:value'. Only rbac_group_id is supported (e.g. filter[]=rbac_group_id:<id>); repeat the param to OR across groups. Scopes the whole day series to members of the matching group(s), re-aggregated from member-level activity — org-wide seat/invite fields and the adoption rates derived from them are null on scoped rows. rbac_group_id accepts the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each UTC day (time-of-usage attribution). At most 100 entries.
### Returns
- `ActivitySummary object { summaries }`
Response for GET /v1/organizations/analytics/summaries.
- `summaries: array of object { assigned_seat_count, cowork_daily_active_user_count, cowork_monthly_active_user_count, 26 more }`
- `assigned_seat_count: number or null`
Number of seats currently assigned to members. Null when the response is scoped to an RBAC group — seat assignment is org-wide and has no per-group analogue.
- `cowork_daily_active_user_count: number`
Number of users with Cowork activity on the requested day
- `cowork_monthly_active_user_count: number`
Number of users with Cowork activity in the 30-day rolling window
- `cowork_weekly_active_user_count: number`
Number of users with Cowork activity in the 7-day rolling window
- `daily_active_user_count: number`
Number of users with token consumption on the requested day
- `daily_adoption_rate: number or null`
Percentage of assigned seats with activity on the requested day (`DAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `ending_at: string`
End time in UTC of aggregation period (e.g. 2026-01-16T00:00:00Z)
- `monthly_active_user_count: number`
Number of users with token consumption in the 30-day rolling window
- `monthly_adoption_rate: number or null`
Percentage of assigned seats with activity in the 30-day rolling window (`MAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `pending_invite_count: number or null`
Number of pending invitations to join the organization. Null when the response is scoped to an RBAC group.
- `starting_at: string`
Start time in UTC of aggregation period (e.g. 2026-01-15T00:00:00Z)
- `weekly_active_user_count: number`
Number of users with token consumption in the 7-day rolling window
- `weekly_adoption_rate: number or null`
Percentage of assigned seats with activity in the 7-day rolling window (`WAU / assigned_seat_count * 100`). Null when the response is scoped to an RBAC group.
- `chat_daily_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `chat_monthly_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `chat_weekly_active_user_count: optional number or null`
Number of users with claude.ai (chat) activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_daily_active_user_count: optional number or null`
Number of users with Claude Code activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_monthly_active_user_count: optional number or null`
Number of users with Claude Code activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_code_weekly_active_user_count: optional number or null`
Number of users with Claude Code activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_design_daily_active_user_count: optional number or null`
Number of users with Claude Design activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_design_monthly_active_user_count: optional number or null`
Number of users with Claude Design activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `claude_design_weekly_active_user_count: optional number or null`
Number of users with Claude Design activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `office_agent_daily_active_user_count: optional number or null`
Number of users with Claude in Office activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `office_agent_monthly_active_user_count: optional number or null`
Number of users with Claude in Office activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `office_agent_weekly_active_user_count: optional number or null`
Number of users with Claude in Office activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `science_daily_active_user_count: optional number or null`
Number of users with Claude Science activity on the requested day. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `science_entitled_user_count: optional number or null`
Number of users with a Claude Science seat entitlement (per-seat RBAC) at the time of the daily snapshot. The funnel top; independent of the org-level Claude Science toggle. Null when the response is scoped to an RBAC group — entitlement is org-wide and has no per-group analogue. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `science_monthly_active_user_count: optional number or null`
Number of users with Claude Science activity in the 30-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
- `science_weekly_active_user_count: optional number or null`
Number of users with Claude Science activity in the 7-day rolling window. Omitted from the response while the per-product breakdown is not enabled for this organization.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/summaries \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"summaries": [
{
"assigned_seat_count": 0,
"cowork_daily_active_user_count": 0,
"cowork_monthly_active_user_count": 0,
"cowork_weekly_active_user_count": 0,
"daily_active_user_count": 0,
"daily_adoption_rate": 0,
"ending_at": "ending_at",
"monthly_active_user_count": 0,
"monthly_adoption_rate": 0,
"pending_invite_count": 0,
"starting_at": "starting_at",
"weekly_active_user_count": 0,
"weekly_adoption_rate": 0,
"chat_daily_active_user_count": 0,
"chat_monthly_active_user_count": 0,
"chat_weekly_active_user_count": 0,
"claude_code_daily_active_user_count": 0,
"claude_code_monthly_active_user_count": 0,
"claude_code_weekly_active_user_count": 0,
"claude_design_daily_active_user_count": 0,
"claude_design_monthly_active_user_count": 0,
"claude_design_weekly_active_user_count": 0,
"office_agent_daily_active_user_count": 0,
"office_agent_monthly_active_user_count": 0,
"office_agent_weekly_active_user_count": 0,
"science_daily_active_user_count": 0,
"science_entitled_user_count": 0,
"science_monthly_active_user_count": 0,
"science_weekly_active_user_count": 0
}
]
}
```
api/admin/analytics/skills First recorded · 353 lines, first recorded
# Skills ## Get Skill Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Skill Usage
The first capture of this source. The page was already there, and this is what it said.
---
title: Skills
url: https://platform.claude.com/docs/en/api/admin/analytics/skills
---
# Skills
## Get Skill Usage
**get** `/v1/organizations/analytics/skills`
Get per-skill usage for a given day, with cursor-based pagination.
Returns skill usage metrics for the organization, sorted by skill name.
Use group_by[] to break usage out per member, per RBAC group, or per
product surface, and filter[] to scope results; the parameter
descriptions list the supported dimensions. Available to organizations
on a Claude Enterprise plan. Requires an API key with the
`read:analytics` scope.
### Query Parameters
- `date: optional string`
UTC date in YYYY-MM-DD format. The day to get skill usage for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive); only valid with starting_date. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day), so this can be at most today — which is also the default when omitted, resolved once when the first page is served and reused for the rest of the pagination sequence. At most 366 days after starting_date.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: product, rbac_group_id, share_status, skill_name, user_id. Value forms: product is one of chat, claude_code, cowork, or office_agent; rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); share_status is one of organization, private, or public; skill_name matches case-insensitively; user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "product" or "rbac_group_id" or "user_id"`
Dimensions to break results out by (e.g. group_by[]=user_id). Supported on this endpoint: product, rbac_group_id, user_id. Grouped rows carry the requested dimension values as additional fields and paginate like ungrouped responses via next_page; an unsupported dimension returns 400. rbac_group_id attributes a user to every group they held at any point during each covered UTC day, so grouped rows are not an exclusive partition and can sum above org-level totals. At most 100 entries.
- `"product"`
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Number of results per page (1-1000, default 100).
- `order: optional "asc" or "desc"`
Sort direction: 'asc' or 'desc'. Defaults to 'asc' for the endpoint's sort column and to 'desc' when order_by names a metric (a top-N ranking). Applies to order_by, or to the endpoint's default sort field when order_by is omitted.
- `"asc"`
- `"desc"`
- `order_by: optional string`
Sort field. Restricted to the endpoint's sort column plus its rankable metrics (metrics default to descending; a few metrics rank in date-range mode only, per the endpoint's documented orderable set).
- `page: optional string`
Opaque cursor from a previous response's next_page field.
- `starting_date: optional string`
UTC date in YYYY-MM-DD format. Start of a date range (inclusive). Enables rollup mode: one row per entity aggregated over the whole range — addable counters are summed across days, and a distinct count is never summed where summing could double-count (a field's range value is recomputed exactly over the window, approximate via HLL with typical error under 2%, null, or — for the creation-event counts, whose per-day values cannot overlap — a per-day sum that is itself exact; each field's own description says which). Use either date or starting_date, not both. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
### Returns
- `SkillUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/skills.
- `data: array of object { chat_metrics, claude_code_metrics, cowork_metrics, 14 more }`
- `chat_metrics: object { distinct_conversation_skill_used_count }`
Claude.ai activity metrics for a single skill on a given day.
- `distinct_conversation_skill_used_count: number or null`
Number of distinct conversations in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `claude_code_metrics: object { distinct_session_skill_used_count }`
Claude Code activity metrics for a single skill on a given day.
- `distinct_session_skill_used_count: number or null`
Number of distinct Claude Code sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `cowork_metrics: object { distinct_session_skill_used_count }`
Cowork activity metrics for a single skill on a given day.
- `distinct_session_skill_used_count: number or null`
Number of distinct Cowork sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users who used the skill on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted.
- `office_metrics: object { excel, outlook, powerpoint, word }`
Office Agent activity metrics for a single skill on a given day, broken out by Office product.
- `excel: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `distinct_session_skill_used_count: number or null`
Number of distinct Office Agent sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `outlook: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `powerpoint: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `word: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `skill_name: string`
Name of the skill
- `attributed_list_price: optional string or null`
List-price (rate-card) value of the member requests attributed to this skill, as a decimal string in the minor unit of `currency` (cents for USD), from Claude Code, Cowork, and Office Agent request-level attribution — the value of requests that INVOLVED the skill, not the skill's incremental cost. Unlike estimated_overage_spend this reflects usage value regardless of how it was funded — seat-covered usage counts — but it is undiscounted and does NOT tie to billed spend or the organization's spend reporting. claude.ai chat usage carries no request-level attribution and contributes nothing: the field is null on chat product rows and on office_agent product cuts dated before 2026-06-18 (the Office Agent attribution data-start), and on ungrouped rows it covers the Claude Code + Cowork + Office Agent share only (null when no attributable usage exists). Also null under the same conditions as estimated_overage_spend (spend reporting not enabled for this organization, office_agent product cuts before the 2026-06-18 data-start). "0" means attributable usage existed but none was attributed to this skill. Addable across days: date-range rollup mode returns the window's sum. On `group_by[]` and `filter[]` shapes both amounts can total below the ungrouped value for the same skill over the same date or range: spend attributed to a member–skill pair with no counted usage on that day is excluded from those cuts.
- `currency: optional "USD" or null`
Currency for this row's monetary fields (estimated_overage_spend and attributed_list_price), as an uppercase ISO-4217 code. Always "USD" when either amount is populated; null whenever both amounts are null.
- `"USD"`
- `enable_count: optional number or null`
Distinct accounts that enabled this skill on the requested day (claude.ai only — the skill analog of plugin install_count). The count is org-wide: null when enable reporting is not enabled for this organization, or when the request scopes to `user_id` / `rbac_group_id` / `product` via `group_by[]` or `filter[]` (an org-wide count would be misleading on per-cut rows). A distinct count, not an event count: summing across days double-counts members who enable the skill on more than one day, so it is also null in date-range rollup mode (starting_date/ending_date).
- `estimated_overage_spend: optional string or null`
Estimated OVERAGE spend attributed to this skill, as a decimal string in the minor unit of `currency` (cents for USD; "1250" is $12.50, fractional cents possible) — an allocation of each member's daily post-discount, pre-credit metered overage spend (the same cost basis as the organization's spend reporting and the Cost & Usage API, so per-skill figures are directly comparable; spend with no skill attribution — including any member-day without skill invocations — is not represented, so skill rows sum to at most those totals) across the skills the member used. Overage only: usage covered by included seat allowances bills nothing and allocates $0 here — see attributed_list_price for the funding-independent usage-value companion. Claude Code, Cowork, and Office Agent spend use request-level skill attribution; claude.ai chat spend is approximated proportionally to skill-invoking messages. An estimate, not a billing number — and the cost of the requests/messages that INVOLVED the skill, not the skill's incremental cost (the same request would still have cost something without the skill active). "0" means no overage spend was attributed; null when spend reporting is not enabled for this organization, on office_agent product cuts dated before 2026-06-18 (the Office Agent attribution data-start). Addable across days: date-range rollup mode (starting_date/ending_date) returns the window's sum. With `group_by[]=user_id` each row carries the user's own attributed spend. On `group_by[]` and `filter[]` shapes both amounts can total below the ungrouped value for the same skill over the same date or range: spend attributed to a member–skill pair with no counted usage on that day is excluded from those cuts.
- `invocation_count: optional number or null`
Total number of times this skill was invoked on the requested day (the skill analog of plugin invocation_count). Unlike distinct_user_count — which answers '\# of users' — this is the true '# of uses'. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Null when invocation reporting is not enabled for this organization. Sum across a date range for total uses in the window — date-range rollup mode (starting_date/ending_date) returns this sum directly.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `share_status: optional string or null`
Skill share status (claude.ai only): one of 'private', 'organization', or 'public'. Null for skills used only in Claude Code or Office (no per-skill share-status concept) and when share-status reporting is not yet available for the organization. Filterable via `filter[]=share_status:<value>`.
- `skill_display_name: optional string or null`
Human-readable display name for rows whose skill_name is an opaque skill id (user/organization skill types — user-defined names are withheld from the analytics pipeline). Only organization-shared skills resolve; the literal 'unknown' bucket row also gets a fixed 'Unknown skill' label. Null for private (user-defined) skills — their names are not disclosed to analytics-key holders — and null when skill_name is already a display name, when the skill was deleted, or when display-name resolution is not enabled for this organization.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/skills \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"chat_metrics": {
"distinct_conversation_skill_used_count": 0
},
"claude_code_metrics": {
"distinct_session_skill_used_count": 0
},
"cowork_metrics": {
"distinct_session_skill_used_count": 0
},
"distinct_user_count": 0,
"office_metrics": {
"excel": {
"distinct_session_skill_used_count": 0
},
"outlook": {
"distinct_session_skill_used_count": 0
},
"powerpoint": {
"distinct_session_skill_used_count": 0
},
"word": {
"distinct_session_skill_used_count": 0
}
},
"skill_name": "skill_name",
"attributed_list_price": "attributed_list_price",
"currency": "USD",
"enable_count": 0,
"estimated_overage_spend": "estimated_overage_spend",
"invocation_count": 0,
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"share_status": "share_status",
"skill_display_name": "skill_display_name",
"user_id": "user_id"
}
],
"next_page": "next_page"
}
```
## Domain Types
### Skill Usage
- `SkillUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/skills.
- `data: array of object { chat_metrics, claude_code_metrics, cowork_metrics, 14 more }`
- `chat_metrics: object { distinct_conversation_skill_used_count }`
Claude.ai activity metrics for a single skill on a given day.
- `distinct_conversation_skill_used_count: number or null`
Number of distinct conversations in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `claude_code_metrics: object { distinct_session_skill_used_count }`
Claude Code activity metrics for a single skill on a given day.
- `distinct_session_skill_used_count: number or null`
Number of distinct Claude Code sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `cowork_metrics: object { distinct_session_skill_used_count }`
Cowork activity metrics for a single skill on a given day.
- `distinct_session_skill_used_count: number or null`
Number of distinct Cowork sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users who used the skill on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted.
- `office_metrics: object { excel, outlook, powerpoint, word }`
Office Agent activity metrics for a single skill on a given day, broken out by Office product.
- `excel: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `distinct_session_skill_used_count: number or null`
Number of distinct Office Agent sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `outlook: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `powerpoint: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `word: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
Cut at 300 lines. The page has the rest.
api/admin/analytics/skills/list First recorded · 235 lines, first recorded
## Get Skill Usage ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Skill Usage
url: https://platform.claude.com/docs/en/api/admin/analytics/skills/list
---
## Get Skill Usage
**get** `/v1/organizations/analytics/skills`
Get per-skill usage for a given day, with cursor-based pagination.
Returns skill usage metrics for the organization, sorted by skill name.
Use group_by[] to break usage out per member, per RBAC group, or per
product surface, and filter[] to scope results; the parameter
descriptions list the supported dimensions. Available to organizations
on a Claude Enterprise plan. Requires an API key with the
`read:analytics` scope.
### Query Parameters
- `date: optional string`
UTC date in YYYY-MM-DD format. The day to get skill usage for. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
- `ending_date: optional string`
UTC date in YYYY-MM-DD format. End of the date range (exclusive); only valid with starting_date. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day), so this can be at most today — which is also the default when omitted, resolved once when the first page is served and reused for the rest of the pagination sequence. At most 366 days after starting_date.
- `filter: optional array of string`
Filters as 'dimension:value', e.g. filter[]=rbac_group_id:<id>. Repeat the param for OR within a dimension and across dimensions for AND. Supported dimensions on this endpoint: product, rbac_group_id, share_status, skill_name, user_id. Value forms: product is one of chat, claude_code, cowork, or office_agent; rbac_group_id takes the tagged id (rbac_group_..., as emitted in responses and by the spend-limits API) or a bare group UUID, and matches users who held the group at any point during each covered UTC day (time-of-usage attribution); share_status is one of organization, private, or public; skill_name matches case-insensitively; user_id takes a tagged user id (user_...), as emitted in responses. An unsupported dimension returns 400. At most 100 entries.
- `group_by: optional array of "product" or "rbac_group_id" or "user_id"`
Dimensions to break results out by (e.g. group_by[]=user_id). Supported on this endpoint: product, rbac_group_id, user_id. Grouped rows carry the requested dimension values as additional fields and paginate like ungrouped responses via next_page; an unsupported dimension returns 400. rbac_group_id attributes a user to every group they held at any point during each covered UTC day, so grouped rows are not an exclusive partition and can sum above org-level totals. At most 100 entries.
- `"product"`
- `"rbac_group_id"`
- `"user_id"`
- `limit: optional number`
Number of results per page (1-1000, default 100).
- `order: optional "asc" or "desc"`
Sort direction: 'asc' or 'desc'. Defaults to 'asc' for the endpoint's sort column and to 'desc' when order_by names a metric (a top-N ranking). Applies to order_by, or to the endpoint's default sort field when order_by is omitted.
- `"asc"`
- `"desc"`
- `order_by: optional string`
Sort field. Restricted to the endpoint's sort column plus its rankable metrics (metrics default to descending; a few metrics rank in date-range mode only, per the endpoint's documented orderable set).
- `page: optional string`
Opaque cursor from a previous response's next_page field.
- `starting_date: optional string`
UTC date in YYYY-MM-DD format. Start of a date range (inclusive). Enables rollup mode: one row per entity aggregated over the whole range — addable counters are summed across days, and a distinct count is never summed where summing could double-count (a field's range value is recomputed exactly over the window, approximate via HLL with typical error under 2%, null, or — for the creation-event counts, whose per-day values cannot overlap — a per-day sum that is itself exact; each field's own description says which). Use either date or starting_date, not both. Data is typically available with a 1-day lag (varies by query; the error for a too-recent date names the latest available day) and may be revised by a few percent over the following days. No earlier than 2026-01-01.
### Returns
- `SkillUsage object { data, next_page }`
Response for GET /v1/organizations/analytics/skills.
- `data: array of object { chat_metrics, claude_code_metrics, cowork_metrics, 14 more }`
- `chat_metrics: object { distinct_conversation_skill_used_count }`
Claude.ai activity metrics for a single skill on a given day.
- `distinct_conversation_skill_used_count: number or null`
Number of distinct conversations in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `claude_code_metrics: object { distinct_session_skill_used_count }`
Claude Code activity metrics for a single skill on a given day.
- `distinct_session_skill_used_count: number or null`
Number of distinct Claude Code sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `cowork_metrics: object { distinct_session_skill_used_count }`
Cowork activity metrics for a single skill on a given day.
- `distinct_session_skill_used_count: number or null`
Number of distinct Cowork sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `distinct_user_count: number`
Number of distinct users who used the skill on the requested day, or, in date-range mode, over the requested window — recomputed as an exact distinct count over the window's per-member daily rows, never a sum of per-day values. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted.
- `office_metrics: object { excel, outlook, powerpoint, word }`
Office Agent activity metrics for a single skill on a given day, broken out by Office product.
- `excel: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `distinct_session_skill_used_count: number or null`
Number of distinct Office Agent sessions in which the skill was used. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Approximate (HLL, typical error <2%) in date-range mode. Null on aggregated rows where a distinct count cannot be computed.
- `outlook: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `powerpoint: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `word: SkillOfficeProductMetrics`
Office Agent activity metrics for a single skill on a given day within one Office product.
- `skill_name: string`
Name of the skill
- `attributed_list_price: optional string or null`
List-price (rate-card) value of the member requests attributed to this skill, as a decimal string in the minor unit of `currency` (cents for USD), from Claude Code, Cowork, and Office Agent request-level attribution — the value of requests that INVOLVED the skill, not the skill's incremental cost. Unlike estimated_overage_spend this reflects usage value regardless of how it was funded — seat-covered usage counts — but it is undiscounted and does NOT tie to billed spend or the organization's spend reporting. claude.ai chat usage carries no request-level attribution and contributes nothing: the field is null on chat product rows and on office_agent product cuts dated before 2026-06-18 (the Office Agent attribution data-start), and on ungrouped rows it covers the Claude Code + Cowork + Office Agent share only (null when no attributable usage exists). Also null under the same conditions as estimated_overage_spend (spend reporting not enabled for this organization, office_agent product cuts before the 2026-06-18 data-start). "0" means attributable usage existed but none was attributed to this skill. Addable across days: date-range rollup mode returns the window's sum. On `group_by[]` and `filter[]` shapes both amounts can total below the ungrouped value for the same skill over the same date or range: spend attributed to a member–skill pair with no counted usage on that day is excluded from those cuts.
- `currency: optional "USD" or null`
Currency for this row's monetary fields (estimated_overage_spend and attributed_list_price), as an uppercase ISO-4217 code. Always "USD" when either amount is populated; null whenever both amounts are null.
- `"USD"`
- `enable_count: optional number or null`
Distinct accounts that enabled this skill on the requested day (claude.ai only — the skill analog of plugin install_count). The count is org-wide: null when enable reporting is not enabled for this organization, or when the request scopes to `user_id` / `rbac_group_id` / `product` via `group_by[]` or `filter[]` (an org-wide count would be misleading on per-cut rows). A distinct count, not an event count: summing across days double-counts members who enable the skill on more than one day, so it is also null in date-range rollup mode (starting_date/ending_date).
- `estimated_overage_spend: optional string or null`
Estimated OVERAGE spend attributed to this skill, as a decimal string in the minor unit of `currency` (cents for USD; "1250" is $12.50, fractional cents possible) — an allocation of each member's daily post-discount, pre-credit metered overage spend (the same cost basis as the organization's spend reporting and the Cost & Usage API, so per-skill figures are directly comparable; spend with no skill attribution — including any member-day without skill invocations — is not represented, so skill rows sum to at most those totals) across the skills the member used. Overage only: usage covered by included seat allowances bills nothing and allocates $0 here — see attributed_list_price for the funding-independent usage-value companion. Claude Code, Cowork, and Office Agent spend use request-level skill attribution; claude.ai chat spend is approximated proportionally to skill-invoking messages. An estimate, not a billing number — and the cost of the requests/messages that INVOLVED the skill, not the skill's incremental cost (the same request would still have cost something without the skill active). "0" means no overage spend was attributed; null when spend reporting is not enabled for this organization, on office_agent product cuts dated before 2026-06-18 (the Office Agent attribution data-start). Addable across days: date-range rollup mode (starting_date/ending_date) returns the window's sum. With `group_by[]=user_id` each row carries the user's own attributed spend. On `group_by[]` and `filter[]` shapes both amounts can total below the ungrouped value for the same skill over the same date or range: spend attributed to a member–skill pair with no counted usage on that day is excluded from those cuts.
- `invocation_count: optional number or null`
Total number of times this skill was invoked on the requested day (the skill analog of plugin invocation_count). Unlike distinct_user_count — which answers '\# of users' — this is the true '# of uses'. A skill counts as used only when it is explicitly activated — the model (or the user, via the skill's slash command) invokes it, reading its instructions into context as part of that activation. Skills that are merely installed or listed as available, or whose content reaches the context without an activation (preloaded, hook-injected, or read as a plain file), are not counted. Null when invocation reporting is not enabled for this organization. Sum across a date range for total uses in the window — date-range rollup mode (starting_date/ending_date) returns this sum directly.
- `product: optional string or null`
Product that produced this row's activity: one of chat, claude_code, cowork, or office_agent (the canonical Cost & Usage product naming; an office_agent row's per-surface breakdown is in its office_metrics). On /plugins only cowork and claude_code occur (the only surfaces with plugin attribution); /artifacts and /apps/chat/projects do not support the product dimension (a product `group_by[]` or `filter[]` there is rejected). Present only when the request grouped by product.
- `rbac_group_id: optional string or null`
Tagged RBAC group identifier (`rbac_group_...`), matching the spend-limits API spelling. Present only when the request grouped by `rbac_group_id`.
- `rbac_group_name: optional string or null`
Resolved RBAC group display name, alongside `rbac_group_id` when name resolution is available. Null if the group has been deleted or its name could not be resolved; `rbac_group_id` remains the stable key.
- `share_status: optional string or null`
Skill share status (claude.ai only): one of 'private', 'organization', or 'public'. Null for skills used only in Claude Code or Office (no per-skill share-status concept) and when share-status reporting is not yet available for the organization. Filterable via `filter[]=share_status:<value>`.
- `skill_display_name: optional string or null`
Human-readable display name for rows whose skill_name is an opaque skill id (user/organization skill types — user-defined names are withheld from the analytics pipeline). Only organization-shared skills resolve; the literal 'unknown' bucket row also gets a fixed 'Unknown skill' label. Null for private (user-defined) skills — their names are not disclosed to analytics-key holders — and null when skill_name is already a display name, when the skill was deleted, or when display-name resolution is not enabled for this organization.
- `user_id: optional string or null`
Tagged user identifier (e.g. `user_...`). Present only when the request grouped by `user_id`.
- `next_page: string or null`
Opaque cursor for the next page, or null if no more results
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/skills \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"chat_metrics": {
"distinct_conversation_skill_used_count": 0
},
"claude_code_metrics": {
"distinct_session_skill_used_count": 0
},
"cowork_metrics": {
"distinct_session_skill_used_count": 0
},
"distinct_user_count": 0,
"office_metrics": {
"excel": {
"distinct_session_skill_used_count": 0
},
"outlook": {
"distinct_session_skill_used_count": 0
},
"powerpoint": {
"distinct_session_skill_used_count": 0
},
"word": {
"distinct_session_skill_used_count": 0
}
},
"skill_name": "skill_name",
"attributed_list_price": "attributed_list_price",
"currency": "USD",
"enable_count": 0,
"estimated_overage_spend": "estimated_overage_spend",
"invocation_count": 0,
"product": "product",
"rbac_group_id": "rbac_group_id",
"rbac_group_name": "rbac_group_name",
"share_status": "share_status",
"skill_display_name": "skill_display_name",
"user_id": "user_id"
}
],
"next_page": "next_page"
}
```
api/admin/analytics/usage First recorded · 839 lines, first recorded
# Usage ## Get Token Usage Over Time ### Query Parameters ### Returns ### Example #### Response ## Get Per-User Token Usage ### Query Parameters ### Returns ### Example #### Response ## Domain Types ### Usage Bucket ### User Usage
The first capture of this source. The page was already there, and this is what it said.
---
title: Usage
url: https://platform.claude.com/docs/en/api/admin/analytics/usage
---
# Usage
## Get Token Usage Over Time
**get** `/v1/organizations/analytics/usage_report`
Get token usage over time across a date range.
Returns token usage bucketed by minute, hour, or day, optionally broken
down by product, model, context window, inference region, or speed.
Available to organizations on a Claude Enterprise plan. Requires an API
key with the `read:analytics` scope.
### Query Parameters
- `starting_at: string`
Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.
- `bucket_width: optional "1d" or "1h" or "1m"`
Time bucket granularity.
- `"1d"`
- `"1h"`
- `"1m"`
- `context_windows: optional array of "0-200k" or "200k-1M"`
Filter to specific context-window pricing tiers. Use `group_by[]=context_window` to break out per-tier values.
- `"0-200k"`
- `"200k-1M"`
- `ending_at: optional string`
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.
- `group_by: optional array of "context_window" or "inference_geo" or "model" or 4 more`
Dimensions to break each time bucket out by. Defaults to no grouping (one total per bucket). Each bucket reports at most its top 100 groups; a group beyond that cap has no row in that bucket (there is no remainder row), so grouped buckets are not exhaustive when a dimension has more than 100 distinct values.
- `"context_window"`
- `"inference_geo"`
- `"model"`
- `"product"`
- `"rbac_group_id"`
- `"slack_channel_id"`
- `"speed"`
- `inference_geos: optional array of "global" or "not_available" or "us"`
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.
- `"global"`
- `"not_available"`
- `"us"`
- `limit: optional number`
Maximum number of time buckets per page. Defaults and caps vary by bucket_width (1d: default 7, max 31; 1h: default 24, max 168; 1m: default 60, max 256).
- `models: optional array of string`
Models to include. Defaults to all models. Use `group_by[]=model` to break out per-model values.
- `page: optional string`
Opaque cursor from a previous response's `next_page` field.
- `products: optional array of string`
Product surfaces to include. Defaults to all products. Use `group_by[]=product` to break out per-product values. Values include "chat", "claude_code", "cowork", "office_agent", "claude_in_chrome", "claude_design", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it.
- `rbac_group_ids: optional array of string`
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.
- `slack_channel_ids: optional array of string`
Filter to usage originating from specific Slack channels. Use `group_by[]=slack_channel_id` to break out per-channel values.
- `speeds: optional array of "fast" or "standard"`
Filter to fast or standard inference mode. Use `group_by[]=speed` to break out per-mode values.
- `"fast"`
- `"standard"`
- `user_ids: optional array of string`
Filter to specific users by tagged user ID.
### Returns
- `UsageBucket object { data, data_refreshed_at, has_more, 2 more }`
- `data: array of object { ending_at, results, starting_at }`
Time buckets for this page, oldest first: one per `bucket_width` interval, including intervals with no data (their `results` list is empty). A page holds at most `limit` buckets.
- `ending_at: string`
End of the time bucket (exclusive) in RFC 3339 format.
- `results: array of object { cache_creation, cache_read_input_tokens, context_window, 10 more }`
Rows for this time bucket. Empty when the bucket has no data; otherwise a single combined row when `group_by[]` is omitted, or one row per group (subject to the per-bucket group cap described on the `group_by[]` parameter).
- `cache_creation: object { ephemeral_1h_input_tokens, ephemeral_5m_input_tokens }`
The number of input tokens for cache creation.
- `ephemeral_1h_input_tokens: number`
The number of input tokens used to create the 1 hour cache entry.
- `ephemeral_5m_input_tokens: number`
The number of input tokens used to create the 5 minute cache entry.
- `cache_read_input_tokens: number`
The number of input tokens read from the cache.
- `context_window: "0-200k" or "200k-1M" or null`
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.
- `"0-200k"`
- `"200k-1M"`
- `inference_geo: "global" or "us" or null`
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).
- `"global"`
- `"us"`
- `model: string or null`
Model that produced the usage or cost, as a model name in the form the `models[]` filter accepts (for example, `claude-opus-4-6`). 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.
- `output_tokens: number`
The number of output tokens generated.
- `product: string or null`
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", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it. Some unattributed usage is reported as "other".
- `rbac_group_id: string or null`
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 with no group_by.
- `requests: number or null`
Number of API requests in this row's scope. For sandbox / code-execution events, this counts execution spans rather than HTTP requests (these rows surface with `product: null`).
- `server_tool_use: object { web_search_requests }`
Server-side tool usage metrics.
- `web_search_requests: number`
The number of web search requests made.
- `slack_channel_id: string or null`
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: "fast" or "standard" or null`
Inference speed mode of the usage or cost: `fast` or `standard`. Null unless `speed` is in `group_by[]`.
- `"fast"`
- `"standard"`
- `uncached_input_tokens: number`
The number of uncached input tokens processed.
- `starting_at: string`
Start of the time bucket (inclusive) in RFC 3339 format.
- `data_refreshed_at: string or null`
RFC 3339 timestamp of the export this response was served from. Null when no export yet covers any part of the requested range, in which case every bucket's `results` list is empty. Buckets beyond this watermark are incomplete; for stable results, set `ending_at` to this value or earlier. Data is typically refreshed every 4 hours but not final until about 30 days after the usage date (late-arriving events, reconciliation adjustments).
- `has_more: boolean`
Whether another page is available. When true, pass `next_page` as the `page` parameter to fetch it.
- `next_page: string or null`
Opaque cursor for the next page, or null when `has_more` is false. Pass it as the `page` parameter, keeping the other parameters unchanged. A cursor can expire after the underlying data refreshes; the request then returns HTTP 410 and pagination must restart from the first page.
- `organization_id: string`
ID of the Organization.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/usage_report \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"ending_at": "2019-12-27T18:11:19.117Z",
"results": [
{
"cache_creation": {
"ephemeral_1h_input_tokens": 1000,
"ephemeral_5m_input_tokens": 500
},
"cache_read_input_tokens": 0,
"context_window": "0-200k",
"inference_geo": "global",
"model": "claude-opus-4-6",
"output_tokens": 0,
"product": "chat",
"rbac_group_id": "rbac_group_012rppKaSVsmTo6NqRDXQXNF",
"requests": 0,
"server_tool_use": {
"web_search_requests": 10
},
"slack_channel_id": "C0123ABCDEF",
"speed": "fast",
"uncached_input_tokens": 0
}
],
"starting_at": "2019-12-27T18:11:19.117Z"
}
],
"data_refreshed_at": "2019-12-27T18:11:19.117Z",
"has_more": true,
"next_page": "next_page",
"organization_id": "org_013FP9SaFPBg7Kw7fetjn6cF"
}
```
## Get Per-User Token Usage
**get** `/v1/organizations/analytics/user_usage_report`
Get per-user token usage across a date range.
Returns one row per user, ranked by the chosen token metric. Use this to
see which users consume the most tokens. Only usage attributable to a
seat user is included; for organization-wide totals including direct
API-key and automation traffic, use the bucketed
`/v1/organizations/analytics/usage_report` endpoint. Available to
organizations on a Claude Enterprise plan. Requires an API key with the
`read:analytics` scope.
### Query Parameters
- `starting_at: string`
Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.
- `bucket_width: optional "1d" or "1h" or "1m"`
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.
- `"1d"`
- `"1h"`
- `"1m"`
- `context_windows: optional array of "0-200k" or "200k-1M"`
Cut at 300 lines. The page has the rest.
api/admin/analytics/usage/list First recorded · 266 lines, first recorded
## Get Token Usage Over Time ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Token Usage Over Time
url: https://platform.claude.com/docs/en/api/admin/analytics/usage/list
---
## Get Token Usage Over Time
**get** `/v1/organizations/analytics/usage_report`
Get token usage over time across a date range.
Returns token usage bucketed by minute, hour, or day, optionally broken
down by product, model, context window, inference region, or speed.
Available to organizations on a Claude Enterprise plan. Requires an API
key with the `read:analytics` scope.
### Query Parameters
- `starting_at: string`
Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.
- `bucket_width: optional "1d" or "1h" or "1m"`
Time bucket granularity.
- `"1d"`
- `"1h"`
- `"1m"`
- `context_windows: optional array of "0-200k" or "200k-1M"`
Filter to specific context-window pricing tiers. Use `group_by[]=context_window` to break out per-tier values.
- `"0-200k"`
- `"200k-1M"`
- `ending_at: optional string`
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.
- `group_by: optional array of "context_window" or "inference_geo" or "model" or 4 more`
Dimensions to break each time bucket out by. Defaults to no grouping (one total per bucket). Each bucket reports at most its top 100 groups; a group beyond that cap has no row in that bucket (there is no remainder row), so grouped buckets are not exhaustive when a dimension has more than 100 distinct values.
- `"context_window"`
- `"inference_geo"`
- `"model"`
- `"product"`
- `"rbac_group_id"`
- `"slack_channel_id"`
- `"speed"`
- `inference_geos: optional array of "global" or "not_available" or "us"`
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.
- `"global"`
- `"not_available"`
- `"us"`
- `limit: optional number`
Maximum number of time buckets per page. Defaults and caps vary by bucket_width (1d: default 7, max 31; 1h: default 24, max 168; 1m: default 60, max 256).
- `models: optional array of string`
Models to include. Defaults to all models. Use `group_by[]=model` to break out per-model values.
- `page: optional string`
Opaque cursor from a previous response's `next_page` field.
- `products: optional array of string`
Product surfaces to include. Defaults to all products. Use `group_by[]=product` to break out per-product values. Values include "chat", "claude_code", "cowork", "office_agent", "claude_in_chrome", "claude_design", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it.
- `rbac_group_ids: optional array of string`
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.
- `slack_channel_ids: optional array of string`
Filter to usage originating from specific Slack channels. Use `group_by[]=slack_channel_id` to break out per-channel values.
- `speeds: optional array of "fast" or "standard"`
Filter to fast or standard inference mode. Use `group_by[]=speed` to break out per-mode values.
- `"fast"`
- `"standard"`
- `user_ids: optional array of string`
Filter to specific users by tagged user ID.
### Returns
- `UsageBucket object { data, data_refreshed_at, has_more, 2 more }`
- `data: array of object { ending_at, results, starting_at }`
Time buckets for this page, oldest first: one per `bucket_width` interval, including intervals with no data (their `results` list is empty). A page holds at most `limit` buckets.
- `ending_at: string`
End of the time bucket (exclusive) in RFC 3339 format.
- `results: array of object { cache_creation, cache_read_input_tokens, context_window, 10 more }`
Rows for this time bucket. Empty when the bucket has no data; otherwise a single combined row when `group_by[]` is omitted, or one row per group (subject to the per-bucket group cap described on the `group_by[]` parameter).
- `cache_creation: object { ephemeral_1h_input_tokens, ephemeral_5m_input_tokens }`
The number of input tokens for cache creation.
- `ephemeral_1h_input_tokens: number`
The number of input tokens used to create the 1 hour cache entry.
- `ephemeral_5m_input_tokens: number`
The number of input tokens used to create the 5 minute cache entry.
- `cache_read_input_tokens: number`
The number of input tokens read from the cache.
- `context_window: "0-200k" or "200k-1M" or null`
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.
- `"0-200k"`
- `"200k-1M"`
- `inference_geo: "global" or "us" or null`
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).
- `"global"`
- `"us"`
- `model: string or null`
Model that produced the usage or cost, as a model name in the form the `models[]` filter accepts (for example, `claude-opus-4-6`). 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.
- `output_tokens: number`
The number of output tokens generated.
- `product: string or null`
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", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it. Some unattributed usage is reported as "other".
- `rbac_group_id: string or null`
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 with no group_by.
- `requests: number or null`
Number of API requests in this row's scope. For sandbox / code-execution events, this counts execution spans rather than HTTP requests (these rows surface with `product: null`).
- `server_tool_use: object { web_search_requests }`
Server-side tool usage metrics.
- `web_search_requests: number`
The number of web search requests made.
- `slack_channel_id: string or null`
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: "fast" or "standard" or null`
Inference speed mode of the usage or cost: `fast` or `standard`. Null unless `speed` is in `group_by[]`.
- `"fast"`
- `"standard"`
- `uncached_input_tokens: number`
The number of uncached input tokens processed.
- `starting_at: string`
Start of the time bucket (inclusive) in RFC 3339 format.
- `data_refreshed_at: string or null`
RFC 3339 timestamp of the export this response was served from. Null when no export yet covers any part of the requested range, in which case every bucket's `results` list is empty. Buckets beyond this watermark are incomplete; for stable results, set `ending_at` to this value or earlier. Data is typically refreshed every 4 hours but not final until about 30 days after the usage date (late-arriving events, reconciliation adjustments).
- `has_more: boolean`
Whether another page is available. When true, pass `next_page` as the `page` parameter to fetch it.
- `next_page: string or null`
Opaque cursor for the next page, or null when `has_more` is false. Pass it as the `page` parameter, keeping the other parameters unchanged. A cursor can expire after the underlying data refreshes; the request then returns HTTP 410 and pagination must restart from the first page.
- `organization_id: string`
ID of the Organization.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/usage_report \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"ending_at": "2019-12-27T18:11:19.117Z",
"results": [
{
"cache_creation": {
"ephemeral_1h_input_tokens": 1000,
"ephemeral_5m_input_tokens": 500
},
"cache_read_input_tokens": 0,
"context_window": "0-200k",
"inference_geo": "global",
"model": "claude-opus-4-6",
"output_tokens": 0,
"product": "chat",
"rbac_group_id": "rbac_group_012rppKaSVsmTo6NqRDXQXNF",
"requests": 0,
"server_tool_use": {
"web_search_requests": 10
},
"slack_channel_id": "C0123ABCDEF",
"speed": "fast",
"uncached_input_tokens": 0
}
],
"starting_at": "2019-12-27T18:11:19.117Z"
}
],
"data_refreshed_at": "2019-12-27T18:11:19.117Z",
"has_more": true,
"next_page": "next_page",
"organization_id": "org_013FP9SaFPBg7Kw7fetjn6cF"
}
```
api/admin/analytics/usage/list_by_user First recorded · 323 lines, first recorded
## Get Per-User Token Usage ### Query Parameters ### Returns ### Example #### Response
The first capture of this source. The page was already there, and this is what it said.
---
title: Get Per-User Token Usage
url: https://platform.claude.com/docs/en/api/admin/analytics/usage/list_by_user
---
## Get Per-User Token Usage
**get** `/v1/organizations/analytics/user_usage_report`
Get per-user token usage across a date range.
Returns one row per user, ranked by the chosen token metric. Use this to
see which users consume the most tokens. Only usage attributable to a
seat user is included; for organization-wide totals including direct
API-key and automation traffic, use the bucketed
`/v1/organizations/analytics/usage_report` endpoint. Available to
organizations on a Claude Enterprise plan. Requires an API key with the
`read:analytics` scope.
### Query Parameters
- `starting_at: string`
Start of range, inclusive. RFC 3339 tz-aware. Must be within the last 365 days and no earlier than 2026-01-01T00:00:00Z.
- `bucket_width: optional "1d" or "1h" or "1m"`
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.
- `"1d"`
- `"1h"`
- `"1m"`
- `context_windows: optional array of "0-200k" or "200k-1M"`
Filter to specific context-window pricing tiers. Use `group_by[]=context_window` to break out per-tier values.
- `"0-200k"`
- `"200k-1M"`
- `ending_at: optional string`
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.
- `exclude_deleted_users: optional boolean`
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.
- `group_by: optional array of "context_window" or "inference_geo" or "model" or 4 more`
Break each actor's row out by the given dimensions. Accepts the same values as the bucketed `/usage_report` endpoint. `limit` bounds (actor × time bucket × dimension) rows — with dimensions or `bucket_width` present, one actor may span several rows.
- `"context_window"`
- `"inference_geo"`
- `"model"`
- `"product"`
- `"rbac_group_id"`
- `"slack_channel_id"`
- `"speed"`
- `inference_geos: optional array of "global" or "not_available" or "us"`
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.
- `"global"`
- `"not_available"`
- `"us"`
- `limit: optional number`
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.
- `models: optional array of string`
Models to include. Defaults to all models. Use `group_by[]=model` to break out per-model values.
- `order: optional "asc" or "desc"`
Sort direction. Defaults to `desc`.
- `"asc"`
- `"desc"`
- `order_by: optional "output_tokens" or "requests" or "total_tokens" or "uncached_input_tokens"`
Metric to rank actors by. Defaults to `total_tokens`.
- `"output_tokens"`
- `"requests"`
- `"total_tokens"`
- `"uncached_input_tokens"`
- `page: optional string`
Opaque cursor from a previous response's `next_page` field.
- `products: optional array of string`
Product surfaces to include. Defaults to all products. Values include "chat", "claude_code", "cowork", "office_agent", "claude_in_chrome", "claude_design", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it.
- `rbac_group_ids: optional array of string`
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.
- `slack_channel_ids: optional array of string`
Filter to usage originating from specific Slack channels. Use `group_by[]=slack_channel_id` to break out per-channel values.
- `speeds: optional array of "fast" or "standard"`
Filter to fast or standard inference mode. Use `group_by[]=speed` to break out per-mode values.
- `"fast"`
- `"standard"`
- `user_ids: optional array of string`
Filter to specific users by tagged user ID.
### Returns
- `UserUsage object { data, data_refreshed_at, has_more, 2 more }`
- `data: array of object { actor, cache_creation, cache_read_input_tokens, 14 more }`
Rows for this page, ranked by `order_by` in the `order` direction. One row per user, or several per user when `group_by[]` or `bucket_width` breaks that user's usage or cost out across rows. Rows split out by `cost_type` or `token_type` (cost endpoint only) stay adjacent and are ranked as one unit.
- `actor: AnalyticsUserActor`
The user this row's usage or cost is attributed to. Always a `user_actor`.
- `deleted: boolean`
True when the user is no longer a member of the organization or its associated organizations: either their membership was removed (for example, deprovisioned via your identity provider) or the account itself has been deleted. The flag reflects organization membership, not account status. `name` and `email` stay populated for removed members; `name` is `"Deleted User"` and `email` null when the account has been deleted. The `user_id` is still populated for reconciliation.
- `email: string or null`
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 or null`
The user's current name, including for users who are no longer members of the organization or its associated organizations. Null when the user has not set a name. Returns `"Deleted User"` when the account itself has been deleted. Rows for system-minted service accounts render the service name (for example, `"Claude Security"` for usage by Anthropic's security-patching service) or null.
- `type: "user_actor"`
Actor type. Always `"user_actor"`.
- `"user_actor"`
- `user_id: string`
Tagged user ID.
- `cache_creation: object { ephemeral_1h_input_tokens, ephemeral_5m_input_tokens }`
The number of input tokens for cache creation.
- `ephemeral_1h_input_tokens: number`
The number of input tokens used to create the 1 hour cache entry.
- `ephemeral_5m_input_tokens: number`
The number of input tokens used to create the 5 minute cache entry.
- `cache_read_input_tokens: number`
The number of input tokens read from the cache.
- `context_window: "0-200k" or "200k-1M" or null`
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.
- `"0-200k"`
- `"200k-1M"`
- `ending_at: string or null`
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.
- `inference_geo: "global" or "us" or null`
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).
- `"global"`
- `"us"`
- `model: string or null`
Model that produced the usage or cost, as a model name in the form the `models[]` filter accepts (for example, `claude-opus-4-6`). 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.
- `output_tokens: number`
The number of output tokens generated.
- `product: string or null`
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", and "claude-in-slack". "claude-in-slack" (with hyphens) is Claude Tag, the Claude product in Slack. A similarly spelled legacy value (underscores instead of hyphens) identifies the retiring v1 Slack chat bot and appears only for organizations that used it. Some unattributed usage is reported as "other".
- `rbac_group_id: string or null`
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 with no group_by.
- `requests: number or null`
Number of API requests in this row's scope. For sandbox / code-execution events, this counts execution spans rather than HTTP requests (these rows surface with `product: null`).
- `server_tool_use: object { web_search_requests }`
Server-side tool usage metrics.
- `web_search_requests: number`
The number of web search requests made.
- `slack_channel_id: string or null`
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: "fast" or "standard" or null`
Inference speed mode of the usage or cost: `fast` or `standard`. Null unless `speed` is in `group_by[]`.
- `"fast"`
- `"standard"`
- `starting_at: string or null`
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.
- `total_tokens: number`
Total token count across all token types. This is the value the default order_by='total_tokens' sorts on.
- `uncached_input_tokens: number`
The number of uncached input tokens processed.
- `data_refreshed_at: string or null`
RFC 3339 timestamp of the export this response was served from. Null when no export yet covers any part of the requested range, in which case `data` is empty. Data beyond this watermark is incomplete; for stable results, set `ending_at` to this value or earlier. Data is typically refreshed every 4 hours but not final until about 30 days after the usage date (late-arriving events, reconciliation adjustments).
- `has_more: boolean`
Whether another page is available. When true, pass `next_page` as the `page` parameter to fetch it.
- `next_page: string or null`
Opaque cursor for the next page, or null when `has_more` is false. Pass it as the `page` parameter, keeping the other parameters unchanged. A cursor can expire after the underlying data refreshes; the request then returns HTTP 410 and pagination must restart from the first page.
- `organization_id: string`
ID of the Organization.
### Example
```http
curl https://api.anthropic.com/v1/organizations/analytics/user_usage_report \
-H 'anthropic-version: 2023-06-01' \
-H "Authorization: Bearer $ANTHROPIC_OAUTH_TOKEN"
```
#### Response
```json
{
"data": [
{
"actor": {
"deleted": true,
"email": "[email protected]",
"name": "Jane Smith",
"type": "user_actor",
"user_id": "user_01AbCdEfGhIjKlMnOpQrSt"
},
"cache_creation": {
"ephemeral_1h_input_tokens": 1000,
"ephemeral_5m_input_tokens": 500
},
"cache_read_input_tokens": 3200000,
"context_window": "0-200k",
Cut at 300 lines. The page has the rest.