Skip to main content

Alter SDK for Python

Official Python SDK for Alter Vault — credential and authorization layer for apps and AI agents that call third-party APIs.

Tokens stay in the vault. The SDK injects the credential, refreshes it, and writes the audit row — application code only calls vault.request() (or vault.proxy_request() when the backend should make the outgoing call instead of the SDK).

Install

pip install alter-sdk

Requires Python 3.11+.

Quick example

Make an authenticated API call — no token ever touches application code.

import asyncio
from alter_sdk import App, HttpMethod

async def main():
    async with App(api_key="<api-key>") as vault:
        response = await vault.request(
            HttpMethod.POST,
            "https://api.example.com/resource",
            grant_id="<grant-id>",
            json={"example": "payload"},
        )
        print(response.status_code, response.json())

asyncio.run(main())

For a full walkthrough — sign-up, key minting, OAuth — see the Quickstart.

Two runtime modes

The SDK exposes two ways to reach a third-party API:

  • vault.request(...)retrieve mode. The SDK fetches the token from the backend and makes the outgoing call itself. Returns the third-party response.
  • vault.proxy_request(...)proxy mode. The backend holds the token, makes the outgoing call, and returns the result. Application code and the SDK never observe the token. Required for any grant configured with human-in-the-loop approval; available for any other grant when wire-level audit, strong token isolation, or backend-side policy enforcement matter.

Proxy mode returns an ApprovalResult with status_code, response headers/body, body_truncated, and duration_ms (provider round-trip milliseconds; None for results created by older workers). Managed-secret secondary header/query injections and AWS SigV4—including query parameters, raw/JSON bodies, and temporary session tokens—behave the same in retrieve and proxy modes.

See runtime modes for the tradeoffs and when to pick each.

Policy rule helpers

content_match_rule(...) builds operation-aware request rules for with_constraints(rule=...) with local validation before the first API call. It accepts attested operation ids and/or operation families, optional parameter conditions, and one of three effects: deny, redact, or step_up. Redaction strips named outbound request-body fields; step-up requires max_session_age_seconds as an integer from 0 through 86400.

Recovering from missing-grant errors

When a request fails because the user hasn't authorized the provider yet, the SDK exposes recovery context on the typed error so you can drive a re-consent flow without re-deriving anything from the call site:

from alter_sdk import NoDelegatedGrantError

try:
    await vault.request(provider="<provider-id>", user_token=jwt, url=..., method=...)
except NoDelegatedGrantError as e:
    session = await vault.create_connect_session_for_error(
        e,
        allowed_origin="https://app.example.com",
    )
    # Surface session.connect_url to the user — popup, redirect,
    # out-of-band message, whatever your framework does.
    results = await vault.poll_connect_session(session.session_token)
    # Retry with the freshly-minted grant_id.
    response = await vault.request(grant_id=results[0].grant_id, url=..., method=...)

create_connect_session_for_error and poll_connect_session are available on both App and Agent so the catch block can recover from whichever client raised.

NoDelegatedGrantError and GrantNotFoundError carry provider_id / agent_id / app_user_id recovery context when the original lookup was identity-mode; CredentialRevokedError carries provider_id / app_user_id. See the error reference for the full surface.

On the agent path, a grant_not_found for an explicit grant_id surfaces as AgentDelegationMissingError — a subclass of GrantNotFoundError, so an except GrantNotFoundError still fires. It means the grant is not delegated to this agent, or a user/base grant id was passed where the agent's own delegation id is required (get it from agent.list_grants). Recover by delegating the agent through Connect (agent.create_connect_session), or resolve by provider instead of passing a grant_id.

Onward delegation (agent to agent)

An agent that holds a grant can hand a scoped-down copy to another agent — without asking the credential owner to consent again. Use agent.delegate() to mint a child grant for the second agent:

from alter_sdk import Agent, GrantNotDelegableError

agent = Agent(api_key="<agent-api-key>")

try:
    result = await agent.delegate(
        "<grant-id>",              # a grant this agent already holds
        "<other-agent-id>",        # the agent that should receive access
        scope_constraint=["chat:write"],   # optional: narrow to fewer scopes
        ttl_seconds=3600,                  # optional: shorten the lifetime
        delegable=False,                   # may the recipient delegate onward? (default no)
    )
    print(result.grant_id, result.depth, result.expires_at)
