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

# Organization administration

> Manage organizations, audit events, Microsoft Entra mappings, and service accounts

Organization administrators can perform the same governance and identity tasks
through the Python SDK that are available under **Settings → Organizations**.
The calling user or service account must be an administrator of the target
organization or a configured deployment-level organization provisioner.

A customer-hosted deployment can also designate specific service-account IDs
as organization provisioners. A provisioner can create and configure
organizations without becoming a member or receiving access to their data.

## Bootstrap and account ownership

Deployment-level provisioners must be **service accounts**, not human users:

1. A human recovery administrator creates or selects a trusted IT automation
   organization, then creates a service account with the explicit `admin`
   organization role inside it. Resource permission is configured separately.
2. Add that **Docent service-account UUID** to the deployment's Terraform
   configuration:

   ```hcl theme={null}
   organization_provisioner_service_account_ids = [
     "<docent-service-account-uuid>",
   ]
   ```

   This is not the creator's user ID, an API key, or an Entra application ID.
   Listing a human-user ID does not grant provisioner authority.
3. Apply Terraform and deploy the updated API task definitions. Automation can
   then authenticate using the service account's own API key, AWS federated
   identity, or Microsoft Entra workload identity, without a human login.

The service account remains owned by its original **home organization**, whose
administrators can manage its credentials. The human creator is recorded for
attribution; the automation does not borrow their credentials or session.
Keep the home organization under trusted IT control and retain a human
recovery administrator. Provisioning authority does not automatically grant
collection-data access.

## Create and update an organization

Creating an organization requires a human identity or a configured provisioner;
an ordinary organization-admin service account cannot create organizations.

```python theme={null}
from docent import Docent

client = Docent(api_key="your-human-or-provisioner-api-key")

organization = client.create_organization(
    "Production evaluation",
    description="Production agent evaluation data",
)
organization_id = organization["id"]

client.update_organization(
    organization_id,
    name="Production evaluation",
    description="Production and pre-release evaluation data",
)
```

For repeatable automation, a configured organization provisioner should use a
stable customer-owned ID. Repeating the call updates the same organization:

```python theme={null}
organization = client.upsert_organization(
    "production",
    name="Production evaluation",
    description="Production and pre-release evaluation data",
)
```

## Manage members

```python theme={null}
members = client.add_organization_member(
    organization_id,
    "operator@example.com",
    role="member",
)

operator = next(member for member in members if member["user"]["email"] == "operator@example.com")
client.update_organization_member_role(organization_id, operator["user"]["id"], "admin")
client.remove_organization_member(organization_id, operator["user"]["id"])
```

Direct membership and Microsoft Entra group membership are independent access
sources. Removing a direct grant does not remove access supplied by a mapped
Entra group. Pass `create_manual_grant=True` only when you intentionally want a
direct grant to remain after the person leaves that group.

## Read and download audit events

List recent events with cursor pagination:

```python theme={null}
from datetime import datetime

events = client.get_organization_audit_events(organization_id, limit=100)

last_event = events[-1]
older_events = client.get_organization_audit_events(
    organization_id,
    limit=100,
    before=datetime.fromisoformat(last_event["created_at"]),
    before_id=last_event["id"],
)
```

`before` must be a timezone-aware `datetime`. To download every event in a
half-open time range—`start_at` is included and `end_at` is excluded—use:

```python theme={null}
from datetime import UTC, datetime

path = client.download_organization_audit_events(
    organization_id,
    start_at=datetime(2026, 8, 1, tzinfo=UTC),
    end_at=datetime(2026, 9, 1, tzinfo=UTC),
    output_path="august-organization-audit.csv",
)
```

The download is streamed to a temporary file and atomically moved to
`output_path` after it succeeds.

## Map a Microsoft Entra group

In an Entra-enabled deployment, Docent searches Microsoft Graph using
the read-only `GroupMember.Read.All` and `User.ReadBasic.All` application
permissions approved by the tenant administrator. Mapping by name is
convenient, while Docent stores the immutable group object ID:

```python theme={null}
mapping = client.set_entra_group_mapping_by_name(
    organization_id,
    "Production operators",
)
print(mapping["group_id"], mapping["group_display_name"])
```

If no security group has that exact display name, or multiple groups share it,
the method raises `ValueError` without changing the mapping. Call
`search_entra_groups` and then `set_entra_group_mapping` when you need to select
an object ID explicitly.

To replace a deleted or renamed group, call either setter again. Replacing the
object ID immediately removes access derived from the old mapping and records
the transition in the audit log. Members of the replacement group receive
access on their next Microsoft sign-in or when an administrator runs a
reconciliation. Direct Docent grants remain intact.

```python theme={null}
client.set_entra_group_mapping(organization_id, "new-group-object-id")
result = client.reconcile_entra_group_memberships(organization_id)
print(result["added"], result["removed"], result["unlinked_entra_users"])
client.clear_entra_group_mapping(organization_id)
```

Reconciliation asks Microsoft Graph for the mapped group's complete transitive
membership and updates Entra-managed Docent grants. Existing sessions reload
organization membership on every request, so additions and removals take
effect immediately without forcing a logout. Users who have never signed in
are reported as `unlinked` and receive access after their first Microsoft
sign-in. A manual Docent grant is independent and is never removed merely
because the user left the Entra group.

When the tenant has organization group mappings, Docent retrieves the user's
complete transitive security-group IDs from Graph during Microsoft sign-in. If
Graph cannot provide the complete list, the sign-in is rejected and existing
group access is not incorrectly retained. Tenants without group mappings do not
depend on this Graph lookup for sign-in.

## Create a service account

```python theme={null}
service_account = client.create_service_account(
    organization_id,
    "Production ingestion",
    permission="write",
    organization_role="member",
    description="Uploads production agent runs",
)
service_account_id = service_account["id"]
```

`permission` caps access to collections and other resources. The independent
`organization_role` controls organization administration and defaults to
`member`. Set `organization_role="admin"` only when the automation must manage
members, identity mappings, service accounts, or audit configuration.

Change the organization role later without changing resource access:

```python theme={null}
client.update_service_account_organization_role(
    organization_id,
    service_account_id,
    "admin",
)
```

### API key

```python theme={null}
credential = client.create_service_account_api_key(
    organization_id,
    service_account_id,
    "Production secret",
)
print(credential["secret"])  # Store once; it is not returned again.
```

### Microsoft Entra workload

```python theme={null}
client.set_service_account_entra_identity(
    organization_id,
    service_account_id,
    client_id="application-client-id",
    service_principal_id="enterprise-application-object-id",
)
```

The enterprise application must have the deployment's service-account app role.

### AWS outbound OIDC workload

```python theme={null}
client.set_service_account_aws_identity(
    organization_id,
    service_account_id,
    role_arn="arn:aws:iam::123456789012:role/production/DocentIngestion",
    oidc_issuer_url="https://issuer-id.tokens.sts.global.api.aws",
)
```

The issuer is account-specific and is required for new AWS outbound OIDC
bindings. Omitting it creates a legacy signed-request binding. See
[Authentication](/sdk/authentication#aws-outbound-oidc) for workload setup.

Disabling a service account revokes all of its API keys, Entra identity, and AWS
identity for subsequent requests:

```python theme={null}
client.disable_service_account(organization_id, service_account_id)
```
