Skip to main content

claude-compliance-sdk

This is a community Python SDK for the Anthropic Compliance API — the API that lets you access Claude activity logs, chat data, and file content programmatically.

The Compliance API requires an Enterprise plan, and primary owners can enable it using the guide here.

Unofficial. This is a community-maintained project. It is not produced, endorsed, or supported by Anthropic.

📚 Read the documentation — full API reference, generated from the source.

Features

  • Complete coverage of all Compliance API endpoints, including the Activity Feed, Chats, Messages, Files, Projects, Groups, Users, Roles, Permissions, Organisations, and session transcripts from Cowork and Claude Code.
  • Full sync + async parity. Every resource method is available on both ComplianceClient and AsyncComplianceClient under the same name.
  • Typed responses as plain dataclasses. Unknown response fields are preserved in an extra: dict so a future API revision adding a field cannot break the SDK.
  • Built-in retry with exponential backoff that treats Retry-After as a floor, plus rate limiting driven by the server's own anthropic-ratelimit-* headers — the client waits for the stated reset instead of spending a request to discover a 429.
  • Streamed downloads with a configurable memory ceiling — switch from eager bytes to download_to_file() or download_stream() for anything larger.
  • Typed exception hierarchy. Every API error maps to a catchable class — InvalidAPIKeyError, InsufficientScopeError, NotFoundError, ConflictError, RateLimitError, and the rest.
  • Tracks the hosted Anthropic Compliance API docs, snapshotted under spec-snapshots/ so upstream changes are visible as a diff.

Requirements

Python 3.11+.

Install

Install from PyPI with pip:

pip install claude-compliance-sdk

Or install from source:

git clone https://github.com/PaperMtn/claude-compliance-sdk.git
cd claude-compliance-sdk
python -m pip install .

Documentation

Full API reference docs are available at papermtn.github.io/claude-compliance-sdk.

Quickstart

Sync

from claude_compliance_sdk import ComplianceClient

with ComplianceClient(api_key="sk-ant-api01-...") as client:
    for activity in client.activities.iter(
        activity_types=["claude_chat_created", "api_key_created"],
        limit=100,
    ):
        print(activity.created_at, activity.type, activity.id)

Async

import asyncio

from claude_compliance_sdk import AsyncComplianceClient


async def main() -> None:
    async with AsyncComplianceClient(api_key="sk-ant-api01-...") as client:
        async for activity in client.activities.iter(limit=100):
            print(activity.created_at, activity.type)


asyncio.run(main())

Every resource group on both clients exposes the same method names — swap ComplianceClient for AsyncComplianceClient, sprinkle await, done.

Authentication

Two key types reach the Compliance API, and which you need depends on what you are querying.

Key type Created in Reaches
Compliance Access Key (sk-ant-api01-...) claude.ai → Organization settings → API Every endpoint
Admin API key (sk-ant-admin01-...) Claude Console → Settings → Admin keys The Activity Feed only — everything else returns 403

A Compliance Access Key is created by a primary owner or organisation owner. A primary owner's key can cover every organisation under the parent; an organisation owner's key covers their own organisation only. Admin API keys carry read:compliance_activities only if the Compliance API was already enabled for the organisation when the key was created, and cannot be granted any other Compliance scope.

Scopes are chosen at creation and are immutable — to change them, create a new key and delete the old one.

Scope Unlocks
read:compliance_activities Activity Feed (activities)
read:compliance_user_data Chats, messages, files, projects, session transcripts, organisation users, group members
delete:compliance_user_data Deleting chats, files, and projects
read:compliance_org_data Organisations, roles, permissions, groups, and effective organisation settings

Pick the smallest set that works. An audit pipeline that only reads the feed needs read:compliance_activities. If your workflow both reads and deletes, use two keys so a leaked read key cannot delete data.

A key with read:compliance_user_data can read every chat, file, project, and session transcript in every linked organisation. Treat these keys like production database credentials.

The separate read:compliance_org_settings scope was retired on 2026-06-30. A key carrying only that scope now returns 403 from the settings endpoint; read:compliance_org_data replaces it.

Authentication and authorisation failures surface as typed exceptions: a 401 (invalid or revoked key) becomes InvalidAPIKeyError, and a 403 becomes PermissionDeniedError — refined to InsufficientScopeError when the key is valid but missing the scope the endpoint needs. The 403 message names both what the key carries and what the endpoint wanted, and is available on error_message.

Pass the key when constructing the client:

import os

client = ComplianceClient(api_key=os.environ["ANTHROPIC_COMPLIANCE_ACCESS_KEY"])

Or set the environment variable and let the client read it:

export ANTHROPIC_COMPLIANCE_ACCESS_KEY=sk-ant-api01-...
client = ComplianceClient()

The legacy ANTHROPIC_COMPLIANCE_API_KEY name this SDK shipped with is still read as a fallback, so existing deployments keep working.

Pagination

Two types of pagination are used:

  • Cursor-paginated — Activity Feed, Chats, Messages. Pages carry first_id / last_id / has_more.
  • Offset-paginated — everything else. Pages carry has_more and an opaque next_page token.

Every paginated resource exposes both .list() (one page at a time) and .iter() (auto-paginate — yields items one at a time across all pages) functions.

# .list() — explicit page boundaries
page = client.projects.list(limit=20)
for project in page.data:
    print(project.id)
if page.has_more:
    next_page = client.projects.list(limit=20, page=page.next_page)

# .iter() — auto-paginate
for project in client.projects.iter(organization_ids=["org_abc123"]):
    print(project.id)

Cursor resources are identical in shape; the page contains last_id and you pass it back as after_id.

Session transcripts