except GrantNotDelegableError:
    # The held grant was not marked delegable when it was created,
    # so it cannot be passed on. Ask the owner for a delegable grant.
    ...

The held grant must have been created as delegable (chosen at connect time). The child can only narrow — fewer scopes, a shorter lifetime — never widen. A grant narrowed with scope_constraint is proxy-only: call it with agent.proxy_request(...). Onward delegation is opt-in at every hop: pass delegable=True only when the recipient should be allowed to delegate further.

agent.list_grants() returns each grant with parent_grant_id (the grant it was minted under, or None for a root) and depth (its distance from the root), so the full delegation chain can be reconstructed from the flat list.

OpenTelemetry trace propagation

When the application runs an OpenTelemetry SDK, Alter requests automatically carry the active span's W3C traceparent, so the audit trail — and any spans the organization streams to its own OTLP collector — join the application's traces. No configuration is required and opentelemetry is never installed by the SDK itself — it uses whatever OpenTelemetry the application installed; without it (or without an active span) the SDK behaves exactly as before. (The optional alter-sdk[otel] extra is available to record the supported opentelemetry-api version range in the application's dependency tree.)

from opentelemetry import trace

tracer = trace.get_tracer("the-application")

# Inside an async function; `vault` from the quick start above.
with tracer.start_as_current_span("handle-user-request"):
    # This call's audit events share the surrounding trace's ids.
    response = await vault.request(HttpMethod.GET, url, grant_id=grant_id)

Documentation

Full docs are at https://docs.alterauth.com.

Topic Page
Getting started end-to-end Quickstart
The mental model How Alter works
Calling APIs on behalf of users (OAuth + JWT) Guide
Identity provider setup Auth0 / Clerk / Okta / WorkOS / Custom OIDC
Provisioning backend secrets Guide
Scoped credentials for AI agents Guide
Human-in-the-loop approvals Guide
OpenTelemetry trace propagation Calling APIs
Runtime modes (retrieve vs proxy) Concept
Integrating with Claude Code (MCP) Guide
Per-method API reference Python SDK reference
Errors Error reference

License

MIT. See LICENSE.

Support

Email founders@alterauth.com or open an issue at https://github.com/alter-ai/alter-vault.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

alter_sdk-0.20.1.tar.gz (234.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

alter_sdk-0.20.1-py3-none-any.whl (248.1 kB view details)

Uploaded Python 3

File details

Details for the file alter_sdk-0.20.1.tar.gz.

File metadata

  • Download URL: alter_sdk-0.20.1.tar.gz
  • Upload date:
  • Size: 234.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for alter_sdk-0.20.1.tar.gz
Algorithm Hash digest
SHA256 4e34aaedc25e5c66860202837226327d69db4b8a3f88e65b453e1b72cd15daf7
MD5 0fcc1a16c5f5522dfd185c559a798e53
BLAKE2b-256 82ca290e2351ea1962775631e22977fc921107166fcfc4f9dcebdc76d2bd9c64

See more details on using hashes here.

Provenance

The following attestation bundles were made for alter_sdk-0.20.1.tar.gz:

Publisher: python-sdk-release.yml on AlterAIDev/Alter-Vault

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file alter_sdk-0.20.1-py3-none-any.whl.

File metadata

  • Download URL: alter_sdk-0.20.1-py3-none-any.whl
  • Upload date:
  • Size: 248.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for alter_sdk-0.20.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a96d9d4ddf3dd680f07e2434b2321f5f5f98914c26def2aac681beccba9062d5
MD5 80db324d1445e44786af9f93f86e89a1
BLAKE2b-256 20ba09b8be4d161d5bdde14a995d4ed68a4143a9ceb32b5fe39a2f74ba559666

See more details on using hashes here.

Provenance

The following attestation bundles were made for alter_sdk-0.20.1-py3-none-any.whl:

Publisher: python-sdk-release.yml on AlterAIDev/Alter-Vault

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.24.0

2 files

0.23.3

2 files

0.23.1

2 files

0.22.0

2 files

0.21.0

2 files

This release

0.20.1 This release

2 files

0.20.0

2 files

0.19.0

2 files

0.18.0

2 files

0.17.0

2 files

0.16.0

2 files

0.15.0

2 files

0.14.0

2 files

0.13.0

2 files

0.12.0

2 files

0.11.0

2 files

0.10.0

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.1

2 files

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 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