Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.alterauth.com/llms.txt

Use this file to discover all available pages before exploring further.

The Python SDK ships as the alter-sdk package on PyPI. Python 3.10+.
pip install alter-sdk
For end-to-end walkthroughs, see the Quickstart and Guides. This page is API reference only.

Clients

Two classes, both async.

App

The application-side client. Construct with an alter_key_app_… API key.
from alter_sdk import App

app = App(
    api_key: str,
    *,
    timeout: float = 30.0,
    caller: str | None = None,
    caller_type: CallerType = CallerType.SERVICE,
    user_token_getter: Callable[[], str | Awaitable[str]] | None = None,
)
Constructor args:
ArgTypeDefaultDescription
api_keystrApp API key. Required.
timeoutfloat30.0HTTP timeout in seconds.
callerstr | NoneNoneFree-form audit attribution, or an agent UUID for impersonation.
caller_typeCallerTypeSERVICESERVICE or AGENT. Drives audit grouping in the portal.
user_token_gettercallableNoneReturns the calling user’s JWT for JWT identity.
Supports async context manager: async with App(...) as app:.

Agent

The workload-side client. Construct with an alter_key_agent_… key (or via App.get_agent(agent_id) for the impersonation path).
from alter_sdk import Agent

agent = Agent(
    api_key: str,
    *,
    timeout: float = 30.0,
    caller: str | None = None,
    user_token_getter: Callable[[], str | Awaitable[str]] | None = None,
)
Agent exposes a strict subset of App — the methods that don’t apply to an agent principal (agents.* CRUD, revoke_grant, create_managed_secret_grant from the operator side, authenticate, verify_user_token) are absent. Calling them on an agent principal would raise typed exceptions deep in the request path anyway; the SDK forbids them at the class level.

Making requests

request(method, url, *, grant_id=..., provider=..., json=..., headers=..., query_params=..., reason=..., context=..., user_token=..., account=...) -> httpx.Response

The token-injected HTTP call. Returns an httpx.Response. Two ways to identify the grant:
  • grant_id=<uuid> — explicit.
  • provider=<slug> — resolved from the user’s JWT via the configured user_token_getter.
Other kwargs:
  • json — request JSON body.
  • headers — additional request headers (Authorization is auto-injected).
  • query_params — query-string parameters.
  • reason — human-readable explanation surfaced to end users in the Wallet and stored in the audit trail.
  • context — application metadata (dict[str, str]).
  • user_token — per-call JWT (overrides user_token_getter).
  • account — disambiguator when the JWT matches multiple grants.
response = await app.request(
    HttpMethod.GET, "https://www.googleapis.com/calendar/v3/calendars/primary/events",
    provider="google", reason="Sync events on page load",
)

proxy_request(...) -> ApprovalResult | PendingApproval

Same arg shape as request, but routes through the HITL approval pipeline. Returns PendingApproval when an approval is required, ApprovalResult when the call ran synchronously.

boto3_client(grant_id, service, region=None) -> boto3.Client

Returns a boto3 client that signs requests with credentials from an AWS managed-secret grant.

Grants

list_grants(*, provider_id=None, limit=100, offset=0) -> UnifiedGrantListResult

Paginated list of grants visible to the calling principal. Returns a discriminated union — each item is either an OAuthGrantItem (grant_kind="oauth") or a ManagedSecretGrantItem (grant_kind="managed_secret"). App.list_grants returns OAuth grants only; Agent.list_grants returns both.

revoke_grant(grant_id) -> RevokeGrantResult

Revoke an OAuth grant. App-only.

create_managed_secret_grant(managed_secret_id, *, principal: Principal) -> CreateGrantResult

Issue a managed-secret grant bound to a principal. principal is one of UserPrincipal, GroupPrincipal, SystemPrincipal, AgentPrincipal.

revoke_delegation(grant_id, agent_id=None)

App: revoke_delegation(grant_id, agent_id) revokes a named agent’s delegation on an OAuth grant. Agent: revoke_delegation(grant_id) revokes the calling agent’s own delegation (no agent_id argument).

Connect flow

create_connect_session(*, allowed_providers, allowed_origin=None, user_token=None, agent=None, return_url=None) -> ConnectSession

Mint a short-lived session token for the Connect widget.

create_managed_secret_connect_session(*, agent_id) -> ManagedSecretConnectSession

Mint a session for the user → agent delegation flow on a managed secret.

connect(providers=[...], email=None, scopes=None) -> list[ConnectResult]

Headless OAuth — opens a local browser, walks the OAuth flow, returns the resulting grant metadata. Use for CLIs, notebooks, one-time bootstrap.

Authentication helpers (App only)

authenticate() -> AuthResult

Open a local browser to the IDP’s sign-in flow, return the user’s JWT.

verify_user_token(token) -> str | None

Verify a JWT against the app’s IDP; return the user UUID if valid.

Approvals

  • get_approval_status(approval_id) -> ApprovalStatus — single poll.
  • await_approval(approval_id, timeout=...) -> ApprovalResult — block until terminal.

