> ## Documentation Index
> Fetch the complete documentation index at: https://docs.endorlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect the Anthropic Compliance API

> Enroll your Claude Enterprise directory so Coding Agent Governance can match Claude Code sessions to organization roles and groups.

Connect the Anthropic Compliance API to give Coding Agent Governance the organization identity behind each Claude Code session. Endor Labs syncs your Claude Enterprise directory on a schedule and resolves each session to a directory entry by corporate email. Session policies can then match on the developer's organization role or group, and audit records carry a real identity instead of a laptop login.

Enrollment runs through the REST API today. The Endor Labs user interface does not expose it yet.

## How it works

After you enroll, three things happen:

* **Sync**: Endor Labs pulls the organizations, users, groups, and group members from your Claude Enterprise directory on a schedule. It stores one directory entry per user in your namespace, keyed by corporate email.
* **Resolve**: At the start of a Claude Code session, the hook looks up the developer's Claude account email in the synced directory. It caches the result for the session, so no later tool call pays for the lookup.
* **Match**: Session policies with `role_matchers` or `group_matchers` evaluate against the resolved roles and groups. A session with no resolved identity skips those policies, so an unknown developer is never blocked by mistake.

## Before you begin

Confirm the following requirements before you enroll:

* Your Claude Enterprise organization has the Compliance API enabled. A primary owner enables it in claude.ai under **Organization settings** > **API**.
* You are a primary owner or an organization owner in claude.ai. A primary owner can create a key that covers every organization under the parent organization. An organization owner can create a key for their own organization only.
* You have the **Admin** role in the Endor Labs namespace that owns your Coding Agent Governance policies, either as a user or through an API key.
* [endorctl](/setup-deployment/cli) is installed, or you have a way to call the [REST API](/developers-api/rest-api) directly.
* Developers sign in to Claude Code with their Claude Enterprise account. Resolution keys on that account's email. See [How Endor Labs matches a developer](#how-endor-labs-matches-a-developer) to check how a session resolves.

## Create a Compliance Access Key

Create the key in claude.ai, not in Claude Console. Admin API keys (`sk-ant-admin01-`) and Claude API keys (`sk-ant-api03-`) do not work, and enrollment rejects them.

1. Decide which organizations the key covers. A parent-organization key reaches every linked organization from one enrollment, and a single-organization key reaches one.
2. Sign in to claude.ai with a role that can create the key you decided on. Only a primary owner of the parent organization can create a parent-organization key.
3. In claude.ai, select **Organization settings** > **API**.
4. Under **Keys**, click **Create key**.
5. Enter a name, such as `endor-labs-directory-sync`.
6. Select the scopes `read:compliance_org_data` and `read:compliance_user_data`, leave every other scope clear, then click **Create**.
7. Copy the key, which starts with `sk-ant-api01-`. claude.ai shows it only once.
8. Store the key in your secret manager until you complete the enrollment.

The two scopes cover the four calls the sync makes. Organizations and groups need `read:compliance_org_data`. Users and group members need `read:compliance_user_data`. Scopes are immutable after creation, so create a new key to change them.

<Warning>
  A key with `read:compliance_user_data` can also read chats, files, and session transcripts through the Compliance API. Endor Labs never calls those endpoints and stores the key encrypted in the platform secret manager, but treat the key as a production credential. Never add `delete:compliance_user_data`.
</Warning>