Transcripts of the sessions your users run in Claude apps — Cowork, Claude Code, Claude Science, and Claude for Microsoft 365 — come from two resource groups, split by where the session ran:

Resource group Covers ID prefix
client.local_sessions Cowork in Claude Desktop, Claude Code (terminal, desktop, IDE), Claude Science, Claude for Microsoft 365 — all on the user's own machine clls_
client.remote_sessions Cowork started on claude.ai web or mobile, running in Anthropic-managed cloud environments cse_

If you are looking for Claude Code usage, it is local_sessions.

with ComplianceClient() as client:
    for session in client.local_sessions.iter(created_at_gte="2026-07-01T00:00:00Z"):
        if session.product_surface != "claude_code":
            continue
        for message in client.local_sessions.iter_messages(session.id):
            print(session.id, message.role, message.content)

Both groups are read-only — sessions cannot be deleted through the Compliance API. Transcript content blocks (text, tool_use, tool_result) are returned as plain dicts so block types that have not shipped yet pass through rather than breaking parsing. Note that a tool_use block's input is a JSON-encoded string, and a truncated one is not valid JSON — raise tool_use_input_max_bytes (or pass -1 for the server maximum) if you need to parse it.

Two errors are worth catching by name. LocalSessionsUnavailableError is a 404 meaning the endpoints are off for your parent organisation, not that a session is gone — keep your queued IDs and retry later. LocalSessionsRetentionUnavailableError is a 503 that is not transient; skip that session and come back to it on a later run.

Downloads

Three resource groups expose binary content — user files, assistant- generated files, and artifacts. Each provides the same three download methods:

# Into memory, bounded by max_download_bytes (default 100 MiB).
data: bytes = client.files.download("claude_file_xyz789")

# Streamed to disk — unbounded.
client.files.download_to_file("claude_file_xyz789", "/tmp/report.pdf")

# Caller-managed streaming — yields bytes; connection closes when the
# iterator is exhausted or garbage-collected.
for chunk in client.files.download_stream("claude_file_xyz789"):
    handle(chunk)

The max_download_bytes cap protects memory on the memory path only. download_to_file and download_stream ignore the cap and always stream, so you can use them for anything larger than the cap.

client = ComplianceClient(max_download_bytes=10 * 1024 * 1024)  # 10 MiB cap

try:
    data = client.files.download("claude_file_big")
except FileTooLargeError as exc:
    print(f"{exc.size_bytes} bytes > {exc.max_bytes} cap — switching to stream")
    client.files.download_to_file("claude_file_big", "big.bin")

User files are deletable (.delete()). Generated files and artifacts are not.

Rate limits

The API allows 600 requests per minute per parent organisation — one budget shared across every key beneath it and every /v1/compliance/* endpoint. The SDK reads the server's anthropic-ratelimit-* headers on every response and waits for the stated reset once the budget is spent.

client.activities.list(limit=100)

status = client.rate_limit_status  # None until the first response
if status and status.remaining is not None and status.remaining < 50:
    ...  # Slow your workers: the budget is shared with other consumers.

rate_limit_rpm caps how fast this client issues requests. 0 disables that local window; the server-reported budget is still honoured, because it is not something a caller can opt out of.

The remote session endpoints carry a second budget on top of the shared one, so a 429 there can arrive well below 600 rpm.

Configuration

ComplianceClient and AsyncComplianceClient accept the same kwargs:

Kwarg Default What it does
api_key env ANTHROPIC_COMPLIANCE_ACCESS_KEY, then ANTHROPIC_COMPLIANCE_API_KEY Compliance Access Key or Admin API key.
base_url https://api.anthropic.com Override for testing.
timeout 30.0 Per-request timeout, seconds.
max_download_bytes 100 * 1024 * 1024 Eager-download cap.
max_retries 3 Retry attempts on 429/5xx and connect errors. 0 disables.
rate_limit_rpm 600 Local burst smoothing for this client. 0 disables the local window. See the note below.
anthropic_version "2023-06-01" Sent as the anthropic-version header on every request. None suppresses it.

On rate_limit_rpm: this caps how fast a single client issues requests, which matters for a cold burst before the first response arrives. Once responses start coming back, the SDK throttles on the server's own anthropic-ratelimit-* headers instead, so you no longer need to divide 600 by your worker count. Setting 0 disables the local window only — the shared server budget is still honoured. See Rate limits.

Contributing

See CONTRIBUTING.md for the dev setup, branch model, coding conventions, and PR checklist. Architecture decisions worth preserving live as numbered ADRs under adr/.

License

GPL-3.0-or-later. See LICENSE.

Release files for claude-compliance-sdk 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for claude-compliance-sdk 0.3.0
File Size Uploaded
claude_compliance_sdk-0.3.0.tar.gz 67.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for claude-compliance-sdk 0.3.0
File Interpreter ABI Platform
claude_compliance_sdk-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 151.4 kB

Release files / claude_compliance_sdk-0.3.0.tar.gz

Download URL claude_compliance_sdk-0.3.0.tar.gz
Size 67.0 kB
Tags Source
SHA-256 checksum
How to use checksums
fca2e422d898469cda9cc29c1ae71dfd742f138d232ef166eb8297abe328ac49
BLAKE2b-256 checksum
How to use checksums
d19131efa860ba667a5ef9a878a196fa6a1c220388fbe597a3e1885bf4f411b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release files / claude_compliance_sdk-0.3.0-py3-none-any.whl

Download URL claude_compliance_sdk-0.3.0-py3-none-any.whl
Size 84.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
997b77b86fcbb2cdc16abac1c8ff6b4049798a36158efd3602efb44badbd9f27
BLAKE2b-256 checksum
How to use checksums
d85a2ab2a737928561051964eb1e4edfc3d426f4450ab74c5184d4e6a4242f0a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page