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_matchersorgroup_matchersevaluate 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 is installed, or you have a way to call the 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 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.
- Decide which organizations the key covers. A parent-organization key reaches every linked organization from one enrollment, and a single-organization key reaches one.
- 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.
- In claude.ai, select Organization settings > API.
- Under Keys, click Create key.
- Enter a name, such as
endor-labs-directory-sync. - Select the scopes
read:compliance_org_dataandread:compliance_user_data, leave every other scope clear, then click Create. - Copy the key, which starts with
sk-ant-api01-. claude.ai shows it only once. - Store the key in your secret manager until you complete the enrollment.
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.
For more information, refer to Set up the Compliance API.
Enroll your organization
Create aComplianceEnrollment 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.
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 totrue. Set it tofalselater to pause the sync without discarding the key.meta.name: Optional. Defaults toAnthropic Compliance Enrollmentwhen you omit it.
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.
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 oneAgentDirectoryEntry 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.emailandspec.identity.display_name: The email and full name from the directory.spec.identity.roles: The user’s built-in Anthropic organization role, such asadmin,billing,claude_code_user,developer,owner,primary_owner, oruser. 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.
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.
Verify the sync
Confirm the enrollment exists and is enabled. Theaccess_token field shows the redacted placeholder, never the key.
<developer-email> with their corporate email.
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:- 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. - The account record in the local Claude Code configuration. The hook reads it only when
claude auth statuscannot 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. - The
CLAUDE_CODE_USER_EMAILenvironment variable, whenCLAUDE_CODE_ACCOUNT_UUIDandCLAUDE_CODE_ORGANIZATION_UUIDare also set. - The
ENDOR_ACTORenvironment variable, which your managed Claude Code settings can set in the sameenvblock that carries the Endor Labs credentials. See Deploy hooks for Claude Code to find that block. - The operating system login.
@, 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
Setrole_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 to learn the matching rules.
The following example alerts on every Claude Code session started by a developer in the contractors group.
Pause, rotate, or remove the enrollment
Every command below needs the enrollment UUID. Capture it once.Pause the sync
To pause the sync and keep the synced entries, setspec.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.
Rotate the key
To rotate the key, create a new Compliance Access Key with the same scopes, then updatespec.access_token. Endor Labs validates the new key before it stores it. Delete the old key in claude.ai after the update succeeds.
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.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_matchersandgroup_matchersapply 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 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 to write session policies that use roles and groups.
- See Deploy hooks for Claude Code to put hooks on the developer machines that resolve identity.
- See Triage policy violations to review the sessions your identity policies flag.