For more information, refer to [Set up the Compliance API](https://platform.claude.com/docs/en/manage-claude/compliance-api-access).

## Enroll your organization

Create a `ComplianceEnrollment` resource in the namespace that owns your Coding Agent Governance policies. Replace `<namespace>` with that namespace and `<compliance-access-key>` with the key you created.

```bash theme={null}
endorctl api create -r ComplianceEnrollment -n "<namespace>" --data '{
  "meta": { "name": "anthropic-compliance" },
  "spec": {
    "access_token": "<compliance-access-key>",
    "enabled": true
  }
}'
```

The request carries the following fields:

* `spec.access_token`: The Compliance Access Key. Required. Endor Labs validates it against the Compliance API before it stores it, encrypts it, and never returns it. Reads show a redacted placeholder instead.
* `spec.enabled`: Whether the sync runs. Defaults to `true`. Set it to `false` later to pause the sync without discarding the key.
* `meta.name`: Optional. Defaults to `Anthropic Compliance Enrollment` when you omit it.

Endor Labs rejects the request with a `400` status when the key is the wrong kind:

* A key that can call the Anthropic model API, or that holds organization admin access, is too broad. Create a compliance key with only the two directory scopes.
* A key that reaches no organization, or that reads organizations but not users, is too narrow. Add the missing scope on a new key.

When the Compliance API is unreachable, the check is inconclusive and the enrollment proceeds. The same validation runs whenever you rotate the key.

A namespace holds one enrollment. A second create returns a `409` status, because the sync reconciles the whole namespace against one directory.

## What the sync stores

Endor Labs runs the sync every six hours. The sync stores one `AgentDirectoryEntry` per directory user in your namespace and reconciles the set on every run. It creates entries for new users, refreshes existing ones, and deletes users who left the directory. Each entry carries the following fields:

* `meta.name`: The user's corporate email. This is the key the hook resolves against.
* `spec.identity.email` and `spec.identity.display_name`: The email and full name from the directory.
* `spec.identity.roles`: The user's built-in Anthropic organization role, such as `admin`, `billing`, `claude_code_user`, `developer`, `owner`, `primary_owner`, or `user`. Endor Labs stores the value Anthropic returns and does not expand custom RBAC role names.
* `spec.identity.groups`: The names of every Claude organization group the user belongs to.
* `spec.organization_uuid`: The Claude organization that the entry came from.

<Note>
  A directory entry names a person, so the sync brings your employee roster into your Endor Labs namespace. Review this data flow with your privacy team before you enroll.
</Note>

## Verify the sync

Confirm the enrollment exists and is enabled. The `access_token` field shows the redacted placeholder, never the key.

```bash theme={null}
endorctl api list -r ComplianceEnrollment -n "<namespace>"
```

After the next sync run, look up one developer you know is in the directory. Replace `<developer-email>` with their corporate email.

```bash theme={null}
endorctl api list -r AgentDirectoryEntry -n "<namespace>" --filter 'meta.name=="<developer-email>"'
```

The response lists one entry with the developer's roles and groups under `spec.identity`. An empty list means the sync has not run yet, or the email is not in your Claude Enterprise directory.

A tenant credential must filter on exactly one email, in the form `meta.name=="<email>"`. Endor Labs refuses any other filter, including no filter, with a `400` status, so no single request can return your whole directory. Only the Endor Labs sync itself lists the directory in bulk.

## How Endor Labs matches a developer

At the start of every Claude Code session, the hook resolves the developer's email and looks it up in the synced directory. It tries the following sources in order and uses the first one that answers:

1. The Claude account the developer is signed in to, read from `claude auth status`. Only a first-party Claude login counts. Sessions authenticated with an API key or a non-Anthropic provider, such as Amazon Bedrock, Google Vertex AI, or Microsoft Foundry, report no account email.
2. The account record in the local Claude Code configuration. The hook reads it only when `claude auth status` cannot answer at all, because the binary is missing, times out, or returns output the hook cannot parse. It also skips the record when the environment shows Claude Code authenticating with something other than a Claude account login, such as an API key or a cloud provider.
3. The `CLAUDE_CODE_USER_EMAIL` environment variable, when `CLAUDE_CODE_ACCOUNT_UUID` and `CLAUDE_CODE_ORGANIZATION_UUID` are also set.
4. The `ENDOR_ACTOR` environment variable, which your managed Claude Code settings can set in the same `env` block that carries the Endor Labs credentials. See [Deploy hooks for Claude Code](/agent-governance/claude-code) to find that block.
5. The operating system login.

The hook looks up only a value that contains `@`, because directory entries are keyed by corporate email. The lookup has a two-second deadline. When it times out, the server is unreachable, or the email is not in the directory, the session runs with no identity. Sub-agent sessions inherit the organization identity resolved for their parent session.

Resolution therefore depends on developers signing in to Claude Code with their Claude Enterprise account. The hook asserts the email from the developer's own machine and does not authenticate it, so treat identity policies as a guardrail, not a security boundary.

## Use identity in a policy

Set `role_matchers` and `group_matchers` on the `top_level` group of a session policy. Both are regex lists, and any match counts. The policy form does not expose these fields yet, so create and edit such policies through the REST API. See [Match on developer identity](/agent-governance/policies#match-on-developer-identity) to learn the matching rules.

The following example alerts on every Claude Code session started by a developer in the `contractors` group.

```bash theme={null}
endorctl api create -r AgentHookPolicyDefinition -n "<namespace>" --data '{
  "meta": { "name": "alert-contractor-sessions" },
  "spec": {
    "policy": {
      "name": "Alert on contractor sessions",
      "enabled": true,
      "activity": { "session": { "top_level": { "group_matchers": ["^contractors$"] } } },
      "action": {
        "match_type": "MATCH_TYPE_BLOCKLIST",
        "alert": { "message": "A contractor started a governed Claude Code session." }
      }
    }
  },
  "propagate": true
}'
```

Hooks pick the policy up at the next session start.

## Pause, rotate, or remove the enrollment

Every command below needs the enrollment UUID. Capture it once.

```bash theme={null}
UUID=$(endorctl api list -r ComplianceEnrollment -n "<namespace>" | jq -r '.list.objects[0].uuid')
```

Endor Labs records every create, update, and delete of the enrollment in the audit log.

### Pause the sync

To pause the sync and keep the synced entries, set `spec.enabled` to `false`. Set it back to `true` to resume. A paused enrollment keeps its roster, so identity policies keep matching against the last sync.

```bash theme={null}
endorctl api update -r ComplianceEnrollment -n "<namespace>" --uuid "$UUID" \
  --field-mask spec.enabled --data '{ "spec": { "enabled": false } }'
```

### Rotate the key

To rotate the key, create a new Compliance Access Key with the same scopes, then update `spec.access_token`. Endor Labs validates the new key before it stores it. Delete the old key in claude.ai after the update succeeds.

```bash theme={null}
endorctl api update -r ComplianceEnrollment -n "<namespace>" --uuid "$UUID" \
  --field-mask spec.access_token --data '{ "spec": { "access_token": "<new-compliance-access-key>" } }'
```

### Remove the enrollment

To remove the enrollment, delete it. The next sync run purges every directory entry in the namespace, and sessions run with no identity from then on. Delete the key in claude.ai as well.

```bash theme={null}
endorctl api delete -r ComplianceEnrollment -n "<namespace>" --uuid "$UUID"
```

## Limitations

The Compliance API connection has the following limits:

* Identity resolution runs for Claude Code sessions only. Cursor, Codex, and GitHub Copilot sessions carry no organization identity.
* `role_matchers` and `group_matchers` apply to session-level policies only. Tool, command, and file events do not match on identity.
* Identity policies fail open. A session with no resolved identity skips them, and the hook never blocks a developer because a lookup failed.
* The developer's machine asserts the email. Endor Labs does not authenticate it against the directory.
* Role and group changes reach policy evaluation only after the next sync run. See [What the sync stores](#what-the-sync-stores) to find the sync schedule.
* One enrollment per namespace. The sync reconciles the whole namespace against one directory.
* The sync reaches only the organizations the key covers. A primary owner's parent-organization key covers every linked organization, and an organization owner's key covers one.
* The policy form does not expose identity criteria. Manage identity criteria and enrollment through the REST API.

## Next steps

Continue with the following pages:

* See [Match on developer identity](/agent-governance/policies#match-on-developer-identity) to write session policies that use roles and groups.
* See [Deploy hooks for Claude Code](/agent-governance/claude-code) to put hooks on the developer machines that resolve identity.
* See [Triage policy violations](/agent-governance/policy-violations) to review the sessions your identity policies flag.
