Follow Discord
Sweep 06 Nov 2026 · 01:32Z Build v2.1.319 537 read Stable v2.1.311 Latest v2.1.319 Next v2.1.319 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One capture · api

One read of Claude Developer Platformapi-20261106T180710Z

16 pages moved out of 886 read.

Pages moved 16 significant first
Pages read 886 in this capture
Captured 18:07 UTC
Corpus hash 10d3e5a55aa8 corpus-hash

What this read moved

1-16 of 16

build-with-claude/preserved-thinking Changed · +3 / -3 lines

from line 1218
12181218}
12191219```
12201220 
1221Sometimes you can’t declare a tool up front because you don’t know its schema yet: a tool your application discovers at runtime, or an MCP server that connects after the first turn. Define it inside the `tool_addition` block instead of touching `tools`. With `inline-tools-2026-09-15`, the block’s `tool` can be `{"type": "tool_definition", "definition": {...}}`, carrying the same entry you would have put in `tools`:
1221Sometimes you can’t declare a tool up front because you don’t know its schema yet: a tool your application discovers at runtime, or an MCP server that connects after the first turn. [Define it inside the `tool_addition` block](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta) instead of touching `tools`. With `inline-tools-2026-09-15`, the block’s `tool` can be `{"type": "tool_definition", "definition": {...}}`, carrying the same entry you would have put in `tools`:
12221222 
12231223```json
12241224{
from line 1245
12451245 
12461246The new tool arrives in `messages`, `tools` never changes, and earlier thinking stays valid. Keep at least one tool without `defer_loading: true` in `tools`: if every tool there is deferred, the first tool you define this way costs one full prompt cache miss.
12471247 
1248If the API connects to the MCP server for you through the [MCP connector](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector), also send `mcp-client-2026-09-15`. It covers everything `mcp-client-2025-11-20` does, so send it instead of that one. The block’s `definition` can then be an `mcp_toolset` for a server listed in `mcp_servers`. When the API has to fetch a server’s tool list, the response starts with an `mcp_tool_listing` block for that server. Send it back unchanged with the rest of the assistant turn, and keep sending `mcp-client-2026-09-15` on every later request that carries it. The block pins the toolset to that list, so the API doesn’t contact the server again for it. These MCP connector features are available on the Claude API.
1248If the API connects to the MCP server for you through the [MCP connector](https://platform.claude.com/docs/en/agents-and-tools/mcp-connector), also send `mcp-client-2026-09-15`. It covers everything `mcp-client-2025-11-20` does, so send it instead of that one. The block’s `definition` can then be an [`mcp_toolset` for a server listed in `mcp_servers`](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta). When the API has to fetch a server’s tool list, the response starts with an `mcp_tool_listing` block for that server. Send it back unchanged with the rest of the assistant turn, and keep sending `mcp-client-2026-09-15` on every later request that carries it. The block pins the toolset to that list, so the API doesn’t contact the server again for it. These MCP connector features are available on the Claude API.
12491249 
12501250With only the `mid-conversation-tool-changes-2026-07-01` header, you can append a tool you learn about mid-session to `tools` with `defer_loading: true`, then offer it with a `tool_addition` block. That’s safe because the prefix check ignores a deferred tool until a `tool_addition` block references it. Adding a tool without `defer_loading: true` changes the prefix and invalidates earlier thinking.
12511251 
from line 1558
15581558 </Accordion>
15591559 
15601560 <Accordion title="My tool list changes mid-session. How do I avoid invalidating the conversation?">
1561 Don’t edit `tools`. Declare the full set at session start, mark tools that aren’t available yet with `defer_loading: true`, and offer or withdraw them with `tool_addition` and `tool_removal` blocks. If you learn a tool’s schema only mid-session, define it inside the `tool_addition` block (`inline-tools-2026-09-15`, plus `mcp-client-2026-09-15` for a server the API’s MCP connector reaches) and leave `tools` unchanged. The `role: "system"` messages that carry these blocks join the prefix for later thinking, so don’t move, reword, or delete them afterward. See [Add or remove tools with `tool_addition` and `tool_removal`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#tool-changes).
1561 Don’t edit `tools`. Declare the full set at session start, mark tools that aren’t available yet with `defer_loading: true`, and offer or withdraw them with `tool_addition` and `tool_removal` blocks. If you learn a tool’s schema only mid-session, [define it inside the `tool_addition` block](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#define-tools-in-a-message-beta) (`inline-tools-2026-09-15`, plus `mcp-client-2026-09-15` for a [server the API’s MCP connector reaches](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages#add-an-mcp-server-mid-conversation-beta)) and leave `tools` unchanged. The `role: "system"` messages that carry these blocks join the prefix for later thinking, so don’t move, reword, or delete them afterward. See [Add or remove tools with `tool_addition` and `tool_removal`](https://platform.claude.com/docs/en/build-with-claude/preserved-thinking#tool-changes).
15621562 </Accordion>
15631563 
15641564 <Accordion title="I compact by summarizing older turns and keeping recent turns verbatim. Does that still work?">

cli-sdks-libraries/overview Changed · +3 / -3 lines

from line 7
77Anthropic provides three kinds of official tooling for building with the Claude API:
88 
99* **CLI:** The `ant` command-line tool for shell scripting and interactive use.
10* **Client SDKs:** General-purpose Messages API clients for Python, TypeScript, C#, Go, Java, PHP, and Ruby. They also cover most of the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api). Each SDK provides idiomatic interfaces, type safety, and built-in support for streaming, retries, error handling, and [OpenTelemetry tracing](https://platform.claude.com/docs/en/manage-claude/opentelemetry/sdk).
10* **Client SDKs:** General-purpose Messages API clients for Python, TypeScript, C#, Go, Java, PHP, and Ruby. They also cover [Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) and most of the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api). Each SDK provides idiomatic interfaces, type safety, and built-in support for streaming, retries, error handling, and [OpenTelemetry tracing](https://platform.claude.com/docs/en/manage-claude/opentelemetry/sdk).
1111* **Libraries and integrations:** Packages and compatibility layers that expose Claude inside another framework’s API surface rather than the Messages API directly.
1212 
1313<Info>
from line 54
5454 </Card>
5555</CardGroup>
5656 
57Each major version of a client SDK sends one [API version](https://platform.claude.com/docs/en/api/versioning) by default, and a new major version comes with each new API version. To move to `2026-10-21`, see [Switch to 2026-10-21](https://platform.claude.com/docs/en/api/migration-2026-10-21#upgrade).
57Each major version of a client SDK sends one [API version](https://platform.claude.com/docs/en/api/versioning) by default. To move to a new API version, upgrade to a new major version. For `2026-10-21`, see [Switch to 2026-10-21](https://platform.claude.com/docs/en/api/migration-2026-10-21#upgrade).
5858 
5959## Latest versions
6060 
from line 87
8787 
8888## Building agents or using Claude Code?
8989 
90The CLI, client SDKs, and libraries are for calling the Claude API yourself: you send each request and handle each response. Claude Code, the Claude Agent SDK, and Claude Managed Agents work at a higher level, providing the agent loop, tool execution, and runtime.
90The CLI, client SDKs, and libraries are for calling the Claude API yourself. You send each request and handle each response. Claude Code, the Claude Agent SDK, and Claude Managed Agents work at a higher level, providing the agent loop, tool execution, and runtime.
9191 
9292<CardGroup cols={3}>
9393 <Card title="Claude Code" href="https://code.claude.com/docs/en/overview">

manage-claude/compliance-org-data Changed · +5 / -5 lines

from line 11
1111<Check>
1212 **Required scope:** `read:compliance_org_data` on the Compliance Access Key. The user, user-preference, and group-member endpoints require `read:compliance_user_data` instead.
1313 
14 Compliance Access Keys (`sk-ant-api01-...`) created in claude.ai are the only key type accepted; see [Set up the Compliance API](https://platform.claude.com/docs/en/manage-claude/compliance-api-access) to provision one. Calls authenticated with an Admin API key (`sk-ant-admin01-...`) return [403 Forbidden](https://platform.claude.com/docs/en/manage-claude/compliance-errors#403-forbidden).
14 Compliance Access Keys (`sk-ant-api01-...`) created in claude.ai are the only key type accepted. See [Set up the Compliance API](https://platform.claude.com/docs/en/manage-claude/compliance-api-access) to provision one. Calls authenticated with an Admin API key (`sk-ant-admin01-...`) return [403 Forbidden](https://platform.claude.com/docs/en/manage-claude/compliance-errors#403-forbidden).
1515</Check>
1616 
1717The endpoints on this page expose the directory side of a Claude Enterprise organization: its linked organizations, the users in each one, the roles defined on each, and its role-based access control (RBAC) or SCIM (System for Cross-domain Identity Management)-provisioned groups and their members. Use them to seed eDiscovery user lists, build reporting dashboards, and reconcile group membership against an external system of record. A Compliance Access Key that covers the parent organization returns data from every linked organization underneath, so a single key reaches the entire tree. The [effective-settings endpoint](https://platform.claude.com/docs/en/manage-claude/compliance-org-data#get-effective-organization-settings) complements the directory: it returns the data-privacy, security, and capability settings actually in force for one organization.
from line 308
308308 
309309## Read plugins and plugin marketplaces
310310 
311Your organization’s plugins and plugin marketplaces are part of the [Admin API](https://platform.claude.com/docs/en/manage-claude/plugins-api) rather than the Compliance API, but a Compliance Access Key with `read:compliance_org_data` can call the Plugins API’s read endpoints directly:
311Your organization’s plugins and plugin marketplaces are part of the Admin API’s [Plugins API](https://platform.claude.com/docs/en/manage-claude/plugins-api) rather than the Compliance API, but a Compliance Access Key with `read:compliance_org_data` can call the Plugins API’s read endpoints directly:
312312 
313313* List plugins and retrieve a plugin
314314* List a plugin’s versions, retrieve a version, and download a version’s files
from line 315
315315* List a plugin’s installation settings and its shares
316316* List plugin marketplaces and retrieve a marketplace
317317 
318Send the `anthropic-beta: ce-plugins-2026-09-01` header on every request; without it these endpoints return [404 Not Found](https://platform.claude.com/docs/en/manage-claude/plugins-api#error-responses). Each call reads one organization: a key that covers the parent organization reads the linked organization it was created in unless you pass the `organization_id` query parameter (a linked organization’s UUID or its `org_`-prefixed ID) to [read a different one](https://platform.claude.com/docs/en/manage-claude/plugins-api#reading-another-organization-under-the-same-parent), and a key restricted to one organization reads only that organization. These calls count against the Admin API’s [rate limits](https://platform.claude.com/docs/en/manage-claude/plugins-api#rate-limiting), not the Compliance API’s.
318Send the `anthropic-beta: ce-plugins-2026-09-01` header on every request; without it these endpoints return 404 Not Found (see the Plugins API’s [Error responses](https://platform.claude.com/docs/en/manage-claude/plugins-api#error-responses)). Each call reads one organization. A key that covers the parent organization reads the linked organization it was created in. To [read a different organization](https://platform.claude.com/docs/en/manage-claude/plugins-api#reading-another-organization-under-the-same-parent), pass the `organization_id` query parameter (a linked organization’s UUID or its `org_`-prefixed ID). A key restricted to one organization reads only that organization. These calls count against the Admin API’s [rate limits](https://platform.claude.com/docs/en/manage-claude/plugins-api#rate-limiting), not the Compliance API’s.
319319 
320Creating or changing plugins, their installation settings, or a marketplace’s settings requires an Admin API key with `write:plugins`. Of the read calls, only downloading the files of a plugin in a member’s personal marketplace records an [Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed) event (`claude_plugin_archive_accessed`). See the [Plugins API guide](https://platform.claude.com/docs/en/manage-claude/plugins-api) for each endpoint, request examples, and the [events the API records](https://platform.claude.com/docs/en/manage-claude/plugins-api#activity-feed-events).
320Creating or changing plugins, their installation settings, or a marketplace’s settings requires an Admin API key with `write:plugins`. Of the read calls, only downloading the files of a plugin in a member’s personal marketplace records an [Activity Feed](https://platform.claude.com/docs/en/manage-claude/compliance-activity-feed) event (`claude_plugin_archive_accessed`). See the [Plugins API](https://platform.claude.com/docs/en/manage-claude/plugins-api) guide for each endpoint, request examples, and the [events the API records](https://platform.claude.com/docs/en/manage-claude/plugins-api#activity-feed-events).
321321 
322322## Next steps
323323 

manage-claude/user-management Changed · +4 / -4 lines

from line 34
3434<Check>
3535 **Scoped Admin API key required**
3636 
37 These endpoints require an Admin API key with the `read:members` scope (member and invite `GET` endpoints, and all custom-role endpoints; there is no separate role scope), the `write:members` scope (member and invite `POST` and `DELETE` endpoints), the `read:rbac_groups` scope (group `GET` endpoints), or the `write:rbac_groups` scope (group `POST` and `DELETE` endpoints). Assigning the `managed` role, or groups on an invite, requires `write:rbac_groups` in addition to `write:members`. A key carrying the `read:org_audit` scope (a read-only scope for security-audit integrations) can also call every `GET` endpoint on this page and the [Compliance API](https://platform.claude.com/docs/en/manage-claude/compliance-api) read endpoints. See [Create an Admin API key](https://platform.claude.com/docs/en/manage-claude/admin-api-keys#create-a-key-for-a-claude-enterprise-organization) for where your primary owner creates one and which scopes to select. Pass the key in the `x-api-key` header on every request, together with the [`anthropic-version`](https://platform.claude.com/docs/en/api/versioning) header.
37 These endpoints require an Admin API key with the scope that matches the request. Member and invite `GET` endpoints, and all custom-role endpoints, need `read:members` (there is no separate role scope). Member and invite `POST` and `DELETE` endpoints need `write:members`. Group `GET` endpoints need `read:rbac_groups`, and group `POST` and `DELETE` endpoints need `write:rbac_groups`. Assigning the `managed` role, or groups on an invite, requires `write:rbac_groups` in addition to `write:members`. A key carrying the `read:org_audit` scope (a read-only scope for security-audit integrations) can also call every `GET` endpoint on this page and the [Compliance API](https://platform.claude.com/docs/en/manage-claude/compliance-api) read endpoints. See [Create an Admin API key](https://platform.claude.com/docs/en/manage-claude/admin-api-keys#create-a-key-for-a-claude-enterprise-organization) for where to create one and which scopes to select. Pass the key in the `x-api-key` header on every request, together with the [`anthropic-version`](https://platform.claude.com/docs/en/api/versioning) header.
3838</Check>
3939 
4040## Overview
from line 194
194194 
195195### Groups and roles
196196 
197Groups connect members to custom roles (role-based access control, the `rbac` in the endpoint paths and scope names). Groups are owned by your enterprise as a whole (the parent organization together with every organization under it), not by a single organization. So the group scopes (`read:rbac_groups` and `write:rbac_groups`) require a key created for all linked organizations. Each group carries a `source_type`: `direct` for groups created in claude.ai, `scim` for groups provisioned by your identity provider. A group’s `role_ids` field lists the IDs of the custom roles attached to it. Resolve them to names and permissions with the [custom role endpoints](https://platform.claude.com/docs/en/manage-claude/user-management#custom-roles). The role catalog is per-organization, but groups are enterprise-wide. So fetching a role that belongs to a different organization of your enterprise returns 404 for your key. The `role_ids` field is `null` (rather than `[]`) when role data was temporarily unavailable, so retry to distinguish a degraded read from a group with no roles.
197Groups connect members to custom roles (role-based access control, the `rbac` in the endpoint paths and scope names). Groups belong to your parent organization and every organization under it, not to a single organization. So the group scopes (`read:rbac_groups` and `write:rbac_groups`) require a key created for all linked organizations. Each group carries a `source_type`: `direct` for groups created in claude.ai, `scim` for groups provisioned by your identity provider. A group’s `role_ids` field lists the IDs of the custom roles attached to it. Resolve them to names and permissions with the [custom role endpoints](https://platform.claude.com/docs/en/manage-claude/user-management#custom-roles). Each organization has its own role catalog, but groups are shared across your parent organization. So fetching a role that belongs to a different organization under your parent organization returns 404 for your key. The `role_ids` field is `null` (rather than `[]`) when role data was temporarily unavailable, so retry to distinguish a degraded read from a group with no roles.
198198 
199199## Versioning
200200 
from line 2160
21602160 
21612161## Custom roles
21622162 
2163Custom roles are read-only through the API: these endpoints catalog your organization’s custom roles (defined in [claude.ai organization settings](https://claude.ai/admin-settings) or provisioned by Anthropic) and the permissions each role grants. Custom-role reads use the `read:members` scope (there is no separate role scope) and work with an organization-level key: unlike the group endpoints, they do not require a key created for all linked organizations, and the catalog returned is your organization’s own.
2163Custom roles are read-only through the API: these endpoints catalog your organization’s custom roles (defined in [claude.ai organization settings](https://claude.ai/admin-settings) or provisioned by Anthropic) and the permissions each role grants. Custom-role reads use the `read:members` scope (there is no separate role scope) and work with an organization-level key, and the catalog returned is your organization’s own.
21642164 
21652165Read a role’s name from its `display_name` field. For a role provisioned by Anthropic, `display_name` can differ from the label claude.ai shows, and Anthropic might change the name. To keep a lasting reference to a role, store its `id`.
21662166 
from line 2685
26852685 
26862686<CardGroup cols={2}>
26872687 <Card title="Create an Admin API key" href="https://platform.claude.com/docs/en/manage-claude/admin-api-keys">
2688 Where your primary owner creates a scoped key and which scopes to select.
2688 Where to create a scoped key and which scopes to select.
26892689 </Card>
26902690 
26912691 <Card title="Compliance API" href="https://platform.claude.com/docs/en/manage-claude/compliance-api">

manage-claude/wif-admin-api Changed · +23 / -21 lines

from line 4
44description: Create and manage Workload Identity Federation service accounts, issuers, and rules programmatically for infrastructure-as-code and CI workflows.
55---
66 
7The Admin API lets you create and manage [Workload Identity Federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation) resources programmatically: service accounts, federation issuers, and federation rules. Use it to keep your federation configuration in infrastructure as code, provision it from CI, and reproduce it across organizations instead of clicking through the Claude Console. These endpoints share the `/v1/organizations` path prefix with the rest of the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api).
7The Admin API lets you create and manage [Workload Identity Federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation) (WIF) resources programmatically: service accounts, federation issuers, and federation rules. Use it to keep your federation configuration in infrastructure as code, provision it from CI, and reproduce it across organizations instead of clicking through the Claude Console. These endpoints share the `/v1/organizations` path prefix with the rest of the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api).
88 
99## Prerequisites
1010 
11Every request on this page authenticates with an OAuth bearer token that carries the `org:admin` scope. The scope is granted only to organization members with the admin, owner, or primary owner role, and it grants access to the whole organization: any workspace binding is ignored. There are two ways to obtain a token, and they carry different permissions. A token from your own login acts as a user. A federated token acts as a service account and cannot perform every operation on this page.
11Every request on this page authenticates with an OAuth bearer token that carries the `org:admin` scope. Anthropic grants the scope only to organization members with the admin, owner, or primary owner role. The scope grants access to the whole organization, and these endpoints ignore any workspace binding. There are two ways to obtain a token, and they carry different permissions. A token from your own login acts as a user. A federated token acts as a service account and cannot perform every operation on this page.
1212 
1313### Interactive (your terminal)
1414 
15Log in with the [`ant` CLI](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/quickstart) under a dedicated profile, requesting the `org:admin` scope (see [Admin access](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/authentication#admin-access)), then export the bearer token. Logging in with `--profile admin` stores the `org:admin` credential under its own profile name and also makes it the CLI’s active profile. The exported variable applies to every SDK and CLI call in that shell. For these reasons, use a shell you reserve for administration, unset the variable when you are done, and switch the CLI back with `ant profile activate default`:
15In a shell you reserve for administration, log in with the [`ant` CLI](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/quickstart) under a dedicated profile, requesting the `org:admin` scope (see [Admin access](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/authentication#admin-access)), then export the bearer token:
1616 
1717```bash CLI
1818ant auth login --profile admin --scope "org:admin"
from line 19
1919export ANTHROPIC_AUTH_TOKEN=$(ant auth print-credentials --profile admin --access-token)
2020```
2121 
22Logging in with `--profile admin` stores the `org:admin` credential under its own profile name and also makes it the CLI’s active profile. The exported variable applies to every SDK and CLI call in that shell. When you are done, unset the variable and switch the CLI back with `ant profile activate default`.
23 
2224Interactive tokens are short-lived. If requests start returning 401, rerun the `export` command to refresh the token.
2325 
24The SDK and the `ant` CLI read `ANTHROPIC_AUTH_TOKEN` automatically; leave `ANTHROPIC_API_KEY` unset in the same shell, because these endpoints reject API keys and every client uses the key when both are set.
26The SDK and the `ant` CLI read `ANTHROPIC_AUTH_TOKEN` automatically. Leave `ANTHROPIC_API_KEY` unset in the same shell. When both are set, the SDK and the CLI use the key, and these endpoints reject API keys.
2527 
2628### Workload (CI and automation)
2729 
28Create a federation rule with `oauth_scope: org:admin` that targets a service account whose `organization_role` is `admin`. You must create the rule itself in the Claude Console: granting a workload organization-admin access is a deliberate human action, not something automation can bootstrap for itself. The next section walks through this once-per-organization setup.
30Create a federation rule with `oauth_scope: org:admin` that targets a service account whose `organization_role` is `admin`. You must create the rule itself in the Claude Console. Granting a workload organization-admin access is a deliberate human action, not something automation can bootstrap for itself. The next section walks through this setup, which you do once for each organization.
2931 
3032## Bootstrap a workload to manage WIF
3133 
32One Console-created rule is enough to put the rest of your federation configuration under infrastructure as code: grant a single trusted workload the `org:admin` scope, and let that workload manage federation issuers and every workspace-scoped federation rule through this API.
34One Console-created rule is enough to put the rest of your federation configuration under infrastructure as code. Grant a single trusted workload the `org:admin` scope, and let that workload manage federation issuers and every workspace-scoped federation rule through this API.
3335 
3436<Steps>
3537 <Step title="Create the org:admin rule in the Console">
36 In the Claude Console, go to the [Workload identity](https://platform.claude.com/settings/workload-identity-federation) page (`platform.claude.com/settings/workload-identity-federation`) and select **Connect workload** to create one federation rule for your automation workload, for example a GitHub Actions workflow in your infrastructure repository. Under **Advanced rule options**, set the rule’s OAuth scope to `org:admin`: the wizard then creates the new service account with the Admin organization role (or asks you to pick an existing admin service account as the target).
38 In the Claude Console, go to the [Workload identity](https://platform.claude.com/settings/workload-identity-federation) page (`platform.claude.com/settings/workload-identity-federation`) and select **Connect workload**. Create one federation rule for your automation workload, for example a GitHub Actions workflow in your infrastructure repository. Under **Advanced rule options**, set the rule’s OAuth scope to `org:admin`. The wizard then creates the new service account with the Admin organization role, or asks you to pick an existing admin service account as the target.
3739 
3840 <Warning>
39 Match the rule to one exact workload identity, not a broad pattern. `subject_prefix` is an exact match unless it ends in `*`. For GitHub Actions, pin the subject to a protected branch, such as `repo:my-org/my-repo:ref:refs/heads/main`. A trailing wildcard such as `repo:my-org/my-repo:*` also matches `pull_request` runs, including runs triggered from forks, so anyone who could open a pull request against the repository could mint an `org:admin` token. See [Restrict which workflows can authenticate](https://platform.claude.com/docs/en/manage-claude/wif-providers/github-actions#restrict-which-workflows-can-authenticate).
41 Match the rule to one exact workload identity, not a broad pattern. `subject_prefix` is an exact match unless it ends in `*`. For GitHub Actions, pin the subject to a protected branch, such as `repo:my-org/my-repo:ref:refs/heads/main`. A trailing wildcard such as `repo:my-org/my-repo:*` also matches `pull_request` runs, including runs triggered from forks. With that pattern, anyone who can open a pull request against the repository can mint an `org:admin` token. See [Restrict which workflows can authenticate](https://platform.claude.com/docs/en/manage-claude/wif-providers/github-actions#restrict-which-workflows-can-authenticate).
4042 </Warning>
4143 </Step>
4244 
from line 57
5557 
5658 The SDK also accepts these settings as explicit constructor arguments, shown in [Construct the SDK client](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#construct-the-sdk-client). The `ant` CLI reads these variables too, or takes `--federation-rule`, `--organization-id`, `--service-account-id`, and `--identity-token-file` flags. See [Environment variables](https://platform.claude.com/docs/en/manage-claude/wif-reference#environment-variables) and [Credential precedence](https://platform.claude.com/docs/en/manage-claude/wif-reference#credential-precedence) for the full list of variables and their order.
5759 
58 For a workload that runs more than one `ant` command, use a [federation profile](https://platform.claude.com/docs/en/manage-claude/wif-reference#profile-configuration-file) rather than flags or environment variables. A profile caches the access token between commands. With flags or variables, every command exchanges the identity token again. By default, identity tokens that carry a `jti` claim, as GitHub Actions tokens do, are accepted only once, so a second command would be rejected.
60 For a workload that runs more than one `ant` command, use a [federation profile](https://platform.claude.com/docs/en/manage-claude/wif-reference#profile-configuration-file) rather than flags or environment variables. A profile caches the access token between commands. With flags or variables, every command exchanges the identity token again. By default, Anthropic accepts an identity token with a `jti` claim only once, and GitHub Actions tokens carry that claim. Anthropic rejects a second command that presents the same token.
5961 
6062 When the rule is enabled for all workspaces or more than one, give the `ant` CLI a federation profile that sets `workspace_id`, and set `ANTHROPIC_PROFILE` to its name. Unlike the SDK, the CLI passes `ANTHROPIC_WORKSPACE_ID` into the exchange only through a federation profile, and `--workspace-id` never reaches the exchange.
6163 
62 A workload that calls the API with curl exchanges the JWT for a short-lived `org:admin` bearer token itself, using the same [token exchange](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#authenticate-from-your-workload) as any other federated workload, and sends it in the `authorization: Bearer` header.
64 A workload that calls the API with curl exchanges the JWT for a short-lived `org:admin` bearer token itself. It uses the same [token exchange](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#authenticate-from-your-workload) as any other federated workload, and sends the token in the `authorization: Bearer` header.
6365 </Step>
6466 
6567 <Step title="Manage issuers and workspace-scoped rules through the API">
from line 69
6769 </Step>
6870</Steps>
6971 
70For the operations a federated token can and cannot perform, see [Permissions and constraints](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#permissions-and-constraints). If you already created issuers, service accounts, or rules with the **Connect workload** wizard, list them with the following endpoints and import them into your infrastructure-as-code state instead of recreating them.
72For the operations a federated token can and cannot perform, see [Permissions and constraints](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#permissions-and-constraints). If you already created issuers, service accounts, or rules with the **Connect workload** wizard, list them with the following endpoints. Then import them into your infrastructure-as-code state instead of recreating them.
7173 
7274## Authentication
7375 
74All endpoints live under `https://api.anthropic.com/v1/organizations/`. Every request to the federation and service-account endpoints needs the API version header and the bearer token:
76All endpoints live under `https://api.anthropic.com/v1/organizations/`. Every request to the federation and service-account endpoints needs the API version header and the bearer token.
7577 
7678In the SDK, these endpoints are `client.organization.service_accounts` (typescript: `client.organization.serviceAccounts`; csharp, go: `client.Organization.ServiceAccounts`; java: `client.organization().serviceAccounts()`; php: `$client->organization->serviceAccounts`), `client.organization.federation.issuers` (csharp, go: `client.Organization.Federation.Issuers`; java: `client.organization().federation().issuers()`; php: `$client->organization->federation->issuers`), and `client.organization.federation.rules` (csharp, go: `client.Organization.Federation.Rules`; java: `client.organization().federation().rules()`; php: `$client->organization->federation->rules`) (`ant organization:service-accounts`, `ant organization:federation:issuers`, and `ant organization:federation:rules` in the CLI). The SDK and the `ant` CLI send the bearer token from `ANTHROPIC_AUTH_TOKEN`. In an automated workload, they perform the federation exchange themselves, as described in [Bootstrap a workload to manage WIF](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#bootstrap-a-workload-to-manage-wif).
7779 
from line 161
159161 ```
160162</CodeGroup>
161163 
162Admin API keys are not accepted on these endpoints; the Admin API page’s `x-api-key` examples do not apply here.
164These endpoints do not accept Admin API keys, so the `x-api-key` examples on the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api) page do not apply here.
163165 
164166## Service accounts
165167 
from line 488
486488}
487489```
488490 
489To read or update a single service account, use `GET` and `POST` on `/v1/organizations/service_accounts/{service_account_id}`. A service account must be a member of a workspace before federated tokens can act in it. Every service account has an implicit membership in your organization’s default workspace; add explicit memberships for other workspaces with `GET`, `POST`, and `DELETE` on `/v1/organizations/service_accounts/{service_account_id}/workspaces`, where `DELETE` targets `.../workspaces/{workspace_id}`.
491To read or update a single service account, use `GET` and `POST` on `/v1/organizations/service_accounts/{service_account_id}`. A service account must be a member of a workspace before federated tokens can act in it. Every service account has an implicit membership in your organization’s default workspace. Manage explicit memberships in other workspaces with `GET`, `POST`, and `DELETE` on `/v1/organizations/service_accounts/{service_account_id}/workspaces`, where `DELETE` targets `.../workspaces/{workspace_id}`.
490492 
491493For complete parameter details and response schemas, see the [Service accounts API reference](https://platform.claude.com/docs/en/api/organization/service_accounts).
492494 
from line 826
824826 ```
825827</CodeGroup>
826828 
827To read or update a single issuer, use `GET` and `POST` on `/v1/organizations/federation_issuers/{issuer_id}`. An OAuth caller cannot update an issuer that backs a rule whose `oauth_scope` is anything other than `workspace:developer` or `workspace:inference`; see [Permissions and constraints](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#permissions-and-constraints).
829To read or update a single issuer, use `GET` and `POST` on `/v1/organizations/federation_issuers/{issuer_id}`. An OAuth caller cannot update an issuer that backs a rule whose `oauth_scope` is anything other than `workspace:developer` or `workspace:inference`. See [Permissions and constraints](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#permissions-and-constraints).
828830 
829831For complete parameter details and response schemas, see the [Federation issuers API reference](https://platform.claude.com/docs/en/api/organization/federation/issuers).
830832 
831833## Federation rules
832834 
833A [federation rule](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#federation-rules) (`fdrl_...`) binds an issuer to a service account: JWTs from the issuer that satisfy the rule’s match conditions can mint tokens that act as the rule’s target. The `workspace_id` in the create request enables the rule in that workspace at creation; add more workspaces later through the `/federation_rules/{rule_id}/workspaces` sub-resource. Either `workspace_id` or `applies_to_all_workspaces: true` is required on create.
835A [federation rule](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#federation-rules) (`fdrl_...`) binds an issuer to a service account. JWTs from the issuer that satisfy the rule’s match conditions can mint tokens that act as the rule’s target. The `workspace_id` in the create request enables the rule in that workspace at creation. Add more workspaces later through the `/federation_rules/{rule_id}/workspaces` subresource. Create requests require either `workspace_id` or `applies_to_all_workspaces: true`.
834836 
835837Create a rule. This example lets GitHub Actions deploys from the main branch act as the service account:
836838 
from line 1264
12621264<Note>
12631265 * OAuth-authenticated callers can only create or modify rules whose `oauth_scope` is `workspace:developer` or `workspace:inference`. To create or modify a rule with any other scope (such as `org:admin` or `workspace:manage_tunnels`), use the Console.
12641266 * An OAuth caller cannot update a federation issuer that backs a rule whose `oauth_scope` is anything other than `workspace:developer` or `workspace:inference` (such as `org:admin` or `workspace:manage_tunnels`). Consider registering a dedicated issuer for the bootstrap rule so the issuers behind workspace-scoped rules stay updatable through the API.
1265 * Admin API keys are not accepted on these endpoints, for reads or writes; use an `org:admin` OAuth token.
1267 * These endpoints do not accept Admin API keys, for reads or writes. Use an `org:admin` OAuth token.
12661268 * A federated token cannot set `organization_role` to `admin` on a new or existing service account, even one that is already `admin`. To set that role, use an [interactive token](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#interactive-your-terminal) or the Console.
12671269</Note>
12681270 
1269A rule with `oauth_scope: org:admin` must target a service account whose `organization_role` is `admin`. Resource names must match `^[a-z0-9-]+$`, be 1 to 255 characters, and be unique within an organization for each resource type; for the full field-level constraints, see [Validation rules](https://platform.claude.com/docs/en/manage-claude/wif-reference#validation-rules).
1271A rule with `oauth_scope: org:admin` must target a service account whose `organization_role` is `admin`. Resource names must match `^[a-z0-9-]+$`, be 1 to 255 characters, and be unique within an organization for each resource type. For the full field-level constraints, see [Validation rules](https://platform.claude.com/docs/en/manage-claude/wif-reference#validation-rules).
12701272 
12711273## Pagination and archiving
12721274 
1273The service-account, federation-issuer, and federation-rule list endpoints accept `limit` (the page size, 1 to 100, default 20) and a `page` cursor taken from the previous response. Pass the response’s `next_page` value as the `page` query parameter on the next request. The SDK fetches further pages on demand when you iterate with `for` (typescript: `for await`; csharp: `Paginate()`; go: `ListAutoPaging()`; java: `autoPager()`; php: `pagingEachItem()`; ruby: `auto_paging_each`), and the `ant` CLI does so by default. The rule-workspaces sub-resource list returns the full set without pagination. Archived resources are hidden from lists by default; pass `include_archived=true` to include them.
1275The service-account, federation-issuer, and federation-rule list endpoints accept `limit` (the page size, 1 to 100, default 20) and a `page` cursor taken from the previous response. Pass the response’s `next_page` value as the `page` query parameter on the next request. The SDK fetches further pages on demand when you iterate with `for` (typescript: `for await`; csharp: `Paginate()`; go: `ListAutoPaging()`; java: `autoPager()`; php: `pagingEachItem()`; ruby: `auto_paging_each`), and the `ant` CLI does so by default. The rule-workspaces subresource list returns the full set without pagination. Lists hide archived resources by default. Pass `include_archived=true` to include them.
12741276 
1275Archiving is a soft delete and is idempotent: archiving an already-archived resource succeeds. Archiving an issuer or a service account returns `400` while a live federation rule still references it; archive the rule first.
1277Archiving is a soft delete. It is idempotent, so archiving an already-archived resource succeeds. Archiving an issuer or a service account returns `400` while a live federation rule references it. Archive the rule first.
12761278 
12771279## See also
12781280 

manage-claude/wif-providers/aws Changed · +18 / -18 lines

from line 10
1010 
1111## Prerequisites
1212 
13* Familiarity with [WIF concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
13* Familiarity with [Workload Identity Federation (WIF) concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
1414* An AWS workload (EKS pod, ECS task, Lambda function, or EC2 instance) with an attached IAM role.
1515* The `aws` CLI or an AWS SDK available in the workload.
1616* Permission to create service accounts, federation issuers, and federation rules in the Claude Console for your Anthropic organization.
from line 50
5050 </Step>
5151 
5252 <Step title="Find your account’s STS issuer URL">
53 After you enable outbound federation, the **IAM > Account settings** page shows a **Get Token Issuer URL** field with a value of the form `https://<uuid>.tokens.sts.global.api.aws`. This URL is unique to your AWS account; copy it for the next step. To retrieve it programmatically:
53 After you enable outbound federation, the **IAM > Account settings** page shows a **Get Token Issuer URL** field with a value of the form `https://<uuid>.tokens.sts.global.api.aws`. This URL is unique to your AWS account. Copy it for the next step. To retrieve it programmatically:
5454 
5555 ```bash
5656 python3 -c "import boto3; print(boto3.client('iam').get_outbound_web_identity_federation_info())"
from line 64
6464 
6565The wizard creates these resources for you. Use the following values whether you enter them in the wizard or send them to the [Admin API](https://platform.claude.com/docs/en/manage-claude/wif-admin-api):
6666 
67**Federation issuer:** Register the per-account STS issuer URL you copied in the prior step. It exposes a public JWKS endpoint, so use discovery mode.
67**Federation issuer:** Register your account’s STS issuer URL, which you copied in the previous step. It exposes a public JWKS endpoint, so use discovery mode.
6868 
6969```json
7070{
from line 74
7474}
7575```
7676 
77**Federation rule:** Match the audience you pass to `GetWebIdentityToken` and the calling role’s ARN in the `sub` claim, in the form `arn:aws:iam::<account>:role/<role-name>`. The token also carries an `https://sts.amazonaws.com/` claim with `aws_account`, `org_id`, `principal_id`, and any `request_tags` you passed. For finer control, match on those with the rule’s `claims` map or a CEL `condition`.
77**Federation rule:** Match the audience you pass to `GetWebIdentityToken` and the calling role’s ARN in the `sub` claim, in the form `arn:aws:iam::<account>:role/<role-name>`. The token also carries an `https://sts.amazonaws.com/` claim with `aws_account`, `org_id`, `principal_id`, and any `request_tags` you passed. For finer control, match on those with a Common Expression Language (CEL) `condition`.
7878 
7979```json
8080{
from line 91
9191}
9292```
9393 
94Be as specific as the workload allows. Match the exact role ARN, and only broaden `subject_prefix` (for example, to `arn:aws:iam::123456789012:role/*`) if multiple IAM roles should map to the same Anthropic service account.
94Be as specific as the workload allows. Match the exact role ARN. Broaden `subject_prefix` (for example, to `arn:aws:iam::123456789012:role/*`) only if multiple IAM roles should map to the same Anthropic service account.
9595 
9696### Acquire and use the token
9797 
98Call `GetWebIdentityToken` with `https://api.anthropic.com` as the audience, then pass the result to the SDK’s federation credentials through `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`). Except in Java, where `IdentityTokenConfig` takes a token or a file path, that option takes a token provider, so the SDK calls STS again on each refresh.
98Call `GetWebIdentityToken` with `https://api.anthropic.com` as the audience, then pass the result to the SDK’s federation credentials through `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`). Where that option takes a token provider, the SDK calls STS again on each refresh.
9999 
100100<Note>
101 `GetWebIdentityToken` is available only on regional STS endpoints. If you receive `'STS' object has no attribute 'get_web_identity_token'` or a similar error, pin your STS client to a region (for example, `boto3.client("sts", region_name="us-east-1")`) and ensure your AWS SDK is recent enough to include the API.
101 `GetWebIdentityToken` is available only on regional STS endpoints. If your STS client reports that the operation does not exist, pin the client to a region (for example, `us-east-1`). Also make sure that your version of the AWS SDK includes the API.
102102</Note>
103103 
104104<CodeGroup>
from line 482
482482JSON
483483```
484484 
485A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason and see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common AWS-side cause is an `iss` mismatch: the per-account STS issuer URL must match the registered `issuer_url` exactly.
485A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason. Then see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common AWS-side cause is an `iss` mismatch. Your account’s STS issuer URL must match the registered `issuer_url` exactly.
486486 
487487## Use EKS projected service-account tokens
488488 
489If your workload runs in an EKS pod, you can skip the STS call and read a Kubernetes-projected service-account token directly from disk. Kubernetes natively projects an OIDC-compatible token into the pod, and the SDK can read it from a file path. This path has two fewer AWS configuration steps than the STS path but only works inside a pod; the underlying mechanism is the same as the [generic Kubernetes integration](https://platform.claude.com/docs/en/manage-claude/wif-providers/kubernetes).
489If your workload runs in an EKS pod, you can skip the STS call and read a Kubernetes-projected service-account token directly from disk. Kubernetes natively projects an OIDC-compatible token into the pod, and the SDK can read it from a file path. This path has two fewer AWS configuration steps than the STS path but only works inside a pod. The underlying mechanism is the same as in [Use WIF with Kubernetes](https://platform.claude.com/docs/en/manage-claude/wif-providers/kubernetes).
490490 
491This path additionally requires an EKS cluster with an [IAM OIDC provider enabled](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) and `kubectl` access to the cluster.
491This path also requires an EKS cluster with an [IAM OIDC provider enabled](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) and `kubectl` access to the cluster.
492492 
493493### Configure your EKS cluster
494494 
from line 573
573573 }
574574 ```
575575 
576 The `serviceAccountToken` projection sets `aud` to `https://api.anthropic.com`. The separate IRSA-injected token at `AWS_WEB_IDENTITY_TOKEN_FILE` carries `aud: sts.amazonaws.com` and is for AWS API calls, not this exchange.
576 The `serviceAccountToken` projection sets `aud` to `https://api.anthropic.com`. The separate token that IAM roles for service accounts (IRSA) injects at `AWS_WEB_IDENTITY_TOKEN_FILE` carries `aud: sts.amazonaws.com` and is for AWS API calls, not this exchange.
577577 </Step>
578578</Steps>
579579 
from line 593
593593}
594594```
595595 
596**Federation rule:** Match the Kubernetes `sub` claim and the Anthropic audience `https://api.anthropic.com`. (Project a dedicated service-account token with that audience; don’t reuse the IRSA default `sts.amazonaws.com` token.)
596**Federation rule:** Match the Kubernetes `sub` claim and the Anthropic audience `https://api.anthropic.com`. Project a dedicated service-account token with that audience. Don’t reuse the IRSA default `sts.amazonaws.com` token.
597597 
598598```json
599599{
from line 610
610610}
611611```
612612 
613Be as specific as the workload allows. Loosen `subject_prefix` to `system:serviceaccount:inference:*` (the trailing `*` makes it a prefix match) only if every service account in the namespace should map to the same Anthropic service account.
613Be as specific as the workload allows. Loosen `subject_prefix` to `system:serviceaccount:inference:*` only if every service account in the namespace should map to the same Anthropic service account. The trailing `*` makes it a prefix match.
614614 
615615### Acquire and use the token
616616 
617Inside the pod, the projected token is at `/var/run/secrets/anthropic.com/token` (exposed as `ANTHROPIC_IDENTITY_TOKEN_FILE` in the Pod spec). Pass that file to the SDK’s federation credentials and the SDK handles the exchange and refresh.
617Inside the pod, the projected token is at `/var/run/secrets/anthropic.com/token` (exposed as `ANTHROPIC_IDENTITY_TOKEN_FILE` in the Pod spec). The SDK gets its identity token from that file and handles the exchange and refresh.
618618 
619619<CodeGroup>
620620 ```bash cURL
from line 815
815815</CodeGroup>
816816 
817817<Tip>
818 The Pod spec already sets `ANTHROPIC_IDENTITY_TOKEN_FILE`, `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, and `ANTHROPIC_WORKSPACE_ID`, so you can construct the client with no arguments and the SDK reads the federation environment variables automatically.
818 The Pod spec already sets `ANTHROPIC_IDENTITY_TOKEN_FILE`, `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, and `ANTHROPIC_WORKSPACE_ID`. With these set, you can construct the client with no arguments, and the SDK reads the federation environment variables automatically.
819819</Tip>
820820 
821821### Verify the setup
from line 839
839839JSON
840840```
841841 
842A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason and see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common EKS-side cause is the projected token’s `aud` not matching the rule (project a token with `audience: https://api.anthropic.com`, not the IRSA default `sts.amazonaws.com`).
842A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason. Then see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common EKS-side cause is the projected token’s `aud` not matching the rule. Project a token with `audience: https://api.anthropic.com`, not the IRSA default `sts.amazonaws.com`.
843843 
844844## Scope your rule
845845 
from line 850
850850Lock the rule’s `match` block to the narrowest scope that fits your use case:
851851 
852852* **Pin the full role ARN:** Use `subject_prefix: "arn:aws:iam::<account>:role/<role-name>"` with no trailing `*` so other roles in the account do not match.
853* **Pin the account ID:** Match the `aws_account` field of the token’s `https://sts.amazonaws.com/` claim with the `claims` map or a CEL `condition` as a defense-in-depth check against a misconfigured prefix.
853* **Pin the account ID:** Match the `aws_account` field of the token’s `https://sts.amazonaws.com/` claim with a CEL `condition`. This adds a second check against a misconfigured prefix.
854854* **Pin namespace and service account on EKS:** Use the exact `system:serviceaccount:<namespace>:<name>` value with no `*` after the `system:serviceaccount:` prefix.
855855* **Use a separate rule for each environment:** Create distinct rules for production, staging, and development workloads rather than widening one prefix to cover them all.
856856 

manage-claude/wif-providers/azure Changed · +44 / -44 lines

from line 7
77Azure workloads authenticate to the Claude API by presenting a JSON Web Token (JWT) issued by Microsoft Entra ID, then exchanging it for a short-lived Anthropic access token. The setup follows the same shape on every Azure platform:
88 
991. **Register the token audience:** Create one app registration in your Microsoft Entra tenant to represent the Claude API audience. Every workload in the tenant requests Entra tokens for it.
102. **Set up the identity for your platform:** Use a managed identity on VMs, VM Scale Sets, App Service, Functions, and Container Apps, or Entra Workload Identity on AKS.
102. **Set up the identity for your platform:** Use a managed identity on VMs, VM Scale Sets, App Service, Functions, and Container Apps, or Entra Workload Identity on Azure Kubernetes Service (AKS).
11113. **Configure Anthropic:** Register your tenant’s Entra issuer, create a service account, and write a federation rule that matches the token’s claims.
12124. **Exchange at runtime:** Your workload exchanges its Entra-issued token at `POST /v1/oauth/token` for an `sk-ant-oat01-...` Anthropic access token and calls Claude with it.
1313 
14On both paths the token you present to Anthropic carries your tenant-specific Entra issuer and the managed identity’s object ID in the `sub` and `oid` claims; only how the workload obtains that token differs. Pick the section for where your workload runs: [Use a managed identity](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#use-a-managed-identity) for VMs, VM Scale Sets, App Service, Functions, and Container Apps, or [Use Entra Workload Identity on AKS](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#use-entra-workload-identity-on-aks) for AKS.
14On both paths the token you present to Anthropic carries your tenant-specific Entra issuer and the managed identity’s object ID in the `sub` and `oid` claims. Only how the workload obtains that token differs. For VMs, VM Scale Sets, App Service, Functions, and Container Apps, see [Use a managed identity](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#use-a-managed-identity). For AKS, see [Use Entra Workload Identity on AKS](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#use-entra-workload-identity-on-aks).
1515 
1616## Prerequisites
1717 
18* Familiarity with [WIF concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
18* Familiarity with [Workload Identity Federation (WIF) concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
1919* An Azure subscription with permission to assign managed identities (or configure Entra Workload Identity on AKS).
2020* Permission to create one app registration and service principal in your Microsoft Entra tenant (the shared Claude API audience). Entra only issues tokens for an audience that exists in the tenant, so the [Register the token audience](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#register-the-token-audience) step is required before any token request succeeds.
2121* Your Microsoft Entra tenant ID. Find it in the Azure portal under **Microsoft Entra ID → Overview → Tenant ID**.
from line 23
2323 
2424## Register the token audience
2525 
26Microsoft Entra ID only issues a token when the requested audience exists in your tenant as an app registration with a service principal. Create one app registration to represent the Claude API audience; every workload in the tenant can request tokens for it. Without this registration, token requests fail with a “resource not found in tenant” error (`AADSTS50001` from the managed identity endpoints, `AADSTS500011` from the Entra token endpoint).
26Microsoft Entra ID only issues a token when the requested audience exists in your tenant as an app registration with a service principal. Create one app registration to represent the Claude API audience. Every workload in the tenant can request tokens for it. Without this registration, token requests fail with a “resource not found in tenant” error (`AADSTS50001` from the managed identity endpoints, `AADSTS500011` from the Entra token endpoint).
2727 
2828```bash
2929# Create the app registration that represents the Claude API audience.
from line 39
3939```
4040 
4141<Note>
42 Use the `api://<APP_ID>` identifier URI format. Entra restricts `https://` identifier URIs to verified domains of your own tenant, so a URI such as `https://api.anthropic.com` cannot be registered in most tenants; `api://<APP_ID>` is accepted everywhere. With `requestedAccessTokenVersion: 2`, tokens for this audience are v2.0, which is what this guide assumes. If you reuse an existing registration that emits v1.0 tokens, see [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
42 Use the `api://<APP_ID>` identifier URI format. Entra restricts `https://` identifier URIs to verified domains of your own tenant, so you cannot register a URI such as `https://api.anthropic.com` in most tenants. Entra accepts `api://<APP_ID>` everywhere. With `requestedAccessTokenVersion: 2`, tokens for this audience are v2.0, which is what this guide assumes. If you reuse an existing registration that emits v1.0 tokens, see [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
4343</Note>
4444 
4545## Use a managed identity
from line 52
5252 <Step title="Attach a managed identity">
5353 Enable a system-assigned or user-assigned managed identity on your Azure resource. In the Azure portal, open the resource, go to **Identity**, and turn on **System assigned** (or attach a user-assigned identity).
5454 
55 After the identity is created, note its **Object (principal) ID**. This GUID appears as both the `sub` and `oid` claims in the issued token, and your Anthropic federation rule matches on it. You can find it on the resource’s **Identity** page; for a user-assigned identity, it is the **Object (principal) ID** on the managed identity resource’s **Overview** page. (A managed identity has only a service principal in Microsoft Entra ID, not an app registration.)
55 After you attach the identity, note its **Object (principal) ID**. This GUID appears as both the `sub` and `oid` claims in the issued token, and your Anthropic federation rule matches on it. You can find it on the resource’s **Identity** page. For a user-assigned identity, it is the **Object (principal) ID** on the managed identity resource’s **Overview** page. (A managed identity has only a service principal in Microsoft Entra ID, not an app registration.)
5656 </Step>
5757 
5858 <Step title="Find the platform’s token endpoint">
59 The platform exposes a local token endpoint once the identity is attached:
59 The platform exposes a local token endpoint once you attach the identity:
6060 
61 * **VMs and VM Scale Sets:** IMDS at `http://169.254.169.254/metadata/identity/oauth2/token` with the header `Metadata: true` and `api-version=2018-02-01`.
61 * **VMs and VM Scale Sets:** Azure Instance Metadata Service (IMDS) at `http://169.254.169.254/metadata/identity/oauth2/token` with the header `Metadata: true` and `api-version=2018-02-01`.
6262 * **App Service, Functions, and Container Apps:** The URL in the `IDENTITY_ENDPOINT` environment variable with the header `X-IDENTITY-HEADER` set to the value of `IDENTITY_HEADER`, and `api-version=2019-08-01`. IMDS is not reachable on these platforms.
6363 
64 If the resource has more than one user-assigned managed identity, add `client_id=<IDENTITY_CLIENT_ID>` to the token request to select one. Azure recommends always specifying it. Without it, the outcome depends on whether the resource also has a system-assigned identity enabled: if it does, the request silently falls back to that identity and then fails your federation rule’s `oid` match; if it does not, the request fails outright as soon as a second user-assigned identity is attached.
64 If the resource has more than one user-assigned managed identity, add `client_id=<IDENTITY_CLIENT_ID>` to the token request to select one. Azure recommends always specifying it. Without it, the outcome depends on whether the resource also has a system-assigned identity enabled. If it does, the request silently falls back to that identity and then fails your federation rule’s `oid` match. If it does not, the request fails outright as soon as you attach a second user-assigned identity.
6565 </Step>
6666 
6767 <Step title="Decode a sample token">
from line 82
8282 
8383 | Claim | Value | Match this when |
8484 | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
85 | `oid` | The managed identity’s object ID, identical to `sub` | You want to authorize one specific managed identity. This is the default; the rule in [Configure Anthropic](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#configure-anthropic) matches it. |
85 | `oid` | The managed identity’s object ID, identical to `sub` | You want to authorize one specific managed identity. This is the default. The rule in [Configure Anthropic](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#configure-anthropic) matches it. |
8686 | `azp` | The calling identity’s client ID | You want to authorize every workload that shares one app registration. For a managed identity, `azp` is unique to that identity, so it is equivalent to `oid`. |
8787 | `aud` | The audience app registration’s client ID (the `<APP_ID>` GUID from [Register the token audience](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#register-the-token-audience)) | Always. The rule’s `audience` field must equal the token’s `aud` value exactly. |
8888 | `tid` | Your tenant ID | You want defense in depth. The issuer URL already pins the tenant. |
from line 97
9797 
9898The wizard creates these resources for you. Use the following values whether you enter them in the wizard or send them to the [Admin API](https://platform.claude.com/docs/en/manage-claude/wif-admin-api):
9999 
100**Federation issuer:** Select **v2.0 (login.microsoftonline.com)** in the wizard’s **Token issuer** selector. (The selector defaults to v1; that default exists for tenants reusing older registrations that still emit v1.0 tokens.) Entra publishes an OIDC discovery document at the per-tenant issuer URL, so use discovery mode. Each Microsoft Entra tenant you federate needs its own issuer record.
100**Federation issuer:** Select **v2.0 (login.microsoftonline.com)** in the wizard’s **Token issuer** selector. (The selector defaults to v1. That default serves tenants whose existing registrations emit v1.0 tokens.) Entra publishes an OpenID Connect (OIDC) discovery document at the tenant-specific issuer URL, so use discovery mode. Each Microsoft Entra tenant you federate needs its own issuer record.
101101 
102102```json
103103{
from line 109
109109```
110110 
111111<Warning>
112 Managed identity workloads need `max_jwt_lifetime_seconds: 86400`. Azure issues managed identity tokens with up to 24 hours between `iat` and `exp` because it caches each resource’s token for that window and offers no way to force an early refresh, and the issuer’s 1-hour default rejects those tokens, so the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`). The **Connect workload** wizard’s **Microsoft Entra** tile creates the issuer with `max_jwt_lifetime_seconds` set to `7500` and provides no field to change it during creation, so complete the wizard, then open the **Issuers** tab on the [Workload identity](https://platform.claude.com/settings/workload-identity-federation) page in the Claude Console, edit the issuer, and raise the value to `86400`. You can also update the issuer through the Admin API.
112 Managed identity workloads need `max_jwt_lifetime_seconds: 86400`. Azure issues managed identity tokens with up to 24 hours between `iat` and `exp`. It caches each resource’s token for that window and offers no way to force an early refresh. The issuer’s 1-hour default rejects those tokens, so the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`). The **Connect workload** wizard’s **Microsoft Entra** tile creates the issuer with `max_jwt_lifetime_seconds` set to `7500` and provides no field to change it during creation. Complete the wizard, then open the **Issuers** tab on the [Workload identity](https://platform.claude.com/settings/workload-identity-federation) page in the Claude Console, edit the issuer, and raise the value to `86400`. You can also update the issuer through the Admin API.
113113</Warning>
114114 
115A longer accepted lifetime means a leaked Entra token stays exchangeable for longer. If a token leaks, disable the federation rule; a tight `oid` match limits which identities can exchange a token in the first place, as described in [Scope your rule](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#scope-your-rule).
115A longer accepted lifetime means a leaked Entra token stays exchangeable for longer. If a token leaks, disable the federation rule. A tight `oid` match limits which identities can exchange a token, as described in [Scope your rule](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#scope-your-rule).
116116 
117117**Federation rule:** Match on the managed identity’s object ID and your tenant ID. For the v2.0 tokens this guide configures, the `audience` value is the audience app registration’s client ID (the `<APP_ID>` GUID from [Register the token audience](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#register-the-token-audience)). Use the exact `aud` value from your decoded token.
118118 
from line 137
137137}
138138```
139139 
140`token_lifetime_seconds` is the lifetime of the Anthropic access token the exchange returns, not of the Entra token; the SDK refreshes it for you.
140`token_lifetime_seconds` is the lifetime of the Anthropic access token the exchange returns, not of the Entra token. The SDK refreshes the access token for you.
141141 
142142### Acquire and use the token
143143 
144At runtime your workload fetches its Entra token, exchanges it at `POST /v1/oauth/token`, and uses the returned bearer token to call Claude. The Claude SDK handles the exchange and refresh loop when you supply `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`), as shown in the following examples. Except in Java, where `IdentityTokenConfig` takes a token or a file path, that option takes a token provider, and the SDK calls it again for each refresh.
144At runtime your workload fetches its Entra token, exchanges it at `POST /v1/oauth/token`, and uses the returned bearer token to call Claude. The SDK handles the exchange and refresh loop when you supply `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`), as shown in the following examples. Where that option takes a token provider, the SDK calls it again for each refresh.
145145 
146The samples fetch the managed identity token from the platform’s token endpoint: IMDS on VMs and VM Scale Sets, or the `IDENTITY_ENDPOINT` service on App Service, Functions, and Container Apps. Replace `<APP_ID>` in the `api://<APP_ID>` resource value with the audience app registration’s client ID from [Register the token audience](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#register-the-token-audience).
146The samples fetch the managed identity token from the platform’s token endpoint. That endpoint is IMDS on VMs and VM Scale Sets, or the `IDENTITY_ENDPOINT` service on App Service, Functions, and Container Apps. Replace `<APP_ID>` in the `api://<APP_ID>` resource value with the audience app registration’s client ID from [Register the token audience](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#register-the-token-audience).
147147 
148148<Tip>
149149 If your workload already uses the Azure Identity client library, get the Entra token from it (`DefaultAzureCredential` with the scope `api://<APP_ID>/.default`) instead of calling the token endpoints directly. Supply it to `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`) the way the examples do. The library selects the correct endpoint on every Azure platform, including AKS with Entra Workload Identity.
from line 616
616616 
617617### Verify the setup
618618 
619From your Azure resource, run the sample in [Acquire and use the token](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#acquire-and-use-the-token). A successful exchange returns a `200` with an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason, then decode the Entra token (see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange) for the command) and check the most common Azure-side causes:
619From your Azure resource, run the sample in [Acquire and use the token](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#acquire-and-use-the-token). A successful exchange returns a `200` with an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason. Then decode the Entra token (see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange) for the command) and check the most common Azure-side causes:
620620 
621* **Issuer mismatch:** The registered `issuer_url` must match the token’s `iss` claim exactly. A v2.0 token carries `https://login.microsoftonline.com/<TENANT_ID>/v2.0`; if the decoded `ver` claim is `1.0`, see [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
622* **Token lifetime:** Managed identity tokens carry up to 24 hours between `iat` and `exp`. If the issuer still has the wizard’s `7500` (or the 1-hour default), raise `max_jwt_lifetime_seconds` to `86400` as described in [Configure Anthropic](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#configure-anthropic).
621* **Issuer mismatch:** The registered `issuer_url` must match the token’s `iss` claim exactly. A v2.0 token carries `https://login.microsoftonline.com/<TENANT_ID>/v2.0`. If the decoded `ver` claim is `1.0`, see [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
622* **Token lifetime:** Managed identity tokens carry up to 24 hours between `iat` and `exp`. If the issuer has the wizard’s `7500` (or the 1-hour default), raise `max_jwt_lifetime_seconds` to `86400` as described in [Configure Anthropic](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#configure-anthropic).
623623* **Audience mismatch:** The rule’s `audience` must equal the token’s `aud` exactly: the audience app registration’s client ID for the v2.0 tokens this guide configures.
624* **Claim name mismatch:** A rule that matches on a claim the token does not carry never passes. v1.0 tokens carry the client ID in `appid`, not `azp`; see [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
624* **Claim name mismatch:** A rule that matches on a claim the token does not carry never passes. A v1.0 token carries the client ID in `appid`, not `azp`. See [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
625625 
626626## Use Entra Workload Identity on AKS
627627 
628Use this path when your workload runs in an AKS pod. Entra Workload Identity federates a Kubernetes service account with a user-assigned managed identity: Kubernetes projects a service account token (signed by the AKS cluster’s OIDC issuer) into the pod at the path in `AZURE_FEDERATED_TOKEN_FILE`. That projected token is not an Entra-issued token, so to stay on the Entra-mediated path described on this page, the workload performs a two-hop exchange. First, it redeems the projected token at `https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token` (federated `client_credentials` grant) for an Entra-issued access token. Then it passes that Entra token to the Anthropic SDK as the identity token.
628Use this path when your workload runs in an AKS pod. Entra Workload Identity federates a Kubernetes service account with a user-assigned managed identity. Kubernetes projects a service account token (signed by the AKS cluster’s OIDC issuer) into the pod at the path in `AZURE_FEDERATED_TOKEN_FILE`. That projected token is not an Entra-issued token. To stay on the Entra-mediated path described on this page, the workload performs a two-hop exchange. First, it redeems the projected token at `https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token` (federated `client_credentials` grant) for an Entra-issued access token. Then it passes that Entra token to the SDK as the identity token.
629629 
630630<Tip>
631631 AKS pods can alternatively skip the Entra exchange and present the Kubernetes-projected service account token to Anthropic directly. That path registers your AKS cluster’s OIDC issuer with Anthropic instead of your Entra tenant. See [Use WIF with Kubernetes](https://platform.claude.com/docs/en/manage-claude/wif-providers/kubernetes) for that flow.
from line 635
635635 
636636<Steps>
637637 <Step title="Enable the OIDC issuer and workload identity on your cluster">
638 Enabling workload identity installs the `azure-workload-identity` mutating webhook for you; deploy it manually only on non-AKS clusters. Capture the cluster’s OIDC issuer URL for the federated credential you create in a later step.
638 Enabling workload identity installs the `azure-workload-identity` mutating webhook for you. Deploy it manually only on non-AKS clusters. Capture the cluster’s OIDC issuer URL for the federated credential you create in a later step.
639639 
640640 ```bash
641641 az aks update \
from line 652
652652 </Step>
653653 
654654 <Step title="Create a user-assigned managed identity">
655 Capture two values from the identity: the **Client ID** goes into the service account annotation (and is injected into the pod as `AZURE_CLIENT_ID`), and the **Object (principal) ID** appears as the `oid` claim that your Anthropic federation rule matches.
655 Capture two values from the identity. The **Client ID** goes into the service account annotation, and the webhook injects it into the pod as `AZURE_CLIENT_ID`. The **Object (principal) ID** appears as the `oid` claim that your Anthropic federation rule matches.
656656 
657657 ```bash
658658 az identity create \
from line 675
675675 </Step>
676676 
677677 <Step title="Create the annotated Kubernetes service account">
678 The `azure-workload-identity` webhook reads the `azure.workload.identity/client-id` annotation to inject `AZURE_CLIENT_ID` into the pod, which the samples in [Acquire and use the token on AKS](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#acquire-and-use-the-token-2) read from the environment.
678 The `azure-workload-identity` webhook reads the `azure.workload.identity/client-id` annotation to inject `AZURE_CLIENT_ID` into the pod. The samples in [Acquire and use the token on AKS](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#acquire-and-use-the-token-2) read it from the environment.
679679 
680680 ```yaml
681681 apiVersion: v1
from line 689
689689 </Step>
690690 
691691 <Step title="Create the federated credential on the managed identity">
692 The federated credential trusts your cluster’s OIDC issuer for that specific service account. The `--audience api://AzureADTokenExchange` value is Entra’s fixed audience for incoming Kubernetes service account tokens; it is unrelated to the Claude API audience you registered earlier.
692 The federated credential trusts your cluster’s OIDC issuer for that specific service account. The `--audience api://AzureADTokenExchange` value is Entra’s fixed audience for incoming Kubernetes service account tokens. It is unrelated to the Claude API audience you registered earlier.
693693 
694694 ```bash
695695 az identity federated-credential create \
from line 722
722722 </Step>
723723 
724724 <Step title="Decode a sample token">
725 The token your Anthropic federation rule sees is not the projected file; it is the Entra-issued token returned by the `client_credentials` exchange. From inside a labeled pod, fetch the Entra token as shown in [Acquire and use the token on AKS](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#acquire-and-use-the-token-2) and decode the result. It carries the same claim shape as the managed identity path:
725 The token your Anthropic federation rule sees is not the projected file. It is the Entra-issued token returned by the `client_credentials` exchange. From inside a labeled pod, fetch the Entra token as shown in [Acquire and use the token on AKS](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#acquire-and-use-the-token-2) and decode the result. It carries the same claim shape as the managed identity path:
726726 
727727 ```json
728728 {
from line 737
737737 }
738738 ```
739739 
740 `sub` and `oid` are the managed identity’s object ID, `aud` is the audience app registration’s client ID, and `azp` is the managed identity’s client ID (the value of `AZURE_CLIENT_ID`). The lifetime differs from the managed identity path: `client_credentials` tokens default to a random 60- to 90-minute window between `iat` and `exp`, not 24 hours.
740 `sub` and `oid` are the managed identity’s object ID, `aud` is the audience app registration’s client ID, and `azp` is the managed identity’s client ID (the value of `AZURE_CLIENT_ID`). The lifetime differs from the managed identity path. `client_credentials` tokens default to a random 60- to 90-minute window between `iat` and `exp`, not 24 hours.
741741 </Step>
742742</Steps>
743743 
from line 747
747747 
748748The wizard creates these resources for you. Use the following values whether you enter them in the wizard or send them to the [Admin API](https://platform.claude.com/docs/en/manage-claude/wif-admin-api):
749749 
750**Federation issuer:** Select **v2.0 (login.microsoftonline.com)** in the wizard’s **Token issuer** selector. (The selector defaults to v1; that default exists for tenants reusing older registrations that still emit v1.0 tokens.) Entra publishes an OIDC discovery document at the per-tenant issuer URL, so use discovery mode. Each Microsoft Entra tenant you federate needs its own issuer record.
750**Federation issuer:** Select **v2.0 (login.microsoftonline.com)** in the wizard’s **Token issuer** selector. (The selector defaults to v1. That default serves tenants whose existing registrations emit v1.0 tokens.) Entra publishes an OIDC discovery document at the tenant-specific issuer URL, so use discovery mode. Each Microsoft Entra tenant you federate needs its own issuer record.
751751 
752752```json
753753{
from line 759
759759```
760760 
761761<Warning>
762 The **Connect workload** wizard’s **Microsoft Entra** tile creates the issuer with `max_jwt_lifetime_seconds` set to `7500` (just over 2 hours), which covers the default 60- to 90-minute lifetime of `client_credentials` tokens. A tenant token-lifetime policy or Continuous Access Evaluation (CAE) can extend that lifetime. If your decoded token’s `exp` minus `iat` exceeds 7,500 seconds, edit the issuer on the **Issuers** tab of the [Workload identity](https://platform.claude.com/settings/workload-identity-federation) page in the Claude Console and raise `max_jwt_lifetime_seconds` to match, or exchanges fail with the opaque `401` `authentication_error` response (message `Authentication failed`). If your tenant also runs managed-identity workloads from [Use a managed identity](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#use-a-managed-identity), use that section’s `86400` value, which covers both paths.
762 The **Connect workload** wizard’s **Microsoft Entra** tile creates the issuer with `max_jwt_lifetime_seconds` set to `7500` (a little over 2 hours). That value covers the default 60- to 90-minute lifetime of `client_credentials` tokens. A tenant token-lifetime policy or Continuous Access Evaluation (CAE) can extend that lifetime. If your decoded token’s `exp` minus `iat` exceeds 7,500 seconds, edit the issuer on the **Issuers** tab of the [Workload identity](https://platform.claude.com/settings/workload-identity-federation) page in the Claude Console and raise `max_jwt_lifetime_seconds` to match. Until you do, exchanges fail with the opaque `401` `authentication_error` response (message `Authentication failed`). If your tenant also runs managed identity workloads from [Use a managed identity](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#use-a-managed-identity), use that section’s `86400` value, which covers both paths.
763763</Warning>
764764 
765A longer accepted lifetime means a leaked Entra token stays exchangeable for longer. If a token leaks, disable the federation rule; a tight `oid` match limits which identities can exchange a token in the first place, as described in [Scope your rule](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#scope-your-rule).
765A longer accepted lifetime means a leaked Entra token stays exchangeable for longer. If a token leaks, disable the federation rule. A tight `oid` match limits which identities can exchange a token, as described in [Scope your rule](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#scope-your-rule).
766766 
767767**Federation rule:** Match on the managed identity’s object ID and your tenant ID. For the v2.0 tokens this guide configures, the `audience` value is the audience app registration’s client ID (the `<APP_ID>` GUID from [Register the token audience](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#register-the-token-audience)). Use the exact `aud` value from your decoded token.
768768 
from line 787
787787}
788788```
789789 
790`token_lifetime_seconds` is the lifetime of the Anthropic access token the exchange returns, not of the Entra token; the SDK refreshes it for you.
790`token_lifetime_seconds` is the lifetime of the Anthropic access token the exchange returns, not of the Entra token. The SDK refreshes the access token for you.
791791 
792792### Acquire and use the token
793793 
794At runtime the pod performs the two-hop exchange: it sends the Kubernetes-projected token (the file at `AZURE_FEDERATED_TOKEN_FILE`) to Entra’s token endpoint as a federated `client_credentials` assertion, then exchanges the resulting Entra access token at `POST /v1/oauth/token`. The Claude SDK handles the second exchange and the refresh loop when you supply `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`), as shown in the following examples. Except in Java, where `IdentityTokenConfig` takes a token or a file path, that option takes your Entra fetch as a token provider, and the SDK calls it again for each refresh.
794At runtime the pod performs the two-hop exchange. It sends the Kubernetes-projected token (the file at `AZURE_FEDERATED_TOKEN_FILE`) to Entra’s token endpoint as a federated `client_credentials` assertion. It then exchanges the resulting Entra access token at `POST /v1/oauth/token`. The SDK handles the second exchange and the refresh loop when you supply `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`), as shown in the following examples. Where that option takes a token provider, the SDK calls it again for each refresh.
795795 
796Two different client IDs appear in the samples. `<APP_ID>` is the audience app registration’s client ID from [Register the token audience](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#register-the-token-audience); the scope `api://<APP_ID>/.default` asks Entra for a token addressed to that audience. `$AZURE_CLIENT_ID` is the managed identity’s client ID, injected by the webhook, and identifies the caller. Do not substitute one for the other.
796Two different client IDs appear in the samples. `<APP_ID>` is the audience app registration’s client ID from [Register the token audience](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#register-the-token-audience). The scope `api://<APP_ID>/.default` asks Entra for a token addressed to that audience. `AZURE_CLIENT_ID`, which the webhook injects, is the managed identity’s client ID and identifies the caller. Do not substitute one for the other.
797797 
798798<Tip>
799799 If your workload already uses the Azure Identity client library, get the Entra token from it (`DefaultAzureCredential` with the scope `api://<APP_ID>/.default`) instead of performing the two-hop exchange yourself. Supply it to `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`) the way the examples do. The library reads the same `AZURE_FEDERATED_TOKEN_FILE`, `AZURE_CLIENT_ID`, and `AZURE_TENANT_ID` environment variables and handles the Entra exchange.
from line 1247
12471247 
12481248From inside a labeled pod, run the sample in [Acquire and use the token on AKS](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#acquire-and-use-the-token-2). A successful exchange returns a `200` with an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason. Then decode the Entra-issued token (see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange) for the command) and check the most common Azure-side causes:
12491249 
1250* **Issuer mismatch:** The registered `issuer_url` must match the token’s `iss` claim exactly. A v2.0 token carries `https://login.microsoftonline.com/<TENANT_ID>/v2.0`; if the decoded `ver` claim is `1.0`, see [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
1250* **Issuer mismatch:** The registered `issuer_url` must match the token’s `iss` claim exactly. A v2.0 token carries `https://login.microsoftonline.com/<TENANT_ID>/v2.0`. If the decoded `ver` claim is `1.0`, see [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
12511251* **Token lifetime:** If a tenant token-lifetime policy or CAE extends the `client_credentials` token past 7,500 seconds, raise the issuer’s `max_jwt_lifetime_seconds` as described in [Configure Anthropic for Entra Workload Identity on AKS](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#configure-anthropic-2).
12521252* **Audience mismatch:** The rule’s `audience` must equal the token’s `aud` exactly: the audience app registration’s client ID for the v2.0 tokens this guide configures.
1253* **Claim name mismatch:** A rule that matches on a claim the token does not carry never passes. v1.0 tokens carry the client ID in `appid`, not `azp`; see [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
1253* **Claim name mismatch:** A rule that matches on a claim the token does not carry never passes. A v1.0 token carries the client ID in `appid`, not `azp`. See [If your tokens are v1.0](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#if-your-tokens-are-v1-0).
12541254 
12551255## If your tokens are v1.0
12561256 
1257This guide configures the audience app registration with `api.requestedAccessTokenVersion: 2`, so every token it shows is v2.0. If you reuse an existing registration that leaves `requestedAccessTokenVersion` unset, Entra issues v1.0 tokens instead. Decode a sample token and check its `ver` claim; if it is `1.0`, four things change:
1257This guide configures the audience app registration with `api.requestedAccessTokenVersion: 2`, so every token it shows is v2.0. If you reuse an existing registration that leaves `requestedAccessTokenVersion` unset, Entra issues v1.0 tokens instead. Decode a sample token and check its `ver` claim. If it is `1.0`, four things change:
12581258 
12591259* **Issuer:** The `iss` claim is `https://sts.windows.net/<TENANT_ID>/` instead of `https://login.microsoftonline.com/<TENANT_ID>/v2.0`. Register the issuer URL exactly as your token’s `iss` claim carries it. The two URLs share the same JWKS, so discovery mode works for either.
12601260* **Wizard selector:** Select **v1 (sts.windows.net)** in the **Connect workload** wizard’s **Token issuer** selector instead of **v2.0 (login.microsoftonline.com)**.
from line 1265
12651265 
12661266## Scope your rule
12671267 
1268A federation rule can match the token’s subject with `subject_prefix` in addition to (or instead of) the `claims` map; see [Rule matching semantics](https://platform.claude.com/docs/en/manage-claude/wif-reference#rule-matching-semantics) for how the fields combine. Entra `sub` values for these identities are fixed-length canonical GUIDs, so a `subject_prefix` containing the full 36-character object ID matches only that subject; this is a property of Entra’s subject format, not of `subject_prefix` in general.
1268A federation rule can match the token’s subject with `subject_prefix` in addition to (or instead of) the `claims` map. See [Rule matching semantics](https://platform.claude.com/docs/en/manage-claude/wif-reference#rule-matching-semantics) for how the fields combine. Entra `sub` values for these identities are fixed-length canonical GUIDs, so a `subject_prefix` containing the full 36-character object ID matches only that subject. This is a property of Entra’s subject format, not of `subject_prefix` in general.
12691269 
12701270<Warning>
12711271 Every identity in your tenant can request a token for the registered audience, so `audience` and `tid` alone do not identify a specific workload. A rule that omits an `oid` (or `azp`/`appid`) match, or that uses a wildcard or partial-GUID `subject_prefix`, authorizes every managed identity and service principal in the tenant.
from line 1273
12731273 
12741274Lock the rule’s `match` block to the narrowest scope that fits your use case:
12751275 
1276* **Match `oid` as an exact value:** Set `claims.oid` to the managed identity’s full object ID. A `subject_prefix` set to that full object ID is equivalent (the Console wizard sets both); never use a wildcard or partial-GUID `subject_prefix`, which matches more identities than you intend.
1276* **Match `oid` as an exact value:** Set `claims.oid` to the managed identity’s full object ID. A `subject_prefix` set to that full object ID is equivalent (the Console wizard sets both). Never use a wildcard or partial-GUID `subject_prefix`, which matches more identities than you intend.
12771277* **Pin `tid` as defense in depth:** The issuer URL already pins your tenant, but adding `claims.tid` guards against configuration drift if the issuer record is later edited.
1278* **Pin the audience:** Set `audience` to the exact `aud` value from your decoded token so tokens minted for other applications are rejected.
1278* **Pin the audience:** Set `audience` to the exact `aud` value from your decoded token so the rule rejects tokens issued for other applications.
12791279* **Use a separate rule for each managed identity:** Create one rule for each identity rather than one rule that authorizes several, so you can revoke a single workload’s access without affecting others.
12801280 
12811281## Next steps
12821282 
12831283* Review the full configuration model in [Workload Identity Federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation).
1284* See the [provider guides](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#identity-providers) for AWS, Google Cloud, GitHub Actions, and Kubernetes.
1284* For AWS, Google Cloud, GitHub Actions, and Kubernetes, see [Identity providers](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#identity-providers).
12851285* For environment variables, profile files, and credential precedence, see the [WIF reference](https://platform.claude.com/docs/en/manage-claude/wif-reference).
12861286 

manage-claude/wif-providers/gcp Changed · +14 / -14 lines

from line 4
44description: Federate Google Cloud workloads (Cloud Run, Cloud Functions, App Engine, GCE, GKE) to the Claude API using Google-signed identity tokens instead of static API keys.
55---
66 
7Any Google Cloud compute environment with access to the instance metadata server (Cloud Run, Cloud Functions, App Engine, Compute Engine (GCE), and GKE with Workload Identity) can request a Google-signed identity token for its attached service account. The token’s issuer is `https://accounts.google.com`, and Anthropic can validate it directly through standard OIDC discovery, with no extra Google Cloud configuration required.
7Any Google Cloud compute environment with access to the instance metadata server can request a Google-signed identity token for its attached service account. These environments include Cloud Run, Cloud Functions, App Engine, Compute Engine (GCE), and Google Kubernetes Engine (GKE) with Workload Identity. The token’s issuer is `https://accounts.google.com`, and Anthropic can validate it directly through standard OpenID Connect (OIDC) discovery, with no extra Google Cloud configuration required.
88 
9This guide shows how to register the Google issuer with Anthropic, bind a Google service account to an Anthropic service account, and have your workload exchange its identity token for a short-lived Claude API access token.
9This guide shows how to register the Google issuer with Anthropic and bind a Google service account to an Anthropic service account. It then shows how to have your workload exchange its identity token for a short-lived Claude API access token.
1010 
1111## Prerequisites
1212 
13* Familiarity with [WIF concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
13* Familiarity with [Workload Identity Federation (WIF) concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
1414* A Google Cloud project with a workload running on Cloud Run, Cloud Functions, App Engine, Compute Engine, or GKE.
1515* A user-managed Google service account attached to that workload (not the Compute Engine default service account).
1616* Permission to create service accounts, federation issuers, and federation rules in the Claude Console for your Anthropic organization.
from line 43
4343 --include-email
4444 ```
4545 
46 The SDK equivalents are shown in [Acquire and use the token](https://platform.claude.com/docs/en/manage-claude/wif-providers/gcp#acquire-and-use-the-token).
46 For the SDK equivalents, see [Acquire and use the token](https://platform.claude.com/docs/en/manage-claude/wif-providers/gcp#acquire-and-use-the-token).
4747 
4848 The decoded token payload looks like this:
4949 
from line 75
7575 iam.gke.io/gcp-service-account: [email protected]
7676 ```
7777 
78 With this binding in place, the GKE metadata server returns a Google-signed token identical to the Cloud Run and GCE case: same `https://accounts.google.com` issuer, same `email` claim, same fetch URL. Configure Anthropic exactly as in the next section.
78 With this binding in place, the GKE metadata server returns a Google-signed token identical to the Cloud Run and GCE case. The `https://accounts.google.com` issuer, the `email` claim, and the fetch URL are all the same. Configure Anthropic exactly as in the next section.
7979 
80 A `format=full` token from GKE additionally includes `google.compute_engine.project_id`, `google.compute_engine.zone`, and `google.compute_engine.instance_name` claims, which you can reference in a federation rule’s `condition` matcher (a CEL expression such as `claims.google.compute_engine.project_id == "my-project"`) to scope access to a specific cluster or node pool.
80 A `format=full` token from GKE also includes the `google.compute_engine.project_id`, `google.compute_engine.zone`, and `google.compute_engine.instance_name` claims. To scope access to a specific cluster or node pool, reference these claims in a federation rule’s `condition` matcher, a Common Expression Language (CEL) expression such as `claims.google.compute_engine.project_id == "my-project"`.
8181 
8282 <Note>
83 If you do not want to bind Kubernetes service accounts to Google service accounts, GKE pods can instead use the cluster’s own OIDC issuer (`https://container.googleapis.com/v1/projects/PROJECT/locations/REGION/clusters/CLUSTER`) with a projected `serviceAccountToken` volume. That path uses a per-cluster issuer rather than `accounts.google.com`. See [Use WIF with Kubernetes](https://platform.claude.com/docs/en/manage-claude/wif-providers/kubernetes) for that pattern.
83 You do not have to bind Kubernetes service accounts to Google service accounts. GKE pods can instead use the cluster’s own OIDC issuer (`https://container.googleapis.com/v1/projects/PROJECT/locations/REGION/clusters/CLUSTER`) with a projected `serviceAccountToken` volume. That path uses a cluster-specific issuer rather than `accounts.google.com`. See [Use WIF with Kubernetes](https://platform.claude.com/docs/en/manage-claude/wif-providers/kubernetes) for that pattern.
8484 </Note>
8585 </Tab>
8686</Tabs>
from line 101
101101}
102102```
103103 
104**Federation rule:** Match on both the `sub` and `email` claims. `email` is the readable service-account address; `sub` is the service account’s numeric unique ID, which Google never reuses, so pinning it protects the rule if the service account is deleted and a new one is later created with the same email. Find the unique ID with `gcloud iam service-accounts describe [email protected] --format='value(uniqueId)'`.
104**Federation rule:** Match on both the `sub` and `email` claims. `email` is the readable service account address. `sub` is the service account’s numeric unique ID, which Google never reuses. Pinning it protects the rule if someone deletes the service account and later creates a new one with the same email. Find the unique ID with `gcloud iam service-accounts describe [email protected] --format='value(uniqueId)'`.
105105 
106106```json
107107{
from line 126
126126 
127127## Acquire and use the token
128128 
129Inside your Google Cloud workload, fetch the identity token from the metadata server, exchange it at `POST /v1/oauth/token`, and use the returned bearer token to call the Claude API. The Claude SDK handles the exchange and refresh loop for you when you supply `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`), as shown in the following examples. Except in Java, where `IdentityTokenConfig` takes a token or a file path, that option takes a token provider that returns a fresh identity token from the metadata server.
129Inside your Google Cloud workload, fetch the identity token from the metadata server, exchange it at `POST /v1/oauth/token`, and use the returned bearer token to call the Claude API. The SDK handles the exchange and refresh loop for you when you supply `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`), as shown in the following examples. Where that option takes a token provider, pass one that returns a fresh identity token from the metadata server.
130130 
131131<CodeGroup>
132132 ```bash cURL
from line 455
455455 ```
456456</CodeGroup>
457457 
458Google identity tokens expire after roughly 1 hour. Except in Java, where `IdentityTokenConfig` takes a token or a file path, the SDK calls the token provider again and repeats the exchange automatically before expiry. For shell scripts that run longer than the access token’s `expires_in`, refresh on a timer and repeat the exchange.
458Google identity tokens expire after roughly 1 hour. With a token provider, the SDK calls it again and repeats the exchange automatically before expiry. For shell scripts that run longer than the access token’s `expires_in`, refresh on a timer and repeat the exchange.
459459 
460460## Verify the setup
461461 
from line 467
467467 | jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson'
468468```
469469 
470Check that `iss` is `https://accounts.google.com`, `aud` is `https://api.anthropic.com`, and `email` matches the value in your federation rule. Then run the exchange from the previous section. A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason and see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common Google Cloud-side cause is the `email` claim missing (request the token with `format=full` so it is included).
470Check that `iss` is `https://accounts.google.com`, `aud` is `https://api.anthropic.com`, and `email` matches the value in your federation rule. Then run the exchange from the previous section. A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason. Then see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common Google Cloud-side cause is a missing `email` claim. Request the token with `format=full` so that it includes the claim.
471471 
472472## Scope your rule
473473 
from line 479
479479 
480480* **Match `sub` exactly:** Set the full numeric unique ID in `claims.sub` and never use `subject_prefix` for Google tokens.
481481* **Pin the `email` claim:** Add `claims.email` alongside `sub` so both the stable ID and the readable address must match.
482* **Pin the audience:** Set `audience` to the exact value you request from the metadata server so tokens minted for other consumers are rejected.
482* **Pin the audience:** Set `audience` to the exact value you request from the metadata server so the rule rejects tokens issued for other consumers.
483483* **Pin the project on GKE:** For `format=full` tokens, add a `condition` such as `claims.google.compute_engine.project_id == "my-project"` to restrict the rule to one project’s nodes.
484484 
485485## Next steps

manage-claude/wif-providers/github-actions Changed · +39 / -37 lines

from line 4
44description: Authenticate GitHub Actions workflows to the Claude API with short-lived identity tokens instead of long-lived API keys.
55---
66 
7Every GitHub Actions workflow run can request a signed identity token from GitHub’s hosted issuer at `https://token.actions.githubusercontent.com`. With Workload Identity Federation, your workflow exchanges that token for a short-lived Anthropic access token, so your CI jobs can call the Claude API without an `ANTHROPIC_API_KEY` secret stored in your repository.
7Every GitHub Actions workflow run can request a signed identity token from GitHub’s hosted issuer at `https://token.actions.githubusercontent.com`. With Workload Identity Federation (WIF), your workflow exchanges that token for a short-lived Anthropic access token. Your CI jobs can then call the Claude API without an `ANTHROPIC_API_KEY` secret stored in your repository.
88 
9The token’s `sub` claim encodes the repository and trigger context. For a push to a branch it has the form `repo:<owner>/<repo>:ref:refs/heads/<branch>`. Pull-request runs use `repo:<owner>/<repo>:pull_request`, and environment-gated deployments use `repo:<owner>/<repo>:environment:<name>`. Your federation rule matches against this claim (and others, such as `repository_owner` and `ref`) to determine which workflow runs are allowed to authenticate.
9The token’s `sub` claim encodes the repository and trigger context. For a push to a branch it has the form `repo:<owner>/<repo>:ref:refs/heads/<branch>`. Pull-request runs use `repo:<owner>/<repo>:pull_request`, and environment-gated deployments use `repo:<owner>/<repo>:environment:<name>`. Your federation rule matches against this claim (and others, such as `repository_owner` and `ref`) to determine which workflow runs can authenticate.
1010 
1111## Prerequisites
1212 
from line 25
2525 contents: read
2626```
2727 
28Inside the job, the runner exposes two environment variables: `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN`. Call the request URL with the request token as a bearer credential and your chosen audience as a query parameter, then write the returned JSON Web Token (JWT) to a file:
28Inside the job, the runner exposes two environment variables: `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN`. Call the request URL with the request token as a bearer credential and your chosen audience as a query parameter. Then write the returned JSON Web Token (JWT) to a file:
2929 
3030```yaml
3131- name: Fetch GitHub OIDC token
from line 105
105105}
106106```
107107 
108Be as specific as the workload allows. Loosen `subject_prefix` to `repo:your-org/your-repo:*` (paired with a `claims.ref` constraint) only if the rule must match multiple event types from the same repository, because the trailing segment of `sub` varies among `ref:...`, `environment:...`, and `pull_request` events.
108Be as specific as the workload allows. Loosen `subject_prefix` to `repo:your-org/your-repo:*` (paired with a `claims.ref` constraint) only if the rule must match multiple event types from the same repository. The trailing segment of `sub` varies among `ref:...`, `environment:...`, and `pull_request` events.
109109 
110110## Acquire and use a token
111111 
112Set the federation environment variables on the job. In the SDK, `anthropic.Anthropic()` (typescript: `new Anthropic()`; csharp: `new AnthropicClient()`; go: `anthropic.NewClient()`; java: `AnthropicOkHttpClient.fromEnv()`; php: `new Client()`; ruby: `Anthropic::Client.new`) reads `ANTHROPIC_IDENTITY_TOKEN_FILE`, exchanges the JWT on the first request, and refreshes the access token automatically before it expires.
112Set the federation environment variables on the job, and write GitHub’s OIDC token to the file that `ANTHROPIC_IDENTITY_TOKEN_FILE` names:
113113 
114<CodeGroup>
115 ```yaml Workflow
116 name: Call Claude
117 on: push
114```yaml
115name: Call Claude
116on: push
118117 
119 permissions:
120 id-token: write
121 contents: read
118permissions:
119 id-token: write
120 contents: read
122121 
123 jobs:
124 call-claude:
125 runs-on: ubuntu-latest
126 env:
127 ANTHROPIC_FEDERATION_RULE_ID: fdrl_...
128 ANTHROPIC_ORGANIZATION_ID: 00000000-0000-0000-0000-000000000000
129 ANTHROPIC_SERVICE_ACCOUNT_ID: svac_...
130 ANTHROPIC_WORKSPACE_ID: wrkspc_... # required when the rule covers multiple workspaces
131 ANTHROPIC_IDENTITY_TOKEN_FILE: /tmp/gha-jwt
132 steps:
133 - uses: actions/checkout@v5
134 - name: Fetch GitHub OIDC token
135 run: |
136 curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
137 "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://api.anthropic.com" \
138 | jq -r .value > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
139 - name: Run your script
140 run: |
141 pip install anthropic
142 python your_script.py
143 ```
122jobs:
123 call-claude:
124 runs-on: ubuntu-latest
125 env:
126 ANTHROPIC_FEDERATION_RULE_ID: fdrl_...
127 ANTHROPIC_ORGANIZATION_ID: 00000000-0000-0000-0000-000000000000
128 ANTHROPIC_SERVICE_ACCOUNT_ID: svac_...
129 ANTHROPIC_WORKSPACE_ID: wrkspc_... # required when the rule covers multiple workspaces
130 ANTHROPIC_IDENTITY_TOKEN_FILE: /tmp/gha-jwt
131 steps:
132 - uses: actions/checkout@v5
133 - name: Fetch GitHub OIDC token
134 run: |
135 curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
136 "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://api.anthropic.com" \
137 | jq -r .value > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
138 - name: Run your script
139 run: |
140 pip install anthropic
141 python your_script.py
142```
144143 
144Then call the Claude API from your script. An SDK client that you create without credentials reads `ANTHROPIC_IDENTITY_TOKEN_FILE`, exchanges the JWT on the first request, and refreshes the access token automatically before it expires.
145 
146<CodeGroup>
145147 ```bash cURL
146148 JWT=$(cat /tmp/gha-jwt)
147149 
from line 315
313315 
314316## Verify the setup
315317 
316A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. A denied exchange returns an opaque `401` `authentication_error` with the fixed message `Authentication failed`, whichever check failed. In most cases the deny reason is recorded on the attempt’s entry in the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console. [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange) walks the checks in order. The most common GitHub Actions-side cause is the `sub` claim format not matching (its trailing segment varies among `ref:...`, `environment:...`, and `pull_request` events); the history entry shows reason `match_subject_prefix`.
318A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. A denied exchange returns an opaque `401` `authentication_error` with the fixed message `Authentication failed`, whichever check failed. In most cases, the attempt’s entry on the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console shows the deny reason. [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange) walks through the checks in order. The most common GitHub Actions-side cause is a `sub` claim format that doesn’t match, because its trailing segment varies among `ref:...`, `environment:...`, and `pull_request` events. The history entry then shows the reason `match_subject_prefix`.
317319 
318320## Restrict which workflows can authenticate
319321 

manage-claude/wif-providers/kubernetes Changed · +7 / -7 lines

from line 11
1111```
1212 
1313<Note>
14 The mechanism on this page (projected service account token, cluster API server as the OIDC issuer) is native to Kubernetes itself, so it underlies every Kubernetes distribution. If you run on a managed Kubernetes service, the cloud provider guides walk through where to find the provider-managed issuer URL: [AWS (EKS)](https://platform.claude.com/docs/en/manage-claude/wif-providers/aws#use-eks-projected-service-account-tokens), [Google Cloud (GKE)](https://platform.claude.com/docs/en/manage-claude/wif-providers/gcp), or [Azure (AKS)](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure). If your cluster runs SPIRE, the SPIRE OIDC Discovery Provider is the issuer rather than the cluster API server; see [Use WIF with SPIFFE](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe). For any other distribution or a managed provider not listed there, follow this guide and use the issuer URL your cluster reports.
14 The mechanism on this page is native to Kubernetes itself: the pod gets a projected service account token, and the cluster API server acts as the OIDC issuer. Every Kubernetes distribution uses it. If you run on a managed Kubernetes service, the cloud provider guides walk through where to find the provider-managed issuer URL: [AWS (EKS)](https://platform.claude.com/docs/en/manage-claude/wif-providers/aws#use-eks-projected-service-account-tokens), [Google Cloud (GKE)](https://platform.claude.com/docs/en/manage-claude/wif-providers/gcp), or [Azure (AKS)](https://platform.claude.com/docs/en/manage-claude/wif-providers/azure#use-entra-workload-identity-on-aks). If your cluster runs SPIRE, the SPIRE OIDC Discovery Provider is the issuer rather than the cluster API server. See [Use WIF with SPIFFE](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe). For any other distribution or a managed provider not listed there, follow this guide and use the issuer URL your cluster reports.
1515</Note>
1616 
1717## Prerequisites
1818 
19* Familiarity with [WIF concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
19* Familiarity with [Workload Identity Federation (WIF) concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
2020 
21* A Kubernetes cluster with the [`--service-account-issuer`](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/) flag configured on the API server. Most distributions set this by default; kubeadm clusters typically use `https://kubernetes.default.svc.cluster.local`. Your platform team can confirm the value if you don’t have direct access to the API server configuration.
21* A Kubernetes cluster with the [`--service-account-issuer`](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/) flag configured on the API server. Most distributions set this by default, and kubeadm clusters typically use `https://kubernetes.default.svc.cluster.local`. Your platform team can confirm the value if you don’t have direct access to the API server configuration.
2222 
2323* One of the following so Anthropic can validate token signatures:
2424 
from line 94
9494}
9595```
9696 
97In `inline` mode the `issuer_url` is only compared against the JWT’s `iss` claim; Anthropic never attempts to reach it. If your issuer is publicly reachable, use `"jwks": {"type": "discovery"}` instead.
97In `inline` mode, Anthropic only compares the `issuer_url` against the JWT’s `iss` claim and never attempts to reach it. If your issuer is publicly reachable, use `"jwks": {"type": "discovery"}` instead.
9898 
9999<Warning>
100100 With `inline` keys you are responsible for updating the issuer when the cluster rotates its service account signing key. Rotation is rare (typically only during cluster upgrades), but token exchanges fail with a signature error until you push the new JWKS.
from line 293
293293 
294294## Verify the setup
295295 
296A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason and see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common Kubernetes-side cause is a JWKS key mismatch (for `inline` mode, re-fetch with `kubectl get --raw /openid/v1/jwks` and update the issuer).
296A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason. Then see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common Kubernetes-side cause is a JWKS key mismatch (for `inline` mode, refetch with `kubectl get --raw /openid/v1/jwks` and update the issuer).
297297 
298298## Scope your rule
299299 
from line 304
304304Lock the rule’s `match` block to the narrowest scope that fits your use case:
305305 
306306* **Pin namespace and service-account name:** Use the full `system:serviceaccount:<namespace>:<name>` value with no trailing `*`.
307* **Always set an audience:** Require `audience` on the rule and set the same value on the pod’s `serviceAccountToken` projection so default-audience tokens are rejected.
307* **Always set an audience:** Require `audience` on the rule and set the same value on the pod’s `serviceAccountToken` projection so Anthropic rejects default-audience tokens.
308308* **Use a separate rule for each namespace:** Create a distinct rule and Anthropic service account for each namespace rather than widening one rule.
309309* **Scope inline-JWKS issuers to one cluster:** When several clusters share an issuer URL, register each cluster’s JWKS as its own federation issuer and bind rules to that issuer only.
310310 

manage-claude/wif-providers/okta Changed · +11 / -11 lines

from line 4
44description: Federate Okta service application identities to the Claude API with Workload Identity Federation.
55---
66 
7Okta can act as a workload identity provider by issuing OIDC access tokens to a **service application** through the OAuth 2.0 `client_credentials` grant. Your workload authenticates to Okta (typically with `private_key_jwt`, so no shared secret is stored), receives a signed JSON Web Token (JWT), and exchanges that JWT with Anthropic for a short-lived access token.
7Okta can act as a workload identity provider by issuing OIDC access tokens to a **service application** through the OAuth 2.0 `client_credentials` grant. Your workload authenticates to Okta (typically with `private_key_jwt`, so you store no shared secret) and receives a signed JSON Web Token (JWT). It then exchanges that JWT with Anthropic for a short-lived access token.
88 
99The Okta authorization server’s issuer URL takes the form `https://<your-domain>.okta.com/oauth2/<auth-server-id>`. If you use the built-in default server, the path is `/oauth2/default`.
1010 
1111<Note>
12 You must use an Okta **custom authorization server** (including the `default` one). External parties cannot validate tokens issued directly by the Okta org authorization server (the `/oauth2/v1/token` endpoint with no authorization server ID in the path), because Okta does not publish signing keys for them.
12 You must use an Okta **custom authorization server** (including the `default` one). External parties cannot validate tokens that the Okta org authorization server issues directly, because Okta does not publish signing keys for them. The org authorization server’s token endpoint is `/oauth2/v1/token`, with no authorization server ID in the path.
1313</Note>
1414 
15There are many ways to configure and authenticate to Okta that are outside the scope of this documentation. Ensure that your configuration and authentication mechanisms follow your company’s guidance and security practices.
15This page shows one way to configure and authenticate to Okta. Make sure your configuration and authentication mechanisms follow your company’s guidance and security practices.
1616 
1717## Prerequisites
1818 
19* Familiarity with [WIF concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
19* Familiarity with [Workload Identity Federation (WIF) concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
2020* An Okta organization with API Access Management enabled (required for custom authorization servers).
2121* Permission to create service accounts, federation issuers, and federation rules in the Claude Console for your Anthropic organization.
2222* A workload that can request a token from Okta’s `/v1/token` endpoint and reach `api.anthropic.com`.
from line 31
3131The exact navigation depends on your Okta org configuration and admin console version. The following numbered steps walk through one common path:
3232 
33331. **Create a service app integration.** In the Okta Admin Console, create a new app integration of type **API Services** (OIDC, machine-to-machine). Note the generated **Client ID**.
342. **Configure client authentication.** For a keyless setup, select **Public key / Private key** (`private_key_jwt`) and register your workload’s public JWK. Alternatively, use a client secret if your environment can store one securely. For the following example you might need to disable the DPoP requirement on the application; ensure that your production setup adheres to your organization’s security requirements.
342. **Configure client authentication.** For a keyless setup, select **Public key / Private key** (`private_key_jwt`) and register your workload’s public JWK. Alternatively, use a client secret if your environment can store one securely. For the following example, you might need to disable the Demonstrating Proof of Possession (DPoP) requirement on the application. Make sure your production setup meets your organization’s security requirements.
35353. **Set the audience.** On your custom authorization server, set the audience to `https://api.anthropic.com` so issued access tokens carry that `aud` claim. Anthropic validates `aud` against this fixed value.
364. **Grant a scope.** On your custom authorization server, ensure at least one scope exists that the service app is allowed to request (for example, `anthropic.access`). Okta rejects `client_credentials` requests that do not include a granted scope.
364. **Grant a scope.** On your custom authorization server, ensure at least one scope exists that the service app can request (for example, `anthropic.access`). Okta rejects `client_credentials` requests that do not include a granted scope.
37375. **Create an access policy.** On your custom authorization server, create an access policy with at least one rule that allows your service app to request the scope you granted in step 4.
38386. **(Optional) Add custom claims.** If you want to match on something other than the client ID, add a claim to the access token in your authorization server’s **Claims** tab.
3939 
from line 55
5555}
5656```
5757 
58**Federation rule:** Match on the Okta `sub` claim, which is the service app’s Client ID. If you defined custom claims in Okta, you can match on those instead with the `claims` map or a CEL `condition`.
58**Federation rule:** Match on the Okta `sub` claim, which is the service app’s Client ID. If you defined custom claims in Okta, you can match on those instead with the `claims` map or a Common Expression Language (CEL) `condition`.
5959 
6060```json
6161{
from line 74
7474 
7575## Acquire a token and call the Claude API
7676 
77Unlike platform-native providers (AWS, Google Cloud, Kubernetes), which make a token available inside the workload’s runtime (through a projected file or local metadata endpoint), Okta does not. Your workload must call Okta’s token endpoint to obtain a JWT, then pass that JWT to the Anthropic SDK as the identity token.
77Platform-native providers (AWS, Google Cloud, Kubernetes) make a token available inside the workload’s runtime, through a projected file or local metadata endpoint. Okta does not. Your workload must call Okta’s token endpoint to obtain a JWT, then pass that JWT to the SDK as the identity token.
7878 
7979<CodeGroup>
8080 ```bash cURL
from line 494
494494 ```
495495</CodeGroup>
496496 
497Pass your Okta token to `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`). Except in Java, where `IdentityTokenConfig` takes a token or a file path, that option takes your Okta fetch as a token provider. The Claude SDK calls it each time the Anthropic access token approaches expiry, so your Okta fetcher should return a fresh token on each call rather than caching one indefinitely. The `ant` CLI re-reads `ANTHROPIC_IDENTITY_TOKEN_FILE` on each exchange, so refresh that file on a timer for long-running shells.
497In the SDK, pass your Okta token to `identity_token_provider` (typescript: `identityTokenProvider`; php: `identityProvider`; csharp: `IdentityTokenProvider`; go: `option.WithFederationTokenProvider()`; java: `IdentityTokenConfig`). Where that option takes a token provider, the SDK calls the provider each time the Anthropic access token approaches expiry. The provider should return a fresh token on each call rather than caching one indefinitely. The `ant` CLI rereads `ANTHROPIC_IDENTITY_TOKEN_FILE` on each exchange, so refresh that file on a timer for long-running shells.
498498 
499499## Verify the setup
500500 
501A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason and see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common Okta-side cause is an `issuer_url` mismatch. The `issuer_url` must include the `/oauth2/<auth-server-id>` path, and the Okta org authorization server is not usable.
501A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason. Then see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common Okta-side cause is an `issuer_url` mismatch. The `issuer_url` must include the `/oauth2/<auth-server-id>` path, and the Okta org authorization server is not usable.
502502 
503503## Scope your rule
504504 
from line 509
509509Lock the rule’s `match` block to the narrowest scope that fits your use case:
510510 
511511* **Pin the exact Client ID:** Set `subject_prefix` to the service app’s full Client ID with no trailing `*`.
512* **Pin the audience:** Match the `audience` value you configured on the authorization server so tokens minted for a different audience are rejected.
512* **Pin the audience:** Match the `audience` value you configured on the authorization server so Anthropic rejects tokens issued for a different audience.
513513* **Match on custom claims:** For finer-grained scoping, add claims in the authorization server’s **Claims** tab and match them with the rule’s `claims` map or a CEL `condition`.
514514* **Use one rule for each service app:** Create a separate federation rule for each service app rather than sharing one rule across apps.
515515 

manage-claude/wif-providers/spiffe Changed · +31 / -31 lines

from line 4
44description: Authenticate SPIFFE workloads to the Claude API using JWT-SVIDs from SPIRE or any other SPIFFE-conformant issuer.
55---
66 
7[SPIFFE](https://spiffe.io/) is the CNCF standard for issuing identity to workloads. [SPIRE](https://spiffe.io/docs/latest/spire-about/) is its open-source reference implementation, and several commercial products also issue SPIFFE-conformant identities. Anthropic federates with any SPIFFE implementation that emits OIDC-compatible JWT-SVIDs. For a current list of implementations, see [Commercial software that implements SPIFFE](https://spiffe.io/docs/latest/spiffe-about/overview/#commercial-software-that-implements-spiffe) on the SPIFFE project site.
7[SPIFFE](https://spiffe.io/) is the CNCF standard for issuing identity to workloads. [SPIRE](https://spiffe.io/docs/latest/spire-about/) is its open-source reference implementation, and several commercial products also issue SPIFFE-conformant identities. Anthropic federates with any SPIFFE implementation that emits OIDC-compatible JWT-SVIDs. For a list of implementations, see [Commercial software that implements SPIFFE](https://spiffe.io/docs/latest/spiffe-about/overview/#commercial-software-that-implements-spiffe) on the SPIFFE project site.
88 
9Federation works either through an OIDC discovery document at a public HTTPS URL (`discovery` mode, subject to the [URL constraints](https://platform.claude.com/docs/en/manage-claude/wif-reference#url-fields)) or by registering the JWKS directly (`inline` mode).
9In `discovery` mode, Anthropic reads an OIDC discovery document at a public HTTPS URL, subject to the constraints in [URL fields](https://platform.claude.com/docs/en/manage-claude/wif-reference#url-fields). In `inline` mode, you register the JSON Web Key Set (JWKS) directly.
1010 
11The JWT-SVID spec defines `sub` as the workload’s SPIFFE ID, and the SPIFFE Workload API requires the caller to supply `aud` at fetch time, so those claims are the same across implementations. Anthropic additionally requires `iss` and `iat`, neither of which the JWT-SVID spec mandates, so configure your implementation to populate both (in SPIRE, `iss` is the `jwt_issuer` server setting and `iat` is set automatically). With those in place, the [Configure Anthropic](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#configure-anthropic), [Acquire and use the token](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#acquire-and-use-the-token), and [Scope your rule](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#scope-your-rule) sections of this guide apply to any SPIFFE implementation.
11The JWT-SVID spec defines `sub` as the workload’s SPIFFE ID, and the SPIFFE Workload API requires the caller to supply `aud` at fetch time. Those claims are therefore the same across implementations. Anthropic also requires `iss` and `iat`, and the JWT-SVID spec mandates neither, so configure your implementation to populate both. In SPIRE, `iss` is the `jwt_issuer` server setting, and SPIRE sets `iat` automatically. With those in place, the [Configure Anthropic](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#configure-anthropic), [Acquire and use the token](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#acquire-and-use-the-token), and [Scope your rule](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#scope-your-rule) sections of this guide apply to any SPIFFE implementation.
1212 
13SPIFFE assigns every workload a stable identity URI of the form `spiffe://<trust-domain>/<path>`, and SPIRE issues that identity as a JWT-SVID on demand through the Workload API. A JWT-SVID is an ordinary signed JWT whose `sub` claim is the workload’s SPIFFE ID and whose `aud` claim is supplied by the workload at fetch time.
13SPIFFE assigns every workload a stable identity URI of the form `spiffe://<trust-domain>/<path>`, and SPIRE issues that identity as a JWT-SVID on demand through the Workload API. A JWT-SVID is an ordinary signed JSON Web Token (JWT).
1414 
15The bridge from a SPIRE trust domain to standard OIDC is the [SPIRE OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md), a standalone helper that publishes `/.well-known/openid-configuration` and a JWKS endpoint for the trust domain’s JWT signing keys. With the discovery provider running, a JWT-SVID validates like any other OIDC token: register the discovery URL as a federation issuer, write a federation rule that matches the workload’s SPIFFE ID, and have the workload present its JWT-SVID to Anthropic’s token-exchange endpoint.
15The [SPIRE OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md) connects a SPIRE trust domain to standard OIDC. This standalone helper publishes `/.well-known/openid-configuration` and a JWKS endpoint for the trust domain’s JWT signing keys. With the discovery provider running, a JWT-SVID validates like any other OIDC token. Register the discovery URL as a federation issuer and write a federation rule that matches the workload’s SPIFFE ID. Then have the workload present its JWT-SVID to Anthropic’s token-exchange endpoint.
1616 
1717This page’s examples use SPIRE and apply anywhere SPIRE Agent runs: Kubernetes pods, virtual machines, and bare-metal hosts.
1818 
from line 22
2222 
2323## Prerequisites
2424 
25* Familiarity with [WIF concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
26* A SPIFFE deployment with workload identities issued (the examples on this page use SPIRE Server and Agent), and registration entries for the workloads that need to call the Claude API.
25* Familiarity with [Workload Identity Federation (WIF) concepts](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#concepts): service accounts, federation issuers, and federation rules.
26* A SPIFFE deployment with workload identities issued, and registration entries for the workloads that need to call the Claude API. The examples on this page use SPIRE Server and Agent.
2727* An OIDC discovery endpoint for the trust domain (in SPIRE, the [OIDC Discovery Provider](https://github.com/spiffe/spire/blob/main/support/oidc-discovery-provider/README.md)) running with a publicly reachable HTTPS endpoint, or the JWKS exported for `inline` registration.
28* Your SPIFFE issuer configured to set the `iss` claim on JWT-SVIDs to the value you will register as the federation issuer’s `issuer_url`. For `discovery` mode, this is the discovery endpoint’s public URL (in SPIRE, the `jwt_issuer` server setting).
28* Your SPIFFE issuer configured to set the `iss` claim on JWT-SVIDs to the value you register as the federation issuer’s `issuer_url`. For `discovery` mode, this is the discovery endpoint’s public URL (in SPIRE, the `jwt_issuer` server setting).
2929* JWT-SVIDs available to your workloads. WIF accepts JWT-SVIDs only, not X.509-SVIDs.
3030* Permission to create service accounts, federation issuers, and federation rules in the Claude Console for your Anthropic organization.
3131 
from line 38
3838If you already run SPIRE with the OIDC Discovery Provider, federating with Anthropic requires three things on the SPIRE side:
3939 
4040* A `jwt_issuer` that matches the discovery URL
41* A registration entry for the workload that will call the Claude API
41* A registration entry for the workload that calls the Claude API
4242* A way for that workload to fetch a JWT-SVID with the Anthropic audience
4343 
4444The following subsections walk through each. The configuration snippets show only the settings relevant to Anthropic federation, not complete SPIRE deployment configs.
from line 49
4949 
5050### Verify the JWT issuer
5151 
52Anthropic validates a JWT-SVID by matching its `iss` claim against a registered federation issuer and fetching the JWKS from that issuer’s discovery document. Two SPIRE settings must agree on the same URL: SPIRE Server’s `jwt_issuer` (which becomes the `iss` claim in every minted JWT-SVID) and the OIDC Discovery Provider’s `domains` list (which determines the host the discovery document and JWKS are served from). That shared URL is what you register with Anthropic.
52Anthropic validates a JWT-SVID by matching its `iss` claim against a registered federation issuer and fetching the JWKS from that issuer’s discovery document. Two SPIRE settings must agree on the same URL. SPIRE Server’s `jwt_issuer` becomes the `iss` claim in every issued JWT-SVID. The OIDC Discovery Provider’s `domains` list determines the host that serves the discovery document and JWKS. That shared URL is what you register with Anthropic.
5353 
5454The trust domain and the issuer URL are independent. The trust domain (`spiffe://prod.example.com`) scopes the `sub` claim. The issuer URL (`https://oidc-discovery.prod.example.com`) is where Anthropic fetches signing keys. They do not need to share a hostname.
5555 
56Confirm `jwt_issuer` is set in SPIRE Server’s configuration and points at the discovery provider’s public URL. The following example also shows a default JWT-SVID lifetime. SPIRE’s built-in default is 5 minutes, which is short enough that continuous rotation is required (see [Run spiffe-helper](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#run-spiffe-helper)). Anthropic’s token-exchange endpoint rejects any identity token whose lifetime exceeds the federation issuer’s configured maximum, which is 1 hour by default (see [Validation rules](https://platform.claude.com/docs/en/manage-claude/wif-reference#validation-rules)). This check applies to every SPIFFE implementation, not only SPIRE, so keep `default_jwt_svid_ttl` (or any per-entry override) at or below that maximum.
56Confirm `jwt_issuer` is set in SPIRE Server’s configuration and points at the discovery provider’s public URL. The following example also shows a default JWT-SVID lifetime. SPIRE’s built-in default is 5 minutes, which is short enough to require continuous rotation (see [Run spiffe-helper](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#run-spiffe-helper)). Anthropic’s token-exchange endpoint rejects any identity token whose lifetime exceeds the federation issuer’s configured maximum, which is 1 hour by default (see [Validation rules](https://platform.claude.com/docs/en/manage-claude/wif-reference#validation-rules)). This check applies to every SPIFFE implementation, not only SPIRE, so keep `default_jwt_svid_ttl` (or any override on a registration entry) at or below that maximum.
5757 
5858```text server.conf
5959server {
from line 64
6464}
6565```
6666 
67In the OIDC Discovery Provider’s configuration, the same hostname must appear under `domains`, and the provider must be able to reach SPIRE Server’s API socket. The provider serves the discovery document and JWKS over HTTPS. Terminate TLS with its built-in ACME support, or front it with a load balancer that does.
67In the OIDC Discovery Provider’s configuration, the same hostname must appear under `domains`, and the provider must be able to reach SPIRE Server’s API socket. The provider serves the discovery document and JWKS over HTTPS. Terminate TLS with its built-in ACME support, or put it behind a load balancer that does.
6868 
6969```text oidc-discovery-provider.conf
7070domains = ["oidc-discovery.prod.example.com"]
from line 105
105105 
106106### Run spiffe-helper
107107 
108[spiffe-helper](https://github.com/spiffe/spiffe-helper) is a sidecar utility that connects to the SPIRE Agent socket, fetches a JWT-SVID for a given audience, writes it to a file, and re-fetches it before expiry. The helper runs in daemon mode by default. The following example sets `daemon_mode = true` explicitly.
108[spiffe-helper](https://github.com/spiffe/spiffe-helper) is a sidecar utility that connects to the SPIRE Agent socket, fetches a JWT-SVID for a given audience, writes it to a file, and refetches it before expiry. The helper runs in daemon mode by default. The following example sets `daemon_mode = true` explicitly.
109109 
110110```text helper.conf
111111agent_address = "/run/spire/sockets/agent.sock"
from line 119
119119}]
120120```
121121 
122In Kubernetes, run spiffe-helper as a sidecar container that shares a memory-backed `emptyDir` volume (`medium: Memory`) with your application container so the bearer SVID never lands on the node’s disk. Mount the SPIRE Agent socket from the host into the sidecar, mount the shared volume at `/var/run/secrets/anthropic.com` in both containers, and set `ANTHROPIC_IDENTITY_TOKEN_FILE=/var/run/secrets/anthropic.com/token` on the application container. On VMs and bare metal, run spiffe-helper as a system service alongside the workload and point both at a shared directory.
122In Kubernetes, run spiffe-helper as a sidecar container that shares a memory-backed `emptyDir` volume (`medium: Memory`) with your application container. The bearer SVID then never reaches the node’s disk. Mount the SPIRE Agent socket from the host into the sidecar, mount the shared volume at `/var/run/secrets/anthropic.com` in both containers, and set `ANTHROPIC_IDENTITY_TOKEN_FILE=/var/run/secrets/anthropic.com/token` on the application container. On VMs and bare metal, run spiffe-helper as a system service alongside the workload and point both at a shared directory.
123123 
124124## Configure Anthropic
125125 
from line 137
137137}
138138```
139139 
140If the discovery provider is not reachable from the public internet, fetch the JWKS yourself (`curl https://oidc-discovery.prod.example.com/keys`) and register the issuer with `"jwks": {"type": "inline", "keys": [...]}` using the contents of the returned `keys` array. In `inline` mode the `issuer_url` is only compared against the JWT-SVID’s `iss` claim. Anthropic never attempts to reach it.
140If the discovery provider is not reachable from the public internet, fetch the JWKS yourself (`curl https://oidc-discovery.prod.example.com/keys`). Then register the issuer with `"jwks": {"type": "inline", "keys": [...]}`, using the contents of the returned `keys` array. In `inline` mode, Anthropic only compares the `issuer_url` against the JWT-SVID’s `iss` claim and never attempts to reach it.
141141 
142142<Warning>
143 SPIRE rotates JWT signing keys frequently, by default on the same cadence as the CA (`ca_ttl`, 24 hours). If you register the issuer with an inline JWKS instead of a discovery URL, you must update the JWKS every time SPIRE rotates: add the new key before workloads start presenting it, and **remove superseded keys** once tokens signed with them have expired. Stale keys left in an inline JWKS remain trusted indefinitely.
143 SPIRE rotates JWT signing keys frequently, by default on the same schedule as the CA (`ca_ttl`, 24 hours). If you register the issuer with an inline JWKS instead of a discovery URL, you must update the JWKS every time SPIRE rotates. Add the new key before workloads start presenting it, and **remove superseded keys** once tokens signed with them have expired. Stale keys left in an inline JWKS remain trusted indefinitely.
144144</Warning>
145145 
146To automate JWKS updates without exposing a public discovery endpoint, configure a SPIRE Server [BundlePublisher](https://spiffe.io/docs/latest/deploying/spire_server/#built-in-plugins) plugin (`aws_s3`, `gcp_cloudstorage`, or `k8s_configmap`) with `format = "jwks"` to push the JWT signing keys to external storage on every rotation, then update the issuer’s inline keys through the [Admin API](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#federation-issuers).
146To automate JWKS updates without exposing a public discovery endpoint, configure a SPIRE Server [BundlePublisher](https://spiffe.io/docs/latest/deploying/spire_server/#built-in-plugins) plugin (`aws_s3`, `gcp_cloudstorage`, or `k8s_configmap`) with `format = "jwks"`. The plugin pushes the JWT signing keys to external storage on every rotation. Then update the issuer’s inline keys through the Admin API. See [Federation issuers](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#federation-issuers).
147147 
148**Federation rule:** Match the JWT-SVID’s `sub` (the SPIFFE ID) and the `aud` you configured spiffe-helper to request. SPIFFE IDs are URI strings and `subject_prefix` matches them as opaque text, so an exact value or a trailing-`*` prefix match both work against them. For more complex patterns, use a CEL `condition`.
148**Federation rule:** Match the JWT-SVID’s `sub` (the SPIFFE ID) and the `aud` you configured spiffe-helper to request. SPIFFE IDs are URI strings and `subject_prefix` matches them as opaque text, so an exact value or a trailing-`*` prefix match both work against them. For more complex patterns, use a Common Expression Language (CEL) `condition`.
149149 
150150```json
151151{
from line 171
171171 
172172## Acquire and use the token
173173 
174The Claude SDK can read the JWT-SVID from the file that spiffe-helper maintains or, except in Java, call the SPIFFE Workload API directly through a token provider. The file path is the simplest integration and works in every SDK language. The token-provider path removes the sidecar but requires a SPIFFE Workload API client in your application’s language.
174The SDK can read the JWT-SVID from the file that spiffe-helper maintains or, except in Java, call the SPIFFE Workload API directly through a token provider. The file path takes the least code, and the SDK supports it in every language. The token-provider path removes the sidecar but requires a SPIFFE Workload API client in your application’s language.
175175 
176176<Tabs>
177177 <Tab title="File-based with spiffe-helper">
178 With spiffe-helper writing a fresh JWT-SVID to `/var/run/secrets/anthropic.com/token`, set `ANTHROPIC_IDENTITY_TOKEN_FILE` to that path along with `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, and `ANTHROPIC_WORKSPACE_ID`. The SDK reads the file on every token exchange, so it always picks up the most recently rotated SVID, and refreshes the Anthropic access token automatically before it expires. See [Environment variables](https://platform.claude.com/docs/en/manage-claude/wif-reference#environment-variables) for where each value comes from.
178 With spiffe-helper writing a fresh JWT-SVID to `/var/run/secrets/anthropic.com/token`, set `ANTHROPIC_IDENTITY_TOKEN_FILE` to that path. Also set the other federation environment variables that the following sample reads. The SDK reads the file on every token exchange, so it always picks up the most recently rotated SVID. It also refreshes the Anthropic access token automatically before it expires. See [Environment variables](https://platform.claude.com/docs/en/manage-claude/wif-reference#environment-variables) for where each value comes from.
179179 
180180 <CodeGroup>
181181 ```bash cURL
from line 350
350350 </Tab>
351351 
352352 <Tab title="Token provider through the SPIFFE Workload API">
353 Except in Java, workloads that link a SPIFFE Workload API client directly can skip spiffe-helper and pass the SDK a token provider that fetches a fresh JWT-SVID from the agent socket. The SDK calls the provider before each token exchange, so the workload always presents an unexpired SVID. Python ([py-spiffe](https://github.com/HewlettPackard/py-spiffe)) and Go ([go-spiffe](https://github.com/spiffe/go-spiffe)) have mature Workload API clients.
353 Except in Java, workloads that link a SPIFFE Workload API client directly can skip spiffe-helper. They pass the SDK a token provider that fetches a fresh JWT-SVID from the agent socket. The SDK calls the provider before each token exchange, so the workload always presents an unexpired SVID. Python ([py-spiffe](https://github.com/HewlettPackard/py-spiffe)) and Go ([go-spiffe](https://github.com/spiffe/go-spiffe)) have mature Workload API clients.
354354 
355355 <CodeGroup exclude="shell, typescript, java, csharp, php, ruby">
356356 ```python Python
from line 446
446446 </CodeGroup>
447447 
448448 <Note>
449 For other languages, fetch the JWT-SVID with your runtime’s SPIFFE Workload API client (or shell out to `spire-agent api fetch jwt`), write it to a file, and set `ANTHROPIC_IDENTITY_TOKEN_FILE` to that path as in the file-based tab.
449 For other languages, fetch the JWT-SVID with your runtime’s SPIFFE Workload API client (or run `spire-agent api fetch jwt`) and write it to a file. Then set `ANTHROPIC_IDENTITY_TOKEN_FILE` to that path, as in the file-based tab.
450450 </Note>
451451 </Tab>
452452</Tabs>
from line 468
468468 | jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson'
469469```
470470 
471The `-output json` flag returns the SVID response and bundle response as a two-element JSON array, so `jq -r '.[0].svids[0].svid'` extracts the bare token. On older SPIRE versions without `-output`, the command prints a labeled block instead. In that case, pipe the default output through `awk '/^[[:space:]]*eyJ/{print $1; exit}'` to extract the token line. Check that `iss` is the OIDC Discovery Provider URL you registered, `sub` is the workload’s SPIFFE ID, and `aud` contains `https://api.anthropic.com`. Then run the sample in [Acquire and use the token](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#acquire-and-use-the-token). A successful exchange returns an `access_token` starting with `sk-ant-oat01-`. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason and see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common SPIRE-side cause is a mismatch between SPIRE Server’s `jwt_issuer` and the URL registered as the federation issuer.
471The `-output json` flag returns the SVID response and bundle response as a two-element JSON array, so `jq -r '.[0].svids[0].svid'` extracts the bare token. If your SPIRE version has no `-output` flag, the command prints a labeled block instead. In that case, pipe the default output through `awk '/^[[:space:]]*eyJ/{print $1; exit}'` to extract the token line. Check that `iss` is the OIDC Discovery Provider URL you registered, `sub` is the workload’s SPIFFE ID, and `aud` contains `https://api.anthropic.com`. Then run the sample in [Acquire and use the token](https://platform.claude.com/docs/en/manage-claude/wif-providers/spiffe#acquire-and-use-the-token). A successful exchange returns an `access_token` starting with `sk-ant-oat01-`. If the exchange fails with the opaque `401` `authentication_error` response (message `Authentication failed`), check the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console for the deny reason. Then see [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange). The most common SPIRE-side cause is a mismatch between SPIRE Server’s `jwt_issuer` and the URL you registered as the federation issuer.
472472 
473473## Scope your rule
474474 
from line 475
475475SPIFFE ID path conventions are operator-defined, so the federation rule’s `subject_prefix` matcher should reflect the path scheme your registration entries use. Common schemes include `spiffe://<trust-domain>/ns/<namespace>/sa/<service-account>` (the default emitted by the `ClusterSPIFFEID` resource in spire-controller-manager) and `spiffe://<trust-domain>/host/<hostname>/<service>` for VM and bare-metal workloads.
476476 
477477<Warning>
478 A `subject_prefix` of `spiffe://prod.example.com/*` matches every workload in the trust domain. Without an `audience` matcher, the rule also accepts JWT-SVIDs minted for any audience, including ones the workload requested for unrelated relying parties.
478 A `subject_prefix` of `spiffe://prod.example.com/*` matches every workload in the trust domain. Without an `audience` matcher, the rule also accepts JWT-SVIDs issued for any audience, including ones the workload requested for unrelated relying parties.
479479</Warning>
480480 
481481Lock the rule’s `match` block to the narrowest scope that fits your use case:
482482 
483483* **Pin to one workload:** Set `subject_prefix` to the full SPIFFE ID with no trailing `*`.
484* **Always set an audience:** Require `audience` on the rule and configure spiffe-helper (or the Workload API call) with the same value so SVIDs minted for other relying parties are rejected.
485* **Scope by path segment:** Use `spiffe://prod.example.com/ns/inference/*` to grant every workload registered under a namespace, and create a separate rule and Anthropic service account for each namespace rather than widening one rule.
484* **Always set an audience:** Require `audience` on the rule and configure spiffe-helper (or the Workload API call) with the same value so Anthropic rejects SVIDs issued for other relying parties.
485* **Scope by path segment:** Use `spiffe://prod.example.com/ns/inference/*` to match every workload registered under a namespace. Create a separate rule and Anthropic service account for each namespace rather than widening one rule.
486486* **Register one issuer for each trust domain:** Each SPIRE trust domain has its own signing keys and OIDC Discovery Provider. Register each as a separate federation issuer and bind rules to the issuer that owns the SPIFFE IDs they match.
487487 
488488## Next steps

manage-claude/wif-reference Changed · +86 / -86 lines

from line 4
44description: Environment variables, validation rules, profile configuration, and error reference for Workload Identity Federation.
55---
66 
7This page collects the configuration surfaces, validation constraints, and error mappings for [Workload Identity Federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation). For setup walkthroughs, see the [provider guides](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#identity-providers).
7This page collects the configuration surfaces, validation constraints, and error mappings for [Workload Identity Federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation) (WIF). For setup walkthroughs, see [Identity providers](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#identity-providers).
88 
99## Token exchange request
1010 
from line 17
1717| `federation_rule_id` | Yes | Tagged ID (`fdrl_...`) of the federation rule to evaluate. |
1818| `organization_id` | Yes | UUID of your Anthropic organization. |
1919| `service_account_id` | Yes | Tagged ID (`svac_...`) of the target service account. |
20| `workspace_id` | Conditional | Tagged ID (`wrkspc_...`) of the workspace to scope the minted token to. Required when the rule is enabled for more than one workspace. When omitted, the server selects the rule’s sole enabled workspace. The literal `default` also works for the organization’s Default Workspace but is deprecated; use that workspace’s `wrkspc_...` ID. |
20| `workspace_id` | Conditional | Tagged ID (`wrkspc_...`) of the workspace to scope the minted token to. Required when the rule is enabled for more than one workspace. When omitted, the server selects the rule’s sole enabled workspace. The literal `default` also works for the organization’s Default Workspace but is deprecated. Use that workspace’s `wrkspc_...` ID. |
2121 
2222## Token exchange response
2323 
from line 34
3434 
3535The SDK reads these variables to perform a federated token exchange with no constructor arguments.
3636 
37| Variable | Required | Description | Example |
38| ------------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
39| `ANTHROPIC_FEDERATION_RULE_ID` | Yes | Tagged ID of the federation rule to evaluate. | `fdrl_...` |
40| `ANTHROPIC_ORGANIZATION_ID` | Yes | UUID of your Anthropic organization. Find it on the [Organization](https://platform.claude.com/settings/organization) page (`platform.claude.com/settings/organization`) in the Claude Console. | `00000000-0000-0000-0000-000000000000` |
41| `ANTHROPIC_IDENTITY_TOKEN_FILE` | One of `_TOKEN_FILE` or `_TOKEN` | Filesystem path to the JWT issued by your identity provider (IdP). The SDK re-reads this file on every exchange so that projected tokens that rotate on disk are always current. | `/var/run/secrets/anthropic.com/token` |
42| `ANTHROPIC_IDENTITY_TOKEN` | One of `_TOKEN_FILE` or `_TOKEN` | The literal JWT as a string. Use when your platform injects the token as an environment variable rather than a file. | `eyJhbGciOiJSUzI1NiIs...` |
43| `ANTHROPIC_SERVICE_ACCOUNT_ID` | Yes | Tagged ID of the target Anthropic service account that the issued access token acts as. | `svac_...` |
44| `ANTHROPIC_WORKSPACE_ID` | Conditional | Tagged ID of the workspace to scope the minted token to. Required when the federation rule is enabled for more than one workspace; optional when the rule is bound to a single workspace. The minted token is scoped to this workspace at exchange time, so switching workspaces requires a new exchange. Without a profile, the `ant` CLI does not pass this variable into the exchange, so set `workspace_id` in a federation profile and set `ANTHROPIC_PROFILE` to its name. The literal `default` also works for the Default Workspace but is deprecated; use its `wrkspc_...` ID. | `wrkspc_...` |
45| `ANTHROPIC_PROFILE` | No | Name of a [configuration profile](https://platform.claude.com/docs/en/manage-claude/wif-reference#profile-configuration-file) to load. Takes precedence over the federation environment variables in this table. | `staging-profile` |
37| Variable | Required | Description | Example |
38| ------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
39| `ANTHROPIC_FEDERATION_RULE_ID` | Yes | Tagged ID of the federation rule to evaluate. | `fdrl_...` |
40| `ANTHROPIC_ORGANIZATION_ID` | Yes | UUID of your Anthropic organization. Find it on the [Organization](https://platform.claude.com/settings/organization) page (`platform.claude.com/settings/organization`) in the Claude Console. | `00000000-0000-0000-0000-000000000000` |
41| `ANTHROPIC_IDENTITY_TOKEN_FILE` | One of `_TOKEN_FILE` or `_TOKEN` | Filesystem path to the JWT issued by your identity provider (IdP). The SDK rereads this file on every exchange so that projected tokens that rotate on disk are always current. | `/var/run/secrets/anthropic.com/token` |
42| `ANTHROPIC_IDENTITY_TOKEN` | One of `_TOKEN_FILE` or `_TOKEN` | The literal JWT as a string. Use when your platform injects the token as an environment variable rather than a file. | `eyJhbGciOiJSUzI1NiIs...` |
43| `ANTHROPIC_SERVICE_ACCOUNT_ID` | Yes | Tagged ID of the target Anthropic service account that the issued access token acts as. | `svac_...` |
44| `ANTHROPIC_WORKSPACE_ID` | Conditional | Tagged ID of the workspace to scope the minted token to. Required when the federation rule is enabled for more than one workspace. Optional when the rule is bound to a single workspace. The exchange scopes the minted token to this workspace, so switching workspaces requires a new exchange. Without a profile, the `ant` CLI does not pass this variable into the exchange. With the `ant` CLI, set `workspace_id` in a federation profile and set `ANTHROPIC_PROFILE` to its name. The literal `default` also works for the Default Workspace but is deprecated. Use its `wrkspc_...` ID. | `wrkspc_...` |
45| `ANTHROPIC_PROFILE` | No | Name of a [configuration profile](https://platform.claude.com/docs/en/manage-claude/wif-reference#profile-configuration-file) to load. Takes precedence over the federation environment variables in this table. | `staging-profile` |
4646 
47The direct environment-variable federation path activates only when `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, and one of `ANTHROPIC_IDENTITY_TOKEN_FILE` or `ANTHROPIC_IDENTITY_TOKEN` are all set. `ANTHROPIC_WORKSPACE_ID` is read alongside but does not gate activation.
47The direct environment-variable federation path activates only when `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, and one of `ANTHROPIC_IDENTITY_TOKEN_FILE` or `ANTHROPIC_IDENTITY_TOKEN` are all set. The SDK also reads `ANTHROPIC_WORKSPACE_ID`, but this path activates with or without it.
4848 
4949<Warning>
50 A variable that is set to an empty string can still occupy its slot in the credential precedence chain. Unset unused credential variables rather than blanking them.
50 A variable that is set to an empty string can occupy its slot in the credential precedence chain. Unset unused credential variables rather than blanking them.
5151</Warning>
5252 
5353### Credential precedence
from line 54
5454 
5555The SDK resolves credentials in this order. The first source that yields a credential wins.
5656 
57| Order | Source | Notes |
58| ----- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
59| 1 | Constructor argument (`api_key=`, `auth_token=`, `credentials=`) | Always overrides everything else. |
60| 2 | `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN` | Shadows federation entirely. Unset these when migrating from API keys. |
61| 3 | `ANTHROPIC_PROFILE` | Loads `<config_dir>/configs/<name>.json`. A missing named profile is an error, not a fall-through. |
62| 4 | Federation environment variables | `ANTHROPIC_FEDERATION_RULE_ID` + `ANTHROPIC_ORGANIZATION_ID` + `ANTHROPIC_SERVICE_ACCOUNT_ID` + `ANTHROPIC_IDENTITY_TOKEN[_FILE]`. |
63| 5 | Active profile | Resolved from `<config_dir>/active_config`, falling back to a profile named `default`. |
57| Order | Source | Notes |
58| ----- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
59| 1 | Constructor argument (API key, auth token, or credentials) | Always overrides everything else. |
60| 2 | `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN` | Overrides federation entirely. Unset these when migrating from API keys. |
61| 3 | `ANTHROPIC_PROFILE` | Loads `<config_dir>/configs/<name>.json`. If the named profile is missing, the SDK reports an error instead of trying the next source. |
62| 4 | Federation environment variables | `ANTHROPIC_FEDERATION_RULE_ID` + `ANTHROPIC_ORGANIZATION_ID` + `ANTHROPIC_SERVICE_ACCOUNT_ID` + `ANTHROPIC_IDENTITY_TOKEN[_FILE]`. |
63| 5 | Active profile | Resolved from `<config_dir>/active_config`, falling back to a profile named `default`. |
6464 
6565In the `ant` CLI, the settings for [Claude Models on Google Cloud (Anthropic managed)](https://platform.claude.com/docs/en/build-with-claude/claude-models-on-google-cloud/anthropic-managed#authentication) rank after the federation environment variables and before the active profile. The settings are the project, the workspace ID, and the location. You set them with the `--google-cloud-*` flags or the `ANTHROPIC_GOOGLE_CLOUD_*` variables. The CLI uses these settings when any one of them is set. With these settings, the CLI gets its credential from Google Application Default Credentials.
6666 
from line 90
9090 
9191### File layout
9292 
93| Path | Contents | Sensitivity |
94| ----------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------- |
95| `<config_dir>/configs/<profile>.json` | `version`, the `authentication` block, `organization_id`, `workspace_id`, and `base_url`. | Non-secret. Safe to commit or bake into an image. |
96| `<config_dir>/credentials/<profile>.json` | `version`, the cached `access_token`, `expires_at`, and (for interactive login) `refresh_token`. | Secret. Written by the SDK with mode `0600`. |
93| Path | Contents | Sensitivity |
94| ----------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------- |
95| `<config_dir>/configs/<profile>.json` | `version`, the `authentication` block, `organization_id`, `workspace_id`, and `base_url`. | Non-secret. Safe to commit or build into an image. |
96| `<config_dir>/credentials/<profile>.json` | `version`, the cached `access_token`, `expires_at`, and (for interactive login) `refresh_token`. | Secret. The SDK writes this file with mode `0600`. |
9797 
9898Both the config file and the credentials file carry a top-level string `version` field in `major.minor` format, such as `"1.0"`. The SDK writes this field automatically. If you omit it when authoring a config by hand, the SDK treats the file as the current version.
9999 
from line 117
117117}
118118```
119119 
120If `authentication.identity_token` is omitted, the SDK falls back to `ANTHROPIC_IDENTITY_TOKEN_FILE` or `ANTHROPIC_IDENTITY_TOKEN` from the environment.
120If you omit `authentication.identity_token`, the SDK falls back to `ANTHROPIC_IDENTITY_TOKEN_FILE` or `ANTHROPIC_IDENTITY_TOKEN` from the environment.
121121 
122122## OAuth scopes
123123 
from line 128
128128| `workspace:developer` | All non-administrative Claude API endpoints in the rule’s workspace: [Messages](https://platform.claude.com/docs/en/api/messages) (including streaming and token counting), [Models](https://platform.claude.com/docs/en/api/models/list), [Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) and their sessions, [Files](https://platform.claude.com/docs/en/build-with-claude/files), and [Skills](https://platform.claude.com/docs/en/build-with-claude/skills-guide). This matches the access a workspace API key in the same workspace has. |
129129| `workspace:inference` | The inference endpoints in the rule’s workspace: [Messages](https://platform.claude.com/docs/en/api/messages) (including streaming and token counting), [Models](https://platform.claude.com/docs/en/api/models/list), and the [OpenAI-compatible chat endpoint](https://platform.claude.com/docs/en/cli-sdks-libraries/libraries/openai-sdk). Use this for workloads that only need to call Claude and never need to manage Files, Skills, or other resources. |
130130| `workspace:manage_tunnels` | The [MCP tunnels API](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/reference#tunnels-api): create, list, and get tunnels, register and archive CA certificates, reveal and rotate the tunnel token, and archive tunnels. The Console’s create-tunnel modal window locks this scope when you create a rule from it. |
131| `org:admin` | Full access to the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api) (organization members, invites, workspaces, API keys, and the rest). An OAuth `org:admin` token can only create or modify rules scoped to `workspace:developer` or `workspace:inference`, and cannot update an issuer that backs a rule with any other scope; see [Permissions and constraints](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#permissions-and-constraints). |
131| `org:admin` | Full access to the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api) (organization members, invites, workspaces, API keys, and the rest). An OAuth `org:admin` token can only create or modify rules scoped to `workspace:developer` or `workspace:inference`. It cannot update an issuer that backs a rule with any other scope. See [Permissions and constraints](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#permissions-and-constraints). |
132132 
133133A request to an endpoint outside the token’s scope returns HTTP 403. Finer-grained scopes (by resource, or read versus write) are not available.
134134 
135135### Permission boundaries
136136 
137A federation rule’s `oauth_scope` is a ceiling: the minted token can never exceed it. The target service account’s `organization_role` (`developer` or `admin`) determines which scopes are grantable, so a rule that grants `org:admin` must target a service account with `organization_role=admin`. Effective permissions are the intersection of the rule’s scope and the service account’s role.
137A federation rule’s `oauth_scope` is a ceiling: the minted token can never exceed it. The target service account’s `organization_role` (`developer` or `admin`) determines which scopes a rule can grant. A rule that grants `org:admin` must target a service account with `organization_role=admin`. Effective permissions are the intersection of the rule’s scope and the service account’s role.
138138 
139139| Rule `oauth_scope` | Service account `organization_role` | Effective permissions |
140140| --------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
141141| `workspace:developer` | `admin` | Claude API access in the rule’s workspace only. The scope caps the token below the role. |
142| `org:admin` | `admin` | Full Admin API access (organization members, invites, workspaces, API keys, and the rest), minus the OAuth-caller exceptions; see [Permissions and constraints](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#permissions-and-constraints). |
142| `org:admin` | `admin` | Full Admin API access (organization members, invites, workspaces, API keys, and the rest), minus the OAuth-caller exceptions. See [Permissions and constraints](https://platform.claude.com/docs/en/manage-claude/wif-admin-api#permissions-and-constraints). |
143143 
144144## Validation rules
145145 
146Anthropic enforces these constraints when you create or update issuers and rules, and when verifying an incoming JWT at exchange time.
146Anthropic enforces these constraints when you create or update issuers and rules, and when it verifies an incoming JWT at exchange time.
147147 
148148For complete parameter details and response schemas, see the [Service accounts API reference](https://platform.claude.com/docs/en/api/organization/service_accounts), [Federation issuers API reference](https://platform.claude.com/docs/en/api/organization/federation/issuers), and [Federation rules API reference](https://platform.claude.com/docs/en/api/organization/federation/rules).
149149 
from line 153
153153| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
154154| Issuer, rule, and service account `name` | Must match `^[a-z0-9-]+$`, length 1 to 255 characters. |
155155| `workspace_id` | Required on create unless `applies_to_all_workspaces` is true. The workspace (`wrkspc_...`) whose quota, billing, and rate limits apply to tokens minted under this rule. Must be a workspace in the same organization, and the target service account must be a member of that workspace. |
156| `applies_to_all_workspaces` | Boolean. Set `true` to enable the rule in every workspace in the organization instead of naming one; either this or `workspace_id` is required on create. |
157| `token_lifetime_seconds` | Integer between `60` and `86400` (1 minute to 24 hours). Default `3600`. Values outside this range are rejected at request time. See [Token lifetime and refresh](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#token-lifetime-and-refresh). |
156| `applies_to_all_workspaces` | Boolean. Set `true` to enable the rule in every workspace in the organization instead of naming one. Either this or `workspace_id` is required on create. |
157| `token_lifetime_seconds` | Integer between `60` and `86400` (1 minute to 24 hours). Default `3600`. Anthropic rejects values outside this range at request time. See [Token lifetime and refresh](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#token-lifetime-and-refresh). |
158158 
159159### URL fields
160160 
161The `issuer_url`, `jwks.discovery_base`, and `jwks.url` fields are validated:
161Anthropic validates the `issuer_url`, `jwks.discovery_base`, and `jwks.url` fields:
162162 
163| Constraint | Detail |
164| ---------- | ------------------------------------------------------------------------------------------------------------------------ |
165| Scheme | Must be `https`. |
166| Port | Must be `443` (explicit or default). |
167| Host | Must be a public DNS hostname for your OIDC provider. Must resolve to public IP addresses; IP literals are not accepted. |
163| Constraint | Detail |
164| ---------- | --------------------------------------------------------------------------------------------------------------------------------- |
165| Scheme | Must be `https`. |
166| Port | Must be `443` (explicit or default). |
167| Host | Must be a public DNS hostname for your OIDC provider. Must resolve to public IP addresses. Anthropic does not accept IP literals. |
168168 
169169URL validation failures return `400 invalid_request_error` with the field name as a prefix on the error message (for example, `issuer_url: url must use https scheme`).
170170 
171171<Note>
172 URL constraints apply only to URLs that Anthropic dials. In `explicit_url` and `inline` JWKS modes, and in `discovery` mode when `jwks.discovery_base` is set, the `issuer_url` is compared against the JWT `iss` claim as a string and is never fetched, so it may reference an internal hostname or non-standard port.
172 URL constraints apply only to URLs that Anthropic connects to. Anthropic never fetches the `issuer_url` in `explicit_url` and `inline` JSON Web Key Set (JWKS) modes, or in `discovery` mode when `jwks.discovery_base` is set. It only compares that URL against the JWT `iss` claim as a string, so the URL may reference an internal hostname or non-standard port.
173173</Note>
174174 
175175### JWT verification
176176 
177| Constraint | Detail |
178| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
179| Maximum size | The `assertion` JWT must be at most 16 KiB. |
180| Signing algorithm | Only asymmetric algorithms (RSA and ECDSA families: ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384, PS512) are accepted. HMAC (`HS256`, `HS384`, `HS512`) and `none` are rejected. |
181| Key ID | The JWT header must carry a `kid` that matches a key in the issuer’s JWKS. Tokens without `kid` are rejected. |
182| Required claims | `sub` must be present. `iat` must be present and not in the future. `exp` must be present and in the future. |
183| Single use | An assertion that carries a `jti` claim can be exchanged only once per issuer: repeating an exchange with the same `jti` is rejected as a replay. The issuer’s `check_jti` field (enabled by default) controls this check; assertions without a `jti` claim are not subject to it. See the [Federation issuers API reference](https://platform.claude.com/docs/en/api/organization/federation/issuers). |
184| Maximum lifetime | The token’s lifetime (`exp` minus `iat`) must not exceed the issuer’s configured maximum (1 hour by default, configurable for each issuer in the Claude Console). |
185| Clock skew | A 30-second leeway is applied to `exp`, `nbf`, and `iat`. |
177| Constraint | Detail |
178| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
179| Maximum size | The `assertion` JWT must be at most 16 KiB. |
180| Signing algorithm | Anthropic accepts only asymmetric algorithms (RSA and ECDSA families: ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384, PS512). It rejects HMAC (`HS256`, `HS384`, `HS512`) and `none`. |
181| Key ID | The JWT header must carry a `kid` that matches a key in the issuer’s JWKS. Anthropic rejects tokens without `kid`. |
182| Required claims | `sub` must be present. `iat` must be present and not in the future. `exp` must be present and in the future. |
183| Single use | An assertion that carries a `jti` claim can be exchanged only once for each issuer. Anthropic rejects a repeat exchange with the same `jti` as a replay. The issuer’s `check_jti` field (enabled by default) controls this check. Assertions without a `jti` claim are not subject to it. See the [Federation issuers API reference](https://platform.claude.com/docs/en/api/organization/federation/issuers). |
184| Maximum lifetime | The token’s lifetime (`exp` minus `iat`) must not exceed the issuer’s configured maximum (1 hour by default, configurable for each issuer in the Claude Console). |
185| Clock skew | Anthropic applies a 30-second leeway to `exp`, `nbf`, and `iat`. |
186186 
187187## Rule matching semantics
188188 
189A federation rule’s `match` block determines whether an incoming JWT is accepted. All populated fields are evaluated with AND semantics: the JWT must satisfy every populated matcher. At least one of `subject_prefix`, `claims`, or `condition` must be set; a `match` block that contains only `audience` (or no matchers at all) is rejected. This guards against rules that would accept every token from an issuer.
189A federation rule’s `match` block determines whether Anthropic accepts an incoming JWT. The JWT must satisfy every populated matcher. Set at least one of `subject_prefix`, `claims`, or `condition`. Anthropic rejects a `match` block that contains only `audience` or no matchers at all. This guards against rules that would accept every token from an issuer.
190190 
191| Matcher | Type | Semantics |
192| ---------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
193| `subject_prefix` | string | Exact match against the JWT `sub` claim. A trailing `*` makes it a prefix match (the `sub` value must start with the characters before the `*`). Case-sensitive. |
194| `audience` | string | The JWT `aud` claim must contain this exact string. When `aud` is an array, any element matching exactly satisfies the check. |
195| `claims` | map\<string, string> | Each key is a top-level claim name and each value is the required exact string value. For nested, numeric, boolean, or complex claims such as lists and maps, use `condition` with a CEL expression instead. |
196| `condition` | string (CEL) | A [CEL](https://cel.dev/) expression that must evaluate to `true`. |
191| Matcher | Type | Semantics |
192| ---------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
193| `subject_prefix` | string | Exact match against the JWT `sub` claim. A trailing `*` makes it a prefix match (the `sub` value must start with the characters before the `*`). Case-sensitive. |
194| `audience` | string | The JWT `aud` claim must contain this exact string. When `aud` is an array, any element matching exactly satisfies the check. |
195| `claims` | map\<string, string> | Each key is a top-level claim name and each value is the required exact string value. For nested, numeric, boolean, or complex claims such as lists and maps, use `condition` with a Common Expression Language (CEL) expression instead. |
196| `condition` | string (CEL) | A [CEL](https://cel.dev/) expression that must evaluate to `true`. |
197197 
198198### CEL evaluation environment
199199 
from line 217
217217 
218218### Token exchange errors
219219 
220`POST /v1/oauth/token` returns errors in the standard [API error shape](https://platform.claude.com/docs/en/api/errors). The SDK reports an exchange failure as `WorkloadIdentityError` (ruby: `Anthropic::Credentials::WorkloadIdentityError`; go: `error`; java: `UnexpectedStatusCodeException`; csharp: `WorkloadIdentityException`; php: `OAuthException`), which gives the HTTP status and the error details from the response body. The request ID is on the error in Python, TypeScript, and Ruby, and in the exception’s response headers in Java. In Go it is only in the error’s message, because the error’s type is in an internal package; the C# and PHP errors do not carry it.
220`POST /v1/oauth/token` returns errors in the standard [API error shape](https://platform.claude.com/docs/en/api/errors). The SDK reports an exchange failure as `WorkloadIdentityError` (ruby: `Anthropic::Credentials::WorkloadIdentityError`; go: `error`; java: `UnexpectedStatusCodeException`; csharp: `WorkloadIdentityException`; php: `OAuthException`), which gives the HTTP status and the error details from the response body. Except in C# and PHP, the SDK also gives the request ID: on the error, in the exception’s response headers, or in the error’s message.
221221 
222222| Status | Error | Cause | Resolution |
223223| ------ | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
224| 400 | `invalid_request_error` | `federation_rule_id` is malformed or a required request field is missing. | Verify the `fdrl_` ID and that the request body includes all required fields. |
225| 400 | `invalid_request_error` | `workspace_id` is present but is not a well-formed `wrkspc_...` ID or the literal `default`. | Fix the `workspace_id` value; the response message names the expected format. |
224| 400 | `invalid_request_error` | `federation_rule_id` is malformed or a required request field is missing. | Check the `fdrl_` ID and that the request body includes all required fields. |
225| 400 | `invalid_request_error` | `workspace_id` is present but is not a well-formed `wrkspc_...` ID or the literal `default`. | Fix the `workspace_id` value. The response message names the expected format. |
226226| 401 | `authentication_error` | The JWT `iss` claim does not equal the registered `issuer_url` exactly. | Compare byte-for-byte, including trailing slashes and scheme: `jq -rR 'split(".")[1] \| gsub("-";"+") \| gsub("_";"/") \| @base64d \| fromjson \| .iss' <<< "$JWT"`. |
227| 401 | `authentication_error` | JWKS fetch failed, JWKS is stale, or the JWT was signed with a key not in the JWKS. | For `inline` mode, update the issuer with the rotated keys. For `discovery` and `explicit_url`, confirm the JWKS endpoint is reachable on port 443; if the issuer recently rotated its signing key, see [Key rotation and caching](https://platform.claude.com/docs/en/manage-claude/wif-reference#key-rotation-and-caching). |
228| 401 | `authentication_error` | The JWT `exp` claim is in the past (beyond the 30-second skew window). | Confirm your identity provider is projecting a fresh token and the SDK is re-reading the token file. |
227| 401 | `authentication_error` | JWKS fetch failed, JWKS is stale, or the JWT was signed with a key not in the JWKS. | For `inline` mode, update the issuer with the rotated keys. For `discovery` and `explicit_url`, confirm the JWKS endpoint is reachable on port 443. If the issuer recently rotated its signing key, see [Key rotation and caching](https://platform.claude.com/docs/en/manage-claude/wif-reference#key-rotation-and-caching). |
228| 401 | `authentication_error` | The JWT `exp` claim is in the past (beyond the 30-second skew window). | Confirm your identity provider is projecting a fresh token and the SDK is rereading the token file. |
229229| 401 | `authentication_error` | The JWT was verified but its claims do not satisfy the rule’s `match` block. | Decode the JWT and compare each claim against the rule. `subject_prefix` is case-sensitive. `audience` requires an exact element match. |
230| 401 | `authentication_error` | The `federation_rule_id` does not exist or is archived, or the JWT is not authorized for it (consolidated to prevent enumeration). | Confirm the rule ID in the Claude Console and that the rule has not been archived. |
230| 401 | `authentication_error` | The `federation_rule_id` does not exist or is archived, or the JWT is not authorized for it (one error covers these cases to prevent enumeration). | Confirm the rule ID in the Claude Console and that the rule has not been archived. |
231231| 401 | `authentication_error` | The federation rule is enabled for more than one workspace and the request omits `workspace_id`. The authentication history entry shows reason `workspace_id_required`. | Set `ANTHROPIC_WORKSPACE_ID` (or the `workspace_id` body field on a raw request) to the `wrkspc_...` ID you want the token scoped to. With the `ant` CLI, set `workspace_id` in a federation profile and set `ANTHROPIC_PROFILE` to its name. See [Token exchange request](https://platform.claude.com/docs/en/manage-claude/wif-reference#token-exchange-request). |
232232 
233Every assertion denial returns the same opaque `401` `authentication_error` with the fixed message `Authentication failed`, regardless of which check failed; a distinguishable error would let a caller probe rule configuration. The deny reason is recorded on the attempt’s entry in the [authentication history](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console, for example `match_subject_prefix` when the `sub` claim fails the rule’s `subject_prefix`, or `workspace_id_required` when the rule spans multiple workspaces and the request names none. Requests rejected before the rule’s organization is corroborated (the `400 invalid_request_error` family in the previous table) leave no history entry. Their response messages name the problem directly. A `401` with no matching history entry usually means the `federation_rule_id` itself was not recognized.
233Every assertion denial returns the same opaque `401` `authentication_error` with the fixed message `Authentication failed`, regardless of which check failed. A distinguishable error would let a caller probe rule configuration. The [authentication history](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console records the deny reason on the attempt’s entry. For example, it shows `match_subject_prefix` when the `sub` claim fails the rule’s `subject_prefix`, or `workspace_id_required` when the rule spans multiple workspaces and the request names none. Requests rejected before the rule’s organization is confirmed (the `400 invalid_request_error` family in the previous table) leave no history entry. Their response messages name the problem directly. A `401` with no matching history entry usually means that Anthropic did not recognize the `federation_rule_id`.
234234 
235235### Common SDK-side failures
236236 
237237| Symptom | Cause | Resolution |
238238| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
239| SDK reports “no credentials” instead of exchanging | One of `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, or `ANTHROPIC_IDENTITY_TOKEN[_FILE]` is unset and no profile is active. | Set all four variables, or configure a profile. |
239| SDK reports missing credentials instead of exchanging | One of `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, or `ANTHROPIC_IDENTITY_TOKEN[_FILE]` is unset and no profile is active. | Set all four variables, or configure a profile. |
240240| SDK authenticates with an API key instead of federating | `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN` is set and wins precedence. | Unset the key or token variable. |
241241| File-not-found error on first request | The path in `ANTHROPIC_IDENTITY_TOKEN_FILE` does not exist. The SDK opens the file lazily at exchange time. | Confirm the projected-token volume is mounted and the path matches. |
242242| Token exchange succeeds but a Claude API request returns 403 | The minted token’s scope does not grant access to that endpoint. | Check the rule’s `oauth_scope` against [OAuth scopes](https://platform.claude.com/docs/en/manage-claude/wif-reference#oauth-scopes). |
243| Authentication fails with empty credential | A credential environment variable is exported but set to an empty string. Empty values can still win their precedence slot. | Unset the variable with `unset VAR` rather than `VAR=""`. |
243| Authentication fails with empty credential | A credential environment variable is exported but set to an empty string. Empty values can win their precedence slot. | Unset the variable with `unset VAR` rather than `VAR=""`. |
244244 
245245## Troubleshoot a failed exchange
246246 
247A `401` `authentication_error` response is intentionally opaque and its message is always `Authentication failed`; the deny reason is recorded in the authentication history, not in the response.
247A `401` `authentication_error` response is intentionally opaque, and its message is always `Authentication failed`. The deny reason appears in the authentication history, not in the response.
248248 
249249<Tip>
250 Start with the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console. Recent exchange attempts surface the issuer and rule that were evaluated, the JWT claims that were inspected, and which validation step failed, which usually short-circuits the following checks.
250 Start with the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console. Recent exchange attempts show the issuer and rule that Anthropic evaluated, the JWT claims that it inspected, and which validation step failed. This information usually makes the following checks unnecessary.
251251</Tip>
252252 
253One common opaque failure is a replayed assertion: an assertion that carries a `jti` claim can be [exchanged only once](https://platform.claude.com/docs/en/manage-claude/wif-reference#jwt-verification), so a workload that re-sends the same JWT (a retry loop, or a refresh that re-reads an unrotated token) is rejected on the second exchange. The authentication history page shows these attempts with the reason `jti_reused`; the fix is to mint a fresh assertion for each exchange.
253One common opaque failure is a replayed assertion. An assertion that carries a `jti` claim can be [exchanged only once](https://platform.claude.com/docs/en/manage-claude/wif-reference#jwt-verification). A workload that resends the same JWT (a retry loop, or a refresh that rereads an unrotated token) fails on the second exchange. The authentication history page shows these attempts with the reason `jti_reused`. To fix this, mint a fresh assertion for each exchange.
254254 
255If you still need to debug from the JWT itself, work through these checks in order:
255If you need to debug from the JWT itself, work through these checks in order:
256256 
257257<Steps>
258258 <Step title="Decode the JWT">
from line 272
272272 </Step>
273273 
274274 <Step title="Check sub and each claims entry">
275 Compare `sub` against the rule’s `subject_prefix` (case-sensitive; a trailing `*` is a prefix match, and anything else is exact). Compare every key in the rule’s `claims` map against the same-named top-level claim.
275 Compare `sub` against the rule’s `subject_prefix`. The comparison is case-sensitive. A trailing `*` makes it a prefix match, and anything else is exact. Compare every key in the rule’s `claims` map against the same-named top-level claim.
276276 </Step>
277277 
278278 <Step title="Check exp, nbf, and iat">
279 `exp` must be in the future and `nbf`/`iat` must be in the past, within the 30-second skew window. If the workload host’s clock has drifted, an otherwise valid token is rejected.
279 `exp` must be in the future and `nbf`/`iat` must be in the past, within the 30-second skew window. If the workload host’s clock has drifted, Anthropic rejects an otherwise valid token.
280280 </Step>
281281 
282282 <Step title="Check JWKS reachability">
from line 288
288288 
289289## JWKS source modes
290290 
291When you register a federation issuer, the `jwks` field controls how Anthropic obtains the public keys used to verify JWT signatures from that issuer. It is a discriminated union keyed on `type`:
291When you register a federation issuer, the `jwks` field controls how Anthropic obtains the public keys used to verify JWT signatures from that issuer. Its `type` field selects the source mode:
292292 
293| `jwks.type` | `jwks` shape | Behavior | Use when |
294| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
295| `discovery` (default) | `{ "type": "discovery", "discovery_base": "https://..." }` (`discovery_base` is optional; set it when the discovery URL differs from `issuer_url`) | Anthropic fetches `<discovery_base or issuer_url>/.well-known/openid-configuration`, reads `jwks_uri` from the discovery document, and fetches the JWKS from there. | Your IdP serves a standard OIDC discovery document on the public internet. Most managed providers (EKS, GKE, Cloud Run, GitHub Actions, Entra ID) support this. |
296| `explicit_url` | `{ "type": "explicit_url", "url": "https://..." }` | Anthropic fetches the JWKS directly from `url`. The `issuer_url` is used only for string comparison against the JWT `iss` claim and is never dialed. | Your IdP does not serve a discovery document, or discovery is internal-only but the JWKS is publicly reachable. |
297| `inline` | `{ "type": "inline", "keys": [...] }` | You supply the array of JWK objects inline (the `keys` array from the JWKS document, not the wrapper object). Anthropic makes no outbound request. The `issuer_url` is used only for `iss` comparison. | Air-gapped environments, self-managed Kubernetes clusters with cluster-internal issuer URLs, or when you want explicit control over key rotation. |
293| `jwks.type` | `jwks` shape | Behavior | Use when |
294| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
295| `discovery` (default) | `{ "type": "discovery", "discovery_base": "https://..." }` (set the optional `discovery_base` when the discovery URL differs from `issuer_url`) | Anthropic fetches `<discovery_base or issuer_url>/.well-known/openid-configuration`, reads `jwks_uri` from the discovery document, and fetches the JWKS from there. | Your IdP serves a standard OIDC discovery document on the public internet. Most managed providers (EKS, GKE, Cloud Run, GitHub Actions, Entra ID) support this. |
296| `explicit_url` | `{ "type": "explicit_url", "url": "https://..." }` | Anthropic fetches the JWKS directly from `url`. Anthropic uses the `issuer_url` only for string comparison against the JWT `iss` claim and never connects to it. | Your IdP does not serve a discovery document, or discovery is internal-only but the JWKS is publicly reachable. |
297| `inline` | `{ "type": "inline", "keys": [...] }` | You supply the array of JWK objects inline (the `keys` array from the JWKS document, not the wrapper object). Anthropic makes no outbound request. Anthropic uses the `issuer_url` only for `iss` comparison. | Air-gapped environments, self-managed Kubernetes clusters with cluster-internal issuer URLs, or when you want explicit control over key rotation. |
298298 
299The discriminated union makes the companion fields mutually exclusive by construction. Both `discovery` and `explicit_url` also accept an optional `ca_cert_pem` string for issuers that serve TLS from a private CA.
299Each `type` takes its own companion fields, so those fields are mutually exclusive. Both `discovery` and `explicit_url` also accept an optional `ca_cert_pem` string for issuers that serve TLS from a private CA.
300300 
301301### Key rotation and caching
302302 
303In `discovery` and `explicit_url` modes, Anthropic caches the fetched JWKS. If your identity provider publishes a new signing key and immediately starts signing tokens with it, exchanges that present those tokens might fail with a signature error for up to 1 minute while the cache refreshes.
303In `discovery` and `explicit_url` modes, Anthropic caches the fetched JWKS. After your identity provider publishes a new signing key, exchanges of tokens signed with it might fail with a signature error for up to 1 minute while the cache refreshes.
304304 
305To avoid this window, publish a new signing key in the JWKS at least 15 minutes before your identity provider starts signing tokens with it, and keep the superseded key in the JWKS until tokens it signed have expired. Managed identity providers typically follow this discipline on their own. If you operate your own issuer (a self-managed Kubernetes cluster, a SPIRE OIDC discovery provider, or an Okta custom authorization server with a configured rotation cadence), confirm that your rotation policy publishes new keys ahead of first use.
305To avoid this window, publish a new signing key in the JWKS at least 15 minutes before your identity provider starts signing tokens with it. Keep the replaced key in the JWKS until the tokens it signed have expired. Managed identity providers typically do this on their own. If you operate your own issuer, confirm that your rotation policy publishes new keys ahead of first use. Examples are a self-managed Kubernetes cluster, a SPIRE OIDC discovery provider, and an Okta custom authorization server with a configured rotation schedule.
306306 
307307<Warning>
308 In `inline` mode there is no automatic key refresh. When your identity provider rotates its signing keys, you must update the issuer configuration with the new JWKS or all token exchanges will fail signature verification.
308 In `inline` mode there is no automatic key refresh. When your identity provider rotates its signing keys, you must update the issuer configuration with the new JWKS or all token exchanges fail signature verification.
309309</Warning>
310310 

manage-claude/workload-identity-federation Changed · +30 / -30 lines

from line 8
88 
99Your workload presents a signed JWT from your identity provider. Anthropic validates it against trust rules you configure in the Claude Console and returns a short-lived Anthropic access token bound to a service account in your organization. There are no static secrets to mint, store in CI, rotate, or leak.
1010 
11Workload Identity Federation strengthens your security posture by replacing static API keys with tokens that expire in minutes rather than never. It is not a complete security solution on its own: federated authentication is only as strong as the upstream identity provider that signs the JWT. Pair Workload Identity Federation with the controls your IdP already supports (workload identity binding, conditional access, audit logging) for defense in depth.
11Workload Identity Federation strengthens your security posture by replacing static API keys with tokens that expire in minutes rather than never. It is not a complete security solution on its own. Federated authentication is only as strong as the upstream identity provider that signs the JWT. Pair Workload Identity Federation with the controls your IdP already supports (workload identity binding, conditional access, audit logging) for defense in depth.
1212 
1313## Concepts
1414 
from line 16
1616 
1717### Service accounts
1818 
19A **service account** (`svac_...`) is a named, non-human identity inside your Anthropic organization. It is the principal that a [service account key](https://platform.claude.com/docs/en/manage-claude/authentication#key-types) or a federated token acts as. Service accounts live at the organization level and become active in a workspace when you add them as members of that workspace. At exchange time, Anthropic checks that the federation rule’s workspace matches one of the service account’s workspace memberships; the minted token then follows that workspace’s rate limits and usage attribution, the same as an API key. Unlike a human user, a service account has no email, no password, and no Console login. Every service account is implicitly a member of your organization’s default workspace; add explicit memberships for any other workspace it should act in. To let an all-workspaces service account key act in a workspace, add the service account to that workspace.
19A **service account** (`svac_...`) is a named, non-human identity inside your Anthropic organization. It is the principal that a [service account key](https://platform.claude.com/docs/en/manage-claude/authentication#key-types) or a federated token acts as. Service accounts live at the organization level and become active in a workspace when you add them as members of that workspace. At exchange time, Anthropic checks that the federation rule’s workspace matches one of the service account’s workspace memberships. The minted token then follows that workspace’s rate limits and usage attribution, the same as an API key. Unlike a human user, a service account has no email, no password, and no Console login. Every service account is implicitly a member of your organization’s default workspace. Add explicit memberships for any other workspace it should act in. To let an all-workspaces service account key act in a workspace, add the service account to that workspace.
2020 
21The key distinction versus a workspace API key: a workspace API key *is* a credential, whereas a service account *has* credentials. You can more easily audit which workloads acted as which service account.
21A workspace API key *is* a credential, whereas a service account *has* credentials. Because each workload authenticates as a named service account, you can more easily audit which workloads acted as which service account.
2222 
2323### Federation issuers
2424 
from line 27
2727An issuer has two pieces of configuration:
2828 
2929* **Issuer URL:** The exact `iss` claim value that appears in the provider’s JWTs, for example `https://token.actions.githubusercontent.com` or `https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLE`.
30* **JWKS source:** How Anthropic fetches the public keys to verify JWT signatures. Use `discovery` (the default) for any provider that serves `/.well-known/openid-configuration` at its issuer URL. Use `explicit_url` to point at a JWKS endpoint directly, or `inline` to upload the key set for issuers that are not reachable from the public internet (for example, a private Kubernetes cluster).
30* **JWKS source:** How Anthropic fetches the public keys to verify JWT signatures. Use `discovery` (the default) for any provider that serves `/.well-known/openid-configuration` at its issuer URL. Use `explicit_url` to point at a JWKS endpoint directly. Use `inline` to upload the key set for issuers that are not reachable from the public internet, for example a private Kubernetes cluster.
3131 
32Issuer and JWKS URLs must be `https`, on port 443, and use a public DNS hostname that resolves to public IP addresses; IP literals are not accepted. These constraints apply only to URLs Anthropic fetches; in `explicit_url` and `inline` modes the `issuer_url` is compared as a string and may reference an internal hostname.
32Issuer and JWKS URLs must be `https`, on port 443, and use a public DNS hostname that resolves to public IP addresses. Anthropic does not accept IP literals. These constraints apply only to URLs Anthropic fetches. In `explicit_url` and `inline` modes, Anthropic compares the `issuer_url` as a string, and the URL may reference an internal hostname.
3333 
3434You typically register one issuer for each environment: your production EKS cluster, your staging cluster, and GitHub Actions are three separate issuers.
3535 
3636### Federation rules
3737 
38A **federation rule** (`fdrl_...`) is the bridge between an issuer and a service account: “when a JWT from issuer X has claims that look like Y, mint a token for service account Z with scope S.”
38A **federation rule** (`fdrl_...`) binds an issuer to a service account: “when a JWT from issuer X has claims that look like Y, mint a token for service account Z with scope S.”
3939 
4040A rule defines match conditions, a target, and the authorization scope and token lifetime that apply when the rule matches:
4141 
42* **Match:** The conditions an incoming JWT must satisfy. You can match on a `subject_prefix` (for example, `system:serviceaccount:prod:worker`, or with a trailing `*` for a prefix match), an exact `audience`, a map of exact claim values, a [CEL](https://cel.dev/) `condition` expression for complex logic, or any combination. At least one of `subject_prefix`, `claims`, or `condition` must be set, and all configured matchers must pass for the JWT to be accepted.
42* **Match:** The conditions an incoming JWT must satisfy. You can match on a `subject_prefix`, an exact `audience`, a map of exact claim values, a [Common Expression Language (CEL)](https://cel.dev/) `condition` expression for complex logic, or any combination. A `subject_prefix` is an exact match, such as `system:serviceaccount:prod:worker`, or a prefix match with a trailing `*`. Set at least one of `subject_prefix`, `claims`, or `condition`. All configured matchers must pass for Anthropic to accept the JWT.
4343* **Target:** The service account the matched JWT maps to.
44* **Authorization:** The OAuth `scope` granted on the minted token. The default is `workspace:developer`, which grants the same access as a workspace API key. Some products lock the scope when you create a rule from their flow; for example, the [MCP tunnels](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview) create-tunnel modal creates rules scoped to `workspace:manage_tunnels`. See [OAuth scopes](https://platform.claude.com/docs/en/manage-claude/wif-reference#oauth-scopes). The rule also sets `token_lifetime_seconds` (60 to 86,400, default 3,600).
44* **Authorization:** The OAuth `scope` granted on the minted token. The default is `workspace:developer`, which grants the same access as a workspace API key. Some products lock the scope when you create a rule from their flow. For example, the [MCP tunnels](https://platform.claude.com/docs/en/agents-and-tools/mcp-tunnels/overview) create-tunnel modal creates rules scoped to `workspace:manage_tunnels`. See [OAuth scopes](https://platform.claude.com/docs/en/manage-claude/wif-reference#oauth-scopes). The rule also sets `token_lifetime_seconds` (60 to 86,400, default 3,600).
4545 
46A single issuer can have many rules: one for each team, namespace, or permission level. Rules are evaluated by ID: the client specifies which rule to use in the exchange request, and Anthropic verifies the JWT satisfies that rule’s match criteria. There is no implicit rule search.
46A single issuer can have many rules: one for each team, namespace, or permission level. Anthropic evaluates rules by ID. The client specifies which rule to use in the exchange request, and Anthropic verifies that the JWT satisfies that rule’s match criteria. There is no implicit rule search.
4747 
4848## How it works
4949 
501. **Your IdP issues a JWT to the workload.** On most platforms this is ambient: a Kubernetes projected service-account token, the Google Cloud metadata server, Azure IMDS, or the GitHub Actions OIDC endpoint. The JWT’s `iss` claim identifies the provider, and its `sub` and other claims identify the specific workload.
512. **The SDK exchanges the JWT for an Anthropic access token.** The SDK posts the JWT to `POST /v1/oauth/token` using the [RFC 7523](https://www.rfc-editor.org/rfc/rfc7523) `jwt-bearer` grant. Anthropic verifies the JWT against the issuer’s JWKS and the federation rule’s match conditions, then returns a short-lived `sk-ant-oat01-...` token that acts on behalf of the rule’s target service account.
501. **Your IdP issues a JWT to the workload.** On most platforms, the JWT is already available to the workload through a Kubernetes projected service-account token, the Google Cloud metadata server, the Azure Instance Metadata Service (IMDS), or the GitHub Actions OIDC endpoint. The JWT’s `iss` claim identifies the provider, and its `sub` and other claims identify the specific workload.
512. **The SDK exchanges the JWT for an Anthropic access token.** The SDK posts the JWT to `POST /v1/oauth/token` using the [RFC 7523](https://www.rfc-editor.org/rfc/rfc7523) `jwt-bearer` grant. Anthropic verifies the JWT against the issuer’s JWKS and the federation rule’s match conditions. It then returns a short-lived `sk-ant-oat01-...` token that acts on behalf of the rule’s target service account.
52523. **The SDK sends the token on every request and refreshes it before it expires.** Your application code constructs the client with no API key and calls the API as usual. The SDK reruns the exchange before the token expires.
5353 
5454## Set up federation
5555 
56You need the admin, owner, or primary owner role in your Anthropic organization, an OIDC-capable identity provider with a reachable JWKS endpoint (or a JWKS document you can paste, for air-gapped clusters), and a workload that can obtain an identity token from that provider.
56You need the admin, owner, or primary owner role in your Anthropic organization. You also need an OIDC-capable identity provider with a reachable JWKS endpoint, or a JWKS document you can paste for air-gapped clusters. Your workload must be able to obtain an identity token from that provider.
5757 
5858The **Connect workload** wizard creates all three resources (the issuer, the service account, and the federation rule) in one guided flow, then verifies the connection end to end.
5959 
from line 67
6767 </Step>
6868 
6969 <Step title="Fill in the guided fields">
70 The wizard walks you through the provider-specific fields: the issuer configuration, the match conditions for incoming JWTs, and names for the service account and federation rule it creates. The wizard prefills `oauth_scope=workspace:developer` and `token_lifetime_seconds=600` (the API default when `token_lifetime_seconds` is omitted is 3,600); adjust these if your workload needs a different scope or lifetime.
70 The wizard walks you through the provider-specific fields: the issuer configuration, the match conditions for incoming JWTs, and names for the service account and federation rule it creates. The wizard prefills `oauth_scope=workspace:developer` and `token_lifetime_seconds=600`. Adjust these if your workload needs a different scope or lifetime. When a request omits `token_lifetime_seconds`, the API default is 3,600 seconds.
7171 </Step>
7272 
7373 <Step title="Verify the issuer">
74 Optionally select **Verify issuer** to dry-run the issuer configuration before anything is created. Verification confirms Anthropic can fetch and parse the JWKS from the URLs you entered, which catches reachability and configuration mistakes early.
74 Optionally select **Verify issuer** to dry-run the issuer configuration before the wizard creates anything. Verification confirms Anthropic can fetch and parse the JWKS from the URLs you entered, which catches reachability and configuration mistakes early.
7575 </Step>
7676 
7777 <Step title="Test the connection">
78 The wizard creates the issuer, service account, and federation rule, then listens for a successful token exchange for 15 minutes. Trigger an exchange from your workload within that window (see [Authenticate from your workload](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#authenticate-from-your-workload)) to confirm the setup works. If the window elapses, the resources persist; you can rerun the test from the federation rule’s detail page. Note the rule’s ID (`fdrl_...`) and the service account ID (`svac_...`) the wizard creates. Your workload passes both in every token-exchange request, along with your organization ID and, when the rule covers more than one workspace, your workspace ID.
78 The wizard creates the issuer, service account, and federation rule, then listens for a successful token exchange for 15 minutes. Trigger an exchange from your workload within that window (see [Authenticate from your workload](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#authenticate-from-your-workload)) to confirm the setup works. If the window elapses, the resources persist. You can rerun the test from the federation rule’s detail page. Note the rule’s ID (`fdrl_...`) and the service account ID (`svac_...`) the wizard creates. Your workload passes both in every token-exchange request, along with your organization ID and, when the rule covers more than one workspace, your workspace ID.
7979 </Step>
8080</Steps>
8181 
from line 87
8787 
8888### Construct the SDK client
8989 
90You can construct the client with explicit credentials or with no arguments. With no arguments, the SDK resolves credentials from environment variables or the active profile, as described under [Credential precedence](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#credential-precedence). The zero-argument form is the recommended pattern for production workloads: ship the same container image everywhere and inject `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, `ANTHROPIC_WORKSPACE_ID`, and `ANTHROPIC_IDENTITY_TOKEN_FILE` for each environment.
90You can construct the client with explicit credentials or with no arguments. With no arguments, the SDK resolves credentials from environment variables or the active profile, as described under [Credential precedence](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#credential-precedence). The zero-argument form is the recommended pattern for production workloads. Ship the same container image everywhere and inject `ANTHROPIC_FEDERATION_RULE_ID`, `ANTHROPIC_ORGANIZATION_ID`, `ANTHROPIC_SERVICE_ACCOUNT_ID`, `ANTHROPIC_WORKSPACE_ID`, and `ANTHROPIC_IDENTITY_TOKEN_FILE` for each environment.
9191 
9292<CodeGroup>
9393 ```bash cURL
from line 347
347347The SDK resolves credentials in a five-tier order: constructor arguments, then `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN`, then an explicit `ANTHROPIC_PROFILE`, then the federation environment variables, then the implicit active profile. The first source that yields a credential wins.
348348 
349349<Warning>
350 `ANTHROPIC_API_KEY` sits above the federation tiers, so a leftover key in the environment silently shadows federation. When migrating a workload from API keys to Workload Identity Federation, confirm `ANTHROPIC_API_KEY` is unset everywhere that workload runs (container env, CI secrets, shell profiles). The CLI’s [`ant auth status`](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/authentication#check-authentication-status) command reports which source won.
350 `ANTHROPIC_API_KEY` sits above the federation tiers, so a leftover key in the environment silently overrides federation. When migrating a workload from API keys to Workload Identity Federation, confirm `ANTHROPIC_API_KEY` is unset everywhere that workload runs (container environment, CI secrets, shell profiles). The CLI’s [`ant auth status`](https://platform.claude.com/docs/en/cli-sdks-libraries/cli/authentication#check-authentication-status) command reports which source won.
351351</Warning>
352352 
353For the full precedence table, the per-tier semantics, and the profile file schema, see [Credential precedence in the WIF reference](https://platform.claude.com/docs/en/manage-claude/wif-reference#credential-precedence).
353For the full precedence table, the meaning of each tier, and the profile file schema, see [Credential precedence in the WIF reference](https://platform.claude.com/docs/en/manage-claude/wif-reference#credential-precedence).
354354 
355355## Migrate from API keys
356356 
357357To switch an existing workload from a static API key to federation without downtime:
358358 
3591. **Configure federation in parallel.** Complete the [setup walkthrough](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#set-up-federation) and confirm the federation rule matches your workload’s token. Leave the existing `ANTHROPIC_API_KEY` in place for now.
3602. **Smoke-test which credential wins.** Run `ant auth status` from inside the workload (or inspect SDK debug logs). Because `ANTHROPIC_API_KEY` sits above the federation tiers in the precedence chain, the API key still wins at this stage.
3591. **Configure federation in parallel.** Complete the steps in [Set up federation](https://platform.claude.com/docs/en/manage-claude/workload-identity-federation#set-up-federation) and confirm the federation rule matches your workload’s token. Leave the existing `ANTHROPIC_API_KEY` in place for now.
3602. **Check which credential wins.** Run `ant auth status` from inside the workload (or inspect SDK debug logs). Because `ANTHROPIC_API_KEY` sits above the federation tiers in the precedence chain, the API key still wins at this stage.
3613613. **Unset `ANTHROPIC_API_KEY` everywhere it is injected.** Remove it from CI secrets, container environment, and shell profiles (see the preceding warning). Rerun `ant auth status` and confirm the federation source now wins.
3623624. **Delete the API key.** Once the workload is running on the federated token, delete the key on the [API keys](https://platform.claude.com/settings/keys) page (`platform.claude.com/settings/keys`) in the Claude Console.
363363 
from line 365
365365 
366366The minted Anthropic token’s lifetime is the lesser of (a) the rule’s `token_lifetime_seconds` (default 3,600 seconds) and (b) twice the remaining lifetime of the IdP JWT you presented. The result is never less than 60 seconds. The second bound prevents an Anthropic token from outliving the upstream identity it was derived from by more than a small margin.
367367 
368The SDK caches the token and refreshes it on a two-tier schedule modeled on `botocore`:
368The SDK caches the token and refreshes it on a two-tier schedule:
369369 
370370* **Advisory refresh** at expiry minus 120 seconds. The SDK attempts a new exchange. If the token endpoint is unreachable, the SDK continues serving the cached token, which is still valid for roughly 90 more seconds.
371* **Mandatory refresh** at expiry minus 30 seconds. A failed exchange at this point raises an error. The cached token is too close to expiry to be safe.
371* **Mandatory refresh** at expiry minus 30 seconds. A failed exchange at this point results in an error. The cached token is too close to expiry to be safe.
372372 
373Because the SDK re-reads `ANTHROPIC_IDENTITY_TOKEN_FILE` on every exchange, it transparently picks up rotated projected tokens (Kubernetes service-account tokens, for example, rotate well before their `exp`).
373Because the SDK rereads `ANTHROPIC_IDENTITY_TOKEN_FILE` on every exchange, it automatically picks up rotated projected tokens (Kubernetes service-account tokens, for example, rotate well before their `exp`).
374374 
375By default, identity tokens that carry a `jti` claim are single-use: each exchange must present a JWT that has not been exchanged before, and re-presenting one fails with the reason `jti_reused` on the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console. If your workload fetches its own tokens from your identity provider, mint a fresh JWT for each exchange instead of reusing a cached one (retry loops are the usual cause of reuse). The same applies to a token read from `ANTHROPIC_IDENTITY_TOKEN_FILE`: the SDK re-reads the file on every exchange, so the file must hold a new token before each refresh. A refresh that re-reads an unrotated token, or a restarted process that re-presents a token it already exchanged, is rejected the same way. Rotating the token well within the minted token’s lifetime keeps the file ahead of the refresh schedule. If your token source cannot rotate that often, you can disable `check_jti` for that issuer as a last resort. This removes replay protection for every rule on the issuer. See [JWT verification](https://platform.claude.com/docs/en/manage-claude/wif-reference#jwt-verification) for details.
375By default, identity tokens that carry a `jti` claim are single-use. Each exchange must present a JWT that has not been exchanged before. Presenting the same JWT again fails with the reason `jti_reused` on the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console. If your workload fetches its own tokens from your identity provider, mint a fresh JWT for each exchange instead of reusing a cached one. Retry loops are the usual cause of reuse. The SDK rereads `ANTHROPIC_IDENTITY_TOKEN_FILE` on every exchange, so the file must hold a new token before each refresh. A refresh that rereads an unrotated token fails the same way, as does a restarted process that presents a token it already exchanged. Rotating the token well within the minted token’s lifetime keeps the file ahead of the refresh schedule. If your token source cannot rotate that often, you can disable `check_jti` for that issuer as a last resort. This removes replay protection for every rule on the issuer. See [JWT verification](https://platform.claude.com/docs/en/manage-claude/wif-reference#jwt-verification) for details.
376376 
377377## Identity providers
378378 
from line 380
380380 
381381<CardGroup cols={3}>
382382 <Card title="AWS" icon="cloud" href="https://platform.claude.com/docs/en/manage-claude/wif-providers/aws">
383 STS web identity tokens, or EKS IRSA projected tokens.
383 STS web identity tokens, or EKS projected service-account tokens.
384384 </Card>
385385 
386386 <Card title="Google Cloud" icon="cloud" href="https://platform.claude.com/docs/en/manage-claude/wif-providers/gcp">

release-notes/overview Changed · +48 / -50 lines

### April 9, 2025 ### March 31, 2025 ### February 27, 2025 ### February 24, 2025 ### February 10, 2025 ### January 31, 2025 ### January 23, 2025 ### January 21, 2025 ### January 15, 2025 ### January 10, 2025 ### December 19, 2024 ### December 17, 2024 ### December 4, 2024 ### November 21, 2024 ### November 20, 2024 ### November 13, 2024 ### November 6, 2024 ### November 4, 2024 ### November 1, 2024 ### October 22, 2024 ### October 8, 2024 ### October 3, 2024 ### September 10, 2024 ### September 4, 2024 ### August 22, 2024 ### August 19, 2024 ### August 14, 2024 ### July 15, 2024 ### July 9, 2024 ### June 27, 2024 ### June 20, 2024 ### May 30, 2024 ### May 10, 2024 ### April 9th, 2025 ### March 31st, 2025 ### February 27th, 2025 ### February 24th, 2025 ### February 10th, 2025 ### January 31st, 2025 ### January 23rd, 2025 ### January 21st, 2025 ### January 15th, 2025 ### January 10th, 2025 ### December 19th, 2024 ### December 17th, 2024 ### December 4th, 2024 ### November 21st, 2024 ### November 20th, 2024 ### November 13th, 2024 ### November 6th, 2024 ### November 4th, 2024 ### November 1st, 2024 ### October 22nd, 2024 ### October 8th, 2024 ### October 3rd, 2024 ### September 10th, 2024 ### September 4th, 2024 ### August 22nd, 2024 ### August 19th, 2024 ### August 14th, 2024 ### July 15th, 2024 ### July 9th, 2024 ### June 27th, 2024 ### June 20th, 2024 ### May 30th, 2024 ### May 10th, 2024

from line 644
644644 
645645### August 5, 2025
646646 
647* We’ve launched [Claude Opus 4.1](https://www.anthropic.com/news/claude-opus-4-1), an incremental update to Claude Opus 4 with enhanced capabilities and performance improvements.<sup>\*</sup> Learn more in [Models overview](https://platform.claude.com/docs/en/models/overview).
647* We’ve launched [Claude Opus 4.1](https://www.anthropic.com/news/claude-opus-4-1), an incremental update to Claude Opus 4 with enhanced capabilities and performance improvements. Opus 4.1 does not allow both `temperature` and `top_p` parameters to be specified. Use only one. Learn more in [Models overview](https://platform.claude.com/docs/en/models/overview).
648648 
649*<sup>\*Opus 4.1 does not allow both `temperature` and `top_p` parameters to be specified. Use only one.</sup>*
650 
651649### July 28, 2025
652650 
653651* We’ve released `text_editor_20250728`, an updated text editor tool that fixes some issues from the previous versions and adds an optional `max_characters` parameter that allows you to control the truncation length when viewing large files.
from line 702
704702 
705703* Cache control must now be specified directly in the parent `content` block of `tool_result` and `document.source`. For backwards compatibility, if cache control is detected on the last block in `tool_result.content` or `document.source.content`, it will be automatically applied to the parent block instead. Cache control on any other blocks within `tool_result.content` and `document.source.content` will result in a validation error.
706704 
707### April 9th, 2025
705### April 9, 2025
708706 
709707* We launched a beta version of the [Ruby SDK](https://github.com/anthropics/anthropic-sdk-ruby).
710708 
711### March 31st, 2025
709### March 31, 2025
712710 
713711* Our [Java SDK](https://github.com/anthropics/anthropic-sdk-java) has moved from beta to its first stable release.
714712* We’ve moved our [Go SDK](https://github.com/anthropics/anthropic-sdk-go) from alpha to beta.
715713 
716### February 27th, 2025
714### February 27, 2025
717715 
718716* We’ve added URL source blocks for images and PDFs in the Messages API. You can now reference images and PDFs directly through a URL instead of having to base64-encode them. Learn more in [Vision](https://platform.claude.com/docs/en/build-with-claude/vision) and [PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support).
719717* We’ve added support for a `none` option to the `tool_choice` parameter in the Messages API that prevents Claude from calling any tools. Additionally, you’re no longer required to provide any `tools` when including `tool_use` and `tool_result` blocks.
720718* We’ve launched an OpenAI-compatible API endpoint, allowing you to test Claude models by changing just your API key, base URL, and model name in existing OpenAI integrations. This compatibility layer supports core chat completions functionality. Learn more in [OpenAI SDK compatibility](https://platform.claude.com/docs/en/cli-sdks-libraries/libraries/openai-sdk).
721719 
722### February 24th, 2025
720### February 24, 2025
723721 
724722* We’ve launched [Claude Sonnet 3.7](https://www.anthropic.com/news/claude-3-7-sonnet), our most intelligent model yet. Claude Sonnet 3.7 can produce near-instant responses or show its extended thinking step-by-step. One model, two ways to think. Learn more about all Claude models in [Models overview](https://platform.claude.com/docs/en/models/overview).
725723 
from line 733
735733 * `text_editor_20250124`: Same functionality as previous version but is independent from computer use. Does not require a beta header.
736734 * `computer_20250124`: Updated computer use tool with new command options including `hold_key`, `left_mouse_down`, `left_mouse_up`, `scroll`, `triple_click`, and `wait`. This tool requires the `computer-use-2025-01-24` anthropic-beta header. Learn more in [Tool use with Claude](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview).
737735 
738### February 10th, 2025
736### February 10, 2025
739737 
740738* We’ve added the `anthropic-organization-id` response header to all API responses. This header provides the organization ID associated with the API key used in the request.
741739 
742### January 31st, 2025
740### January 31, 2025
743741 
744742* We’ve moved our [Java SDK](https://github.com/anthropics/anthropic-sdk-java) from alpha to beta.
745743 
746### January 23rd, 2025
744### January 23, 2025
747745 
748746* We’ve launched citations capability in the API, allowing Claude to provide source attribution for information. Learn more in [Citations](https://platform.claude.com/docs/en/build-with-claude/citations).
749747* We’ve added support for plain text documents and custom content documents in the Messages API.
750748 
751### January 21st, 2025
749### January 21, 2025
752750 
753751* We announced the deprecation of the Claude 2, Claude 2.1, and Claude Sonnet 3 models. Read more in [Model deprecations](https://platform.claude.com/docs/en/about-claude/model-deprecations).
754752 
755### January 15th, 2025
753### January 15, 2025
756754 
757755* We’ve updated [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) to be easier to use. Now, when you set a cache breakpoint, we’ll automatically read from your longest previously cached prefix.
758756* You can now prefill Claude’s response when using tools.
759757 
760### January 10th, 2025
758### January 10, 2025
761759 
762760* We’ve optimized support for [prompt caching in the Message Batches API](https://platform.claude.com/docs/en/build-with-claude/batch-processing#using-prompt-caching-with-message-batches) to improve cache hit rate.
763761 
764### December 19th, 2024
762### December 19, 2024
765763 
766764* We’ve added support for a [delete endpoint](https://platform.claude.com/docs/en/api/messages/batches/delete) in the Message Batches API.
767765 
768### December 17th, 2024
766### December 17, 2024
769767 
770The following features are now available in the Claude API without a beta header:
768* The following features are now available in the Claude API without a beta header:
771769 
772* [Models API](https://platform.claude.com/docs/en/api/models/list): Query available models, validate model IDs, and resolve [model aliases](https://platform.claude.com/docs/en/models/overview) to their canonical model IDs.
773* [Message Batches API](https://platform.claude.com/docs/en/build-with-claude/batch-processing): Process large batches of messages asynchronously at 50% of the standard API cost.
774* [Token counting API](https://platform.claude.com/docs/en/build-with-claude/token-counting): Calculate token counts for Messages before sending them to Claude.
775* [Prompt Caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching): Reduce costs by up to 90% and latency by up to 80% by caching and reusing prompt content.
776* [PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support): Process PDFs to analyze both text and visual content within documents.
770 * [Models API](https://platform.claude.com/docs/en/api/models/list): Query available models, validate model IDs, and resolve [model aliases](https://platform.claude.com/docs/en/models/overview) to their canonical model IDs.
771 * [Message Batches API](https://platform.claude.com/docs/en/build-with-claude/batch-processing): Process large batches of messages asynchronously at 50% of the standard API cost.
772 * [Token counting API](https://platform.claude.com/docs/en/build-with-claude/token-counting): Calculate token counts for Messages before sending them to Claude.
773 * [Prompt Caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching): Reduce costs by up to 90% and latency by up to 80% by caching and reusing prompt content.
774 * [PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support): Process PDFs to analyze both text and visual content within documents.
777775 
778We also released new official SDKs:
776* We also released new official SDKs:
779777 
780* [Java SDK](https://github.com/anthropics/anthropic-sdk-java) (alpha)
781* [Go SDK](https://github.com/anthropics/anthropic-sdk-go) (alpha)
778 * [Java SDK](https://github.com/anthropics/anthropic-sdk-java) (alpha)
779 * [Go SDK](https://github.com/anthropics/anthropic-sdk-go) (alpha)
782780 
783### December 4th, 2024
781### December 4, 2024
784782 
785783* We’ve added the ability to group by API key on the [Usage](https://console.anthropic.com/settings/usage) and [Cost](https://console.anthropic.com/settings/cost) pages of the [Developer Console](https://console.anthropic.com).
786784* We’ve added two new **Last used at** and **Cost** columns and the ability to sort by any column on the [API keys](https://console.anthropic.com/settings/keys) page of the [Developer Console](https://console.anthropic.com).
787785 
788### November 21st, 2024
786### November 21, 2024
789787 
790788* We’ve released the [Admin API](https://platform.claude.com/docs/en/manage-claude/admin-api), allowing users to programmatically manage their organization’s resources.
791789 
792### November 20th, 2024
790### November 20, 2024
793791 
794792* We’ve updated our rate limits for the Messages API. We’ve replaced the tokens per minute rate limit with new input and output tokens per minute rate limits. Read more in [Rate limits](https://platform.claude.com/docs/en/api/rate-limits).
795793* We’ve added support for [tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview) in the [Console Workbench](https://console.anthropic.com/workbench).
796794 
797### November 13th, 2024
795### November 13, 2024
798796 
799797* We’ve added PDF support for all Claude Sonnet 3.5 models. Read more in [PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support).
800798 
801### November 6th, 2024
799### November 6, 2024
802800 
803801* We’ve retired the Claude 1 and Instant models. Read more in [Model deprecations](https://platform.claude.com/docs/en/about-claude/model-deprecations).
804802 
805### November 4th, 2024
803### November 4, 2024
806804 
807805* [Claude Haiku 3.5](https://www.anthropic.com/claude/haiku) is now available on the Claude API as a text-only model.
808806 
809### November 1st, 2024
807### November 1, 2024
810808 
811809* We’ve added PDF support for use with the new Claude Sonnet 3.5. Read more in [PDF support](https://platform.claude.com/docs/en/build-with-claude/pdf-support).
812810* We’ve also added token counting, which allows you to determine the total number of tokens in a Message prior to sending it to Claude. Read more in [Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting).
813811 
814### October 22nd, 2024
812### October 22, 2024
815813 
816814* We’ve added Anthropic-defined computer use tools to our API for use with the new Claude Sonnet 3.5. Read more in [Computer use tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool).
817815* Claude Sonnet 3.5, our most intelligent model yet, just got an upgrade and is now available on the Claude API. Read more in the [Claude Sonnet documentation](https://www.anthropic.com/claude/sonnet).
818816 
819### October 8th, 2024
817### October 8, 2024
820818 
821819* The Message Batches API is now available in beta. Process large batches of queries asynchronously in the Claude API for 50% less cost. Read more in [Batch processing](https://platform.claude.com/docs/en/build-with-claude/batch-processing).
822820* We’ve loosened restrictions on the ordering of `user`/`assistant` turns in our Messages API. Consecutive `user`/`assistant` messages will be combined into a single message instead of erroring, and we no longer require the first input message to be a `user` message.
823821* We’ve deprecated the Build and Scale plans in favor of a standard feature suite (formerly referred to as Build), along with additional features that are available through sales. Read more in our [API pricing information](https://claude.com/platform/api).
824822 
825### October 3rd, 2024
823### October 3, 2024
826824 
827825* We’ve added the ability to disable parallel tool use in the API. Set `disable_parallel_tool_use: true` in the `tool_choice` field to ensure that Claude uses at most one tool. Read more in [Parallel tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/parallel-tool-use).
828826 
829### September 10th, 2024
827### September 10, 2024
830828 
831829* We’ve added Workspaces to the [Developer Console](https://console.anthropic.com). Workspaces allow you to set custom spend or rate limits, group API keys, track usage by project, and control access with user roles. Read more in our [Workspaces blog post](https://www.anthropic.com/news/workspaces).
832830 
833### September 4th, 2024
831### September 4, 2024
834832 
835833* We announced the deprecation of the Claude 1 models. Read more in [Model deprecations](https://platform.claude.com/docs/en/about-claude/model-deprecations).
836834 
837### August 22nd, 2024
835### August 22, 2024
838836 
839837* We’ve added support for usage of the SDK in browsers by returning CORS headers in the API responses. Set `dangerouslyAllowBrowser: true` in the SDK instantiation to enable this feature.
840838 
841### August 19th, 2024
839### August 19, 2024
842840 
843841* 8,192-token outputs on Claude Sonnet 3.5 are out of beta and no longer require the `max-tokens-3-5-sonnet-2024-07-15` header.
844842 
845### August 14th, 2024
843### August 14, 2024
846844 
847845* [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching) is now available as a beta feature in the Claude API. Cache and re-use prompts to reduce latency by up to 80% and costs by up to 90%.
848846 
849### July 15th, 2024
847### July 15, 2024
850848 
851849* Generate outputs up to 8,192 tokens in length from Claude Sonnet 3.5 with the new `anthropic-beta: max-tokens-3-5-sonnet-2024-07-15` header.
852850 
853### July 9th, 2024
851### July 9, 2024
854852 
855853* Automatically generate test cases for your prompts using Claude in the [Developer Console](https://console.anthropic.com).
856854* Compare the outputs from different prompts side by side in the new output comparison mode in the [Developer Console](https://console.anthropic.com).
857855 
858### June 27th, 2024
856### June 27, 2024
859857 
860858* View API usage and billing broken down by dollar amount, token count, and API keys in the new [Usage](https://console.anthropic.com/settings/usage) and [Cost](https://console.anthropic.com/settings/cost) tabs in the [Developer Console](https://console.anthropic.com).
861859* View your current API rate limits in the new [Rate Limits tab](https://console.anthropic.com/settings/limits) in the [Developer Console](https://console.anthropic.com).
862860 
863### June 20th, 2024
861### June 20, 2024
864862 
865863* [Claude Sonnet 3.5](https://www.anthropic.com/news/claude-3-5-sonnet), our most intelligent model yet, is now available across the Claude API, Amazon Bedrock, and Vertex AI.
866864 
867### May 30th, 2024
865### May 30, 2024
868866 
869867* [Tool use](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview) is out of beta across the Claude API, Amazon Bedrock, and Vertex AI, with no beta header required.
870868 
871### May 10th, 2024
869### May 10, 2024
872870 
873871* Our prompt generator tool is now available in the [Developer Console](https://console.anthropic.com). The prompt generator helps you guide Claude to generate high-quality prompts tailored to your specific tasks. Read more in our [prompt generator blog post](https://www.anthropic.com/news/prompt-generator).
874872 

build-with-claude/prompt-caching Changed · +1 / -1 lines

from line 913
913913 
914914## Pre-warming the cache
915915 
916Cache pre-warming lets you load your system prompt or tool definitions into the prompt cache before a user triggers a real request. This eliminates the cache-miss latency penalty on the first user interaction, reducing time-to-first-token (TTFT) for latency-sensitive applications.
916Cache pre-warming lets you load your system prompt or tool definitions into the prompt cache before a user triggers a real request. This can reduce the cache-miss latency penalty on the first user interaction, lowering time-to-first-token (TTFT) for latency-sensitive applications.
917917 
918918### How it works
919919 
Feedback