Anthropic
The Anthropic integration monitors your Claude organization — members and their roles, workspaces and workspace memberships, API keys, usage and spend limits, and the models your organization can reach — and, depending on the keys you give it, the Claude Enterprise directory (linked organizations, users, groups, roles), the Compliance Activity Feed, and Enterprise analytics for provider-billed cost.
On Claude Enterprise it can also capture AI invocations — each prompt, the files it carried and the tools it used — and block prompts that carry files you have tagged sensitive or that violate your SlashID policies. That part runs in your own Google Cloud project; see step 5.
How credentials work
The connection takes a list of API keys rather than one key per purpose. This is because a key's capabilities are decided by its kind and its scopes, not by which field it was pasted into.
For each group of endpoints SlashID uses whichever of your keys the API accepts, so the order you list them in does not matter. A group no key can reach is skipped, and the connection's health check says which scope was missing.
| What you want | What the key needs | Health check |
|---|---|---|
| Organization (required) | any valid key | key_valid |
| Organization members (required) | an organization-scoped key: a Console Admin API key or a claude.ai key | list_users |
| Workspaces, workspace members, API keys, usage reports, spend limits | api:admin (a Console Admin API key) | list_workspaces, list_api_keys, usage_report, spend_limits, etc. |
| Claude Code activity per identity | api:admin | claude_code_usage |
| Linked organizations, directory users, groups, roles | read:org_audit, or read:compliance_org_data + read:compliance_user_data | compliance_directory |
| Activity Feed (last-activity, activity detections) | read:org_audit, or read:compliance_activities | activity_feed |
| Provider-billed cost, per-user token usage, adoption summaries | read:analytics | analytics |
| Model catalog — reachable-but-unused and retired-but-used models | a regular Console API key (sk-ant-api03-) — a key kind, not a scope | models_catalog |
| Service accounts and workload identity federation | not a key — see step 3 | wif_service_accounts |
read:org_audit is accepted everywhere the read:compliance_* scopes are, so a
single claude.ai key carrying read:org_audit and read:analytics covers the
whole Enterprise surface. The scope vocabulary depends on how a key was minted:
the Compliance API setup flow issues the documented read:compliance_* scopes,
while keys created from claude.ai's API settings page carry the granular
read:members / read:rbac_groups / read:org_audit set instead. Both reach
the same endpoints, so do not judge a key by its scope names — run the health
check.
Every key must belong to the same organization. A Console key and a claude.ai key resolve to different organization UUIDs, so they cannot share a connection — create one connection per organization. If a key disagrees with the connection's Organization ID, preflight fails and names the offending key.
Because of that rule, the model catalog is in practice a Console-organization feature: Admin, compliance and analytics keys are all refused by the Models API, and the regular key that can read it belongs to a Console organization.
Before starting
- Console keys: the admin role in the Claude Console organization.
- claude.ai keys: primary owner or organization owner. Only the primary
owner can enable API access and create a key carrying
read:analytics. - Optional, for service-account and federation visibility: the admin, owner or primary owner role in the Claude Console, to set up workload identity federation.
1. Create your keys
You do not need every key. A Console-only organization uses Console keys; a Claude Enterprise organization uses one claude.ai key. Give SlashID whichever keys describe the surface you want monitored — each secret is shown once, so copy it when you create it.
Console Admin API key
In the Claude Console, go to
Settings → Admin keys
and create an Admin API key (it starts with sk-ant-admin01-). This is the key
that unlocks workspaces, API keys, usage reports, Claude Code activity and spend
limits. It is also the key SlashID acts through when you run a remediation —
deactivating an API key or zeroing a user's spend limit.
Console regular API key (optional)
For the model catalog, in the Claude Console,
go to Settings → API keys and
create a regular API key (it starts with sk-ant-api03-). SlashID only lists
models with it (GET /v1/models) and never runs inference.
claude.ai key (Claude Enterprise)
- Sign in to claude.ai as the primary owner if you
want cost data — no other role can enable API access or create a key with
read:analytics. An organization owner can create a key for the directory and the Activity Feed. - Go to
Organization settings → API
and turn on the toggles for what you want SlashID to read:
- Compliance API — for the directory and the Activity Feed. On a Claude Enterprise tenant the primary owner enables it on the parent organization, and it cascades to every linked organization. See Set up the Compliance API.
- Analytics API, just below it — for provider-billed cost and per-user usage.
- Create a key and select the scopes from the table above:
read:analyticsfor cost, andread:org_audit(or theread:compliance_*scopes) for the directory and the Activity Feed. Scopes cannot be changed after creation, so pick the full set now.
Grant read scopes only. SlashID never writes through a claude.ai key, so a
key carrying write:members, write:rbac_groups, write:plugins,
write:spend_limits or delete:compliance_user_data gives a read-only
integration the ability to modify or destroy your directory. Be aware too that
read:compliance_user_data lets a key read chats, files, projects and session
transcripts across every linked organization; SlashID uses it only for the user
and group-member listings. read:org_audit avoids that grant.
About analytics data: cost and usage figures are actual spend on usage-based
Enterprise plans, but only usage credits on seat-based plans. Data starts at
2026-01-01, lags about a day, and does not cover Claude Code used through Amazon
Bedrock. Without a read:analytics key, SlashID reports Anthropic spend as
estimated from token usage.
2. Find your organization ID
Take the ID from the organization your keys belong to — Console keys and claude.ai keys belong to different organizations with different IDs:
- Console keys: Claude Console → Settings → Organization.
- claude.ai keys: claude.ai → Organization settings → Organization.
Or ask the API with one of the keys you are going to configure — the endpoint answers with the presenting key's own organization:
curl https://api.anthropic.com/v1/organizations/me \
--header "anthropic-version: 2023-06-01" \
--header "x-api-key: $ANTHROPIC_KEY"
SlashID validates at connection time that every configured key returns this value.
3. (Optional) Enable service-account & federation visibility (WIF)
Anthropic's service-account and federation endpoints reject API keys outright;
they only accept an OAuth token with the org:admin scope, minted through
workload identity federation
(WIF). This setup stores no secret with SlashID. Instead, the SlashID
scanner proves who it is with a Google-signed identity token, and you tell
Anthropic to trust that one identity.
You create three things in the Claude Console: an issuer (Google), a service account that SlashID acts as, and a federation rule that maps the scanner's Google identity to that service account. The Connect workload wizard creates all three in one pass.
Before you begin
Ask SlashID support for the scanner identity for your deployment. You need three values:
| Value | Looks like |
|---|---|
| Service account email | svc-<region>@<project>.iam.gserviceaccount.com |
Service account unique ID (sub) | a 21-digit number, for example 104892101234567890123 |
| Google Cloud project ID | the project in the service account email, <project> |
Create the issuer, service account and rule
In the Claude Console, go to Settings → Workload identity and select Connect workload.
Select the Google Cloud tile.
Step 1 — issuer. Keep the issuer URL
https://accounts.google.comand select Continue. If your organization already has a Google issuer, reuse it — one issuer covers every Google workload.Step 2 — federation rule. Fill in the guided fields:
- Rule name: for example
slashid-scanner(lowercase letters, numbers and hyphens). - Description: optional, for example
SlashID identity scanner. - GCP service account email: the email from SlashID support.
- Service account unique ID: the 21-digit ID from SlashID support.
- Project ID: the Google Cloud project ID from SlashID support — the
<project>part of the service account email. The field is required.
The rule then matches only the SlashID scanner's identity: the unique ID is never reused by Google, and the email is the readable name you can recognise later.
Leave the advanced match section below the guided fields alone — subject pattern, additional claim conditions, expected audience and CEL condition. Once you edit it, it takes precedence over the guided fields. In particular, do not enter a subject pattern: a wildcard there would match service accounts across every Google Cloud project. The expected audience can stay blank, since SlashID requests the default Anthropic API audience,
https://api.anthropic.com.- Rule name: for example
Enable in workspaces. Select exactly one workspace — Default is fine — rather than All workspaces (including future ones). SlashID does not name a workspace when it exchanges its token, and a rule enabled for more than one workspace refuses such an exchange.
OAuth scope. Select
org:admininstead ofworkspace:developer. The service-account and federation endpoints SlashID reads accept nothing less. As the wizard notes, organization-level access is not limited by the workspace you picked above.Token lifetime. Keep the default, 10 minutes (600 seconds).
Step 3 — service account. Select an existing service account, or create one:
- Service account name: for example
slashid(lowercase letters, numbers and hyphens). You become its owner. - Description: optional, for example
SlashID identity scanner.
- Service account name: for example
Check the service account's role. Anthropic mints an
org:admintoken only for a service account with the Admin organization role. Before relying on the connection, open the service account in Settings → Workload identity and confirm its role is Admin.Run this from your workload. The last screen says everything is set up and shows a
curlsnippet to run from the workload, with a live Test connection listener. The workload is SlashID's scanner, not yours, so you cannot run the snippet — skip it. The rule, issuer and service account already exist; the test only watches for an exchange and changes nothing. To see a real exchange, finish step 4 and run the SlashID connection's health check: itswif_service_accountscheck performs the same token exchange, and it shows up in the listener if it is still open, and in the authentication history either way.Copy the rule ID (
fdrl_...) and the service account ID (svac_...) — both appear in that snippet, asfederation_rule_idandservice_account_id. They go into the SlashID connection in step 4. You do not need the snippet'sworkspace_id: the rule is enabled in one workspace, so Anthropic selects it.
Never use a subject_prefix, and never a trailing wildcard, for this rule. A
Google sub is an opaque number with no stable prefix, so a wildcard matches
service accounts across every Google Cloud project — any of them could mint
organization-admin tokens for your organization.
4. Create your Anthropic ↔ SlashID integration
Go to the SlashID Console integrations page and create an Anthropic connection:
| SlashID Console field | Description | Example |
|---|---|---|
| Name of the connection | Arbitrary name for this connection | Anthropic Production |
| Organization ID | The UUID from step 2 | b3053f8f-4432-4d3d-... |
| API keys | One or more keys from the same organization, in any order | sk-ant-admin01-... |
| Federation rule ID | Optional — the WIF rule from step 3; requires the service account ID | fdrl_... |
| Service account ID | Optional — the WIF service account from step 3; requires the federation rule ID | svac_... |
| Authoritative status | Whether Anthropic identities are the primary source of truth when reconciling across sources | Primary or Secondary |
5. (Optional) Capture AI invocations
The connection above reads your organization's inventory. Capturing what people actually send to Claude takes a small receiver, the SlashID Anthropic forwarder, deployed with Terraform into a Google Cloud project you own. It pushes each invocation to SlashID as it is observed. The forwarder's own credentials — the Compliance Access Key and the hook's signing secret — stay in that project's Secret Manager and are never sent to SlashID.
The forwarder has two sources. Each is turned on by supplying its credential, and you can run either or both:
| Source | How it works | What it adds |
|---|---|---|
| Inference hook | claude.ai sends every prompt to the forwarder before the model runs, and the forwarder answers allow or deny. | Every prompt, including turns with no tool calls; blocking prompts that carry files tagged sensitive or violate a policy. |
| Compliance reader | Every 5 minutes the forwarder reads the Compliance API: claude.ai chats, Claude Code sessions, and the denials claude.ai recorded. | Uploaded files hashed from their stored copy, the model used, and denials as the user's client saw them. |
Run both in one deployment, pushing to one connection. The two sources describe the same invocations and the forwarder joins them. Two deployments lose the join, and two SlashID connections count each invocation twice.
Before you begin
- Claude Enterprise. Inference hooks are configured by an owner or primary owner.
- For the compliance reader: the Compliance API enabled by the primary
owner (step 1), and a Compliance Access Key carrying
read:compliance_activitiesandread:compliance_user_data. This key reads chat and session transcripts, which is exactly what the reader needs, so keep it separate from the connection's keys. Enablement is not retroactive: nothing from before it was switched on is ever recorded. - A Google Cloud project with billing enabled, and Terraform 1.5 or later
signed in (
gcloud auth application-default login) as an account that can enable APIs and create Cloud Run services, service accounts, Secret Manager secrets, a Firestore database and a Cloud Scheduler job. Project Owner is simplest. - Registry credentials from SlashID support. The forwarder image is not public yet; support gives you a username and a read-only token for it.
- The connection's Event streaming token, from its details page in the SlashID Console. It is how the forwarder authenticates to SlashID.
Deploy the forwarder
The hook's signing secret does not exist until claude.ai has the hook's URL, and the URL does not exist until the forwarder is deployed, so the hook takes two applies.
Add the module to your Terraform configuration:
module "slashid_anthropic_forwarder" {
source = "git::https://github.com/slashid/slashid-ai-forwarders.git//anthropic/deploy/terraform?ref=anthropic-v0.1.1"
project_id = "your-project-id"
region = "us-central1"
slashid_endpoint = "https://api.slashid.com"
slashid_push_token = var.slashid_push_token # the Event streaming token
release_version = "anthropic-v0.1.1"
# Inference hook. A placeholder for the first apply.
hook_signing_secret = var.hook_signing_secret # "whsec_placeholder"
# Compliance reader. Omit both lines to run the hook alone.
compliance_key = var.compliance_key # sk-ant-api01-...
organization_uuid = "b3053f8f-4432-4d3d-..." # from step 2
ghcr_username = var.ghcr_username # from SlashID support
ghcr_token = var.ghcr_token
}
output "hook_url" {
value = module.slashid_anthropic_forwarder.hook_url
}Pass the secrets as sensitive variables rather than writing them into the file. For a compliance-only deployment, leave out
hook_signing_secret: the forwarder then has no public endpoint at all.Run
terraform applyand copy thehook_urloutput.In claude.ai, as an owner, open Organization settings and configure
hook_urlas the Inference hooks endpoint.Copy the signing secret claude.ai generates (
whsec_...), set it ashook_signing_secret, and apply again. Until then the forwarder rejects every request with 401.Use claude.ai's Test connection to confirm the forwarder answers.
Roll out enforcement
A new deployment only observes: the module's shadow_mode defaults to true,
and while it is on every prompt is allowed and the verdict the forwarder would
have given is recorded beside it. claude.ai has a shadow mode of its own; when
either is on, nothing is blocked. That record is the only way to see what
enforcement would have blocked, because claude.ai logs a denial only when it
is honored.
To enforce:
- Set
preflight_enabled = true. Each prompt is then checked by SlashID before the model runs: it is denied if it carries a file you have tagged sensitive or violates one of your policies. - Choose
verdict_fail_mode:allow(the default) lets a prompt through when the check cannot answer in time, anddenyblocks it. - Set
shadow_mode = falseand apply. - Take claude.ai through its own staged rollout: shadow mode, a rollout percentage, role exclusions, then enforcement.
A denial is sticky. The blocked content stays in the conversation, so every later prompt in it is denied too, and the person has to start a new conversation. The denial message they see says so.
With a rollout percentage below 100 and no compliance reader, the turns claude.ai does not send to the hook are not recorded at all.
Verification
Run the connection's health check. Three checks are required:
key_valid— at least one key authenticates.organization_id_matches— every key belongs to the configured organization.list_users— the connection can list organization members.
Every other data slice has its own optional check (the right-hand column of the
table in How credentials work). An optional check that
fails does not block the sync; it names the scope or key kind that would unlock
the slice and what you lose without it — for example, spend_limits failing
means no key carries api:admin, so provider spend limits and native budget
enforcement are skipped.
If you deployed the forwarder (step 5), claude.ai's Test connection confirms the hook answers. Invocations are recorded shortly after the next prompt in the same conversation, or within an hour of the last one; the compliance reader adds its records every 5 minutes, a few minutes behind.
Troubleshooting
key_validfails / 401 — a key is invalid or revoked. Anthropic shows a key's secret once at creation, so a lost key must be replaced rather than recovered.organization_id_matchesfails — one of the keys belongs to a different organization. The message names the key by position and shows it redacted the way claude.ai does (sk-ant-api01-L3g..._wAA) so you can find it in the console. Remove it, or correct the Organization ID; keys from two different organizations cannot share a connection.list_usersfails — no key in the list is organization-scoped. A regular (sk-ant-api03-) key cannot list members on its own; add a Console Admin API key or a claude.ai key.list_workspaces,list_org_workspace_members,list_api_keys,usage_report,claude_code_usageorspend_limitsunavailable — no key carriesapi:admin. Add a Console Admin API key.compliance_directoryoractivity_feedunavailable — no key carriesread:org_audit(or the equivalentread:compliance_*scopes), or the Compliance API is not enabled for the organization. A key that falls short gets a 403 naming both sides, which is the authoritative answer:Missing required scopes. Got: [...] Needed one of: ['read:compliance_activities', 'read:org_audit']. Scopes cannot be edited, so the fix is a replacement key. Admin API keys pick upread:compliance_activitiesonly if the Compliance API was already enabled when the key was created; enabling it afterwards does not retrofit an existing key, so mint a new one.analyticsunavailable, or spend reads as fully estimated — no key carriesread:analytics, or the Analytics API toggle is off in Organization settings → API. Only the primary owner can switch it on and create such a key (step 1). With the check passing, remember that no cost data exists before 2026-01-01 or for Claude Code used through Amazon Bedrock.models_catalogunavailable — no key in the list is a regular (sk-ant-api03-) API key. Admin, compliance and analytics keys cannot read the Models API. Add a regular key from the same Console organization.wif_service_accountsfails — open the Console's authentication history: every failed exchange is logged there with the reason, while the API itself only ever answersAuthentication failed. The usual causes:- a claim mismatch — the rule's
sub,emailor audience differs from the values in step 3; workspace_id_required— the rule is enabled for more than one workspace; bind it to one;- the exchange succeeds but the endpoints answer 403 — the rule's scope is
not
org:admin, or the service account is not an admin.
- a claim mismatch — the rule's
AI invocation capture
terraform applyrefuses with "Set hook_signing_secret … compliance_key …" — neither source has a credential. Supply at least one.- Revisions fail to start with an image pull error — the registry credentials from SlashID support are missing or expired.
- claude.ai's Test connection fails with 401 —
hook_signing_secretdoes not match the secret claude.ai generated, or the second apply has not run. To rotate without downtime, set both secrets comma-separated (whsec_new,whsec_old), then drop the old one once claude.ai has switched. - No invocations appear — the push token is not the connection's current
Event streaming token. Recreating the connection issues a new one; update
slashid_push_tokenand apply. - The compliance reader records nothing — the Compliance API was enabled
after the activity you expect (it is not retroactive), the key lacks
read:compliance_user_dataorread:compliance_activities, ororganization_uuidnames a different organization than the one the activity happened in.