Managed agents (App only)

The app.agents namespace.
  • app.agents.create(name=..., **opts) -> AgentCreateResult — plaintext API key returned once.
  • app.agents.list(limit=..., offset=...) -> AgentListResult
  • app.agents.get(agent_id) -> AgentInfo
  • app.agents.get_by_name(name) -> AgentInfo | None
  • app.agents.update(agent_id, **opts) -> AgentInfo
  • app.agents.mint_key(agent_id) -> AgentKeyMintResult — plaintext returned once.
  • app.agents.list_keys(agent_id) -> AgentKeyList
  • app.agents.deprecate_key(agent_id, key_id), undeprecate_key(...), revoke_key(agent_id, key_id, force=False)

Scoped key derivation

The app.keys and agent.keys namespaces.
  • keys.derive(scopes=[...], expires_in=..., cidr_allowlist=..., rate_limit_rpm=...) -> MintedKey
  • keys.rotate(key_id) -> MintedKey
  • keys.revoke(key_id) -> APIKeyInfo

Scope catalog

  • app.scopes.get_catalog() -> ScopeCatalog — the server-published scope set at the current version.

Attenuation

  • app.with_constraints(scopes=[...]) -> App — returns a sibling client whose every request signs with X-Alter-Scope-Constraints. The intersection of the parent key’s scopes and the supplied list applies. See Scopes.

Agent introspection (Agent only)

  • agent.me() -> AgentInfo — the calling agent’s own record. Works even when paused, useful for self-diagnostics.
  • agent.trace(run_id=..., thread_id=..., parent=..., **metadata) — async context manager scoping audit identity for nested request() calls. See Give an agent scoped access.

Models

Public types exported from alter_sdk:
TypePurpose
TokenResponseOAuth token metadata (access token is never readable).
GrantInfoSingle grant record (legacy list_grants shape).
OAuthGrantItem, ManagedSecretGrantItemDiscriminated union members in UnifiedGrantListResult.
UnifiedGrantListResultPaginated list_grants response.
ConnectSession, ManagedSecretConnectSessionConnect session response shape.
ConnectResult, AuthResultHeadless flow results.
Principal (discriminated union: UserPrincipal, GroupPrincipal, SystemPrincipal, AgentPrincipal)Input shape for create_managed_secret_grant.
GrantPolicy, GrantPolicyInputTTL and policy fields on a grant.
PendingApproval, ApprovalStatus, ApprovalResultHITL flow types.
AgentInfo, AgentCreateResult, AgentListResultManaged agent records.
AgentKey, AgentKeyMintResult, AgentKeyListPer-agent key records.
APIKeyInfo, MintedKeyDerived API key records.
ScopeCatalog, ResourceScopesScope catalog discovery.
RetryInfo, RetryErrorInfoRetry metadata on last_retry_info.
All models are frozen Pydantic; field access only.

Errors

See Errors for the full hierarchy. The exceptions importable from alter_sdk (selection): AlterSDKError, AlterValueError, BackendError, ReAuthRequiredError, GrantExpiredError, GrantRevokedError, CredentialRevokedError, GrantDeletedError, GrantNotFoundError, AmbiguousGrantError, PolicyViolationError, InsufficientScopeError, TokenRefreshInProgressError, NoDelegatedGrantError, ConnectFlowError, ConnectDeniedError, ConnectConfigError, ConnectTimeoutError, ProviderAPIError, ScopeReauthRequiredError, NetworkError, TimeoutError, ApprovalError, ApprovalDeniedError, ApprovalExpiredError, ApprovalTimeoutError, ApprovalExecutionFailedError, AgentError (and the agent subclasses).

Enums

EnumMembers
HttpMethodGET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
CallerTypeSERVICE, AGENT

Framework recipes

FastAPI

import os
from fastapi import FastAPI, Depends
from contextvars import ContextVar
from alter_sdk import App

current_jwt: ContextVar[str] = ContextVar("current_jwt")
alter = App(api_key=os.environ["ALTER_API_KEY"], user_token_getter=lambda: current_jwt.get())

app = FastAPI()

async def with_user(request):
    current_jwt.set(extract_jwt(request))

@app.get("/api/events", dependencies=[Depends(with_user)])
async def list_events():
    r = await alter.request("GET", "https://www.googleapis.com/calendar/v3/calendars/primary/events", provider="google")
    return r.json()

LangChain

import os
from alter_sdk import Agent
from alter_sdk.langchain import alter_tool

agent = Agent(api_key=os.environ["AGENT_KEY"])

@alter_tool(agent=agent)
async def send_slack(channel: str, text: str) -> dict:
    """Post a Slack message."""
    r = await agent.request("POST", "https://slack.com/api/chat.postMessage",
                            provider="slack", json={"channel": channel, "text": text})
    return r.json()

# `send_slack` is now a LangChain tool. Identity flows through agent.trace() automatically.

MCP

See Integrate with Claude Code (MCP).