Metadata-Version: 2.1
Name: alter-sdk
Version: 0.17.0
Summary: Alter Vault Python SDK - OAuth token management with policy enforcement
Home-page: https://alterauth.com
Keywords: oauth,tokens,security,policy,vault
Author: Alter Team
Author-email: founders@alterauth.com
Requires-Python: >=3.11,<4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Provides-Extra: aws
Provides-Extra: fastapi
Provides-Extra: langchain
Provides-Extra: mcp
Requires-Dist: boto3 (>=1.28.0,<2.0.0) ; extra == "aws"
Requires-Dist: fastapi (>=0.100.0) ; extra == "fastapi"
Requires-Dist: fastmcp (>=2.14) ; extra == "mcp"
Requires-Dist: httpx[http2] (>=0.25.0,<1.0)
Requires-Dist: langchain-core (>=0.3.85,<2.0.0,!=1.0.*,!=1.1.*,!=1.2.*,!=1.3.0,!=1.3.1,!=1.3.2) ; extra == "langchain"
Requires-Dist: pydantic (>=2.5.0,<3.0.0)
Description-Content-Type: text/markdown

# Alter SDK for Python

Official Python SDK for [Alter Vault](https://alterauth.com) — 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

```bash
pip install alter-sdk
```

Requires Python 3.10+.

## Quick example

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

```python
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](https://docs.alterauth.com/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.

See [runtime modes](https://docs.alterauth.com/concepts/runtime-modes) for the tradeoffs and when to pick each.

## 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:

```python
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](https://docs.alterauth.com/reference/errors) for the full surface.

## Documentation

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

| Topic | Page |
|---|---|
| Getting started end-to-end | [Quickstart](https://docs.alterauth.com/quickstart) |
| The mental model | [How Alter works](https://docs.alterauth.com/how-it-works) |
| Calling APIs on behalf of users (OAuth + JWT) | [Guide](https://docs.alterauth.com/guides/call-apis-on-behalf-of-users) |
| Identity provider setup | [Auth0 / Clerk / Okta / Custom OIDC](https://docs.alterauth.com/admin/identity-provider) |
| Provisioning backend secrets | [Guide](https://docs.alterauth.com/guides/provision-secrets-for-backend-services) |
| Scoped credentials for AI agents | [Guide](https://docs.alterauth.com/guides/give-an-agent-scoped-access) |
| Human-in-the-loop approvals | [Guide](https://docs.alterauth.com/guides/add-human-in-the-loop-approvals) |
| Runtime modes (retrieve vs proxy) | [Concept](https://docs.alterauth.com/concepts/runtime-modes) |
| Integrating with Claude Code (MCP) | [Guide](https://docs.alterauth.com/guides/integrate-with-claude-code-mcp) |
| Per-method API reference | [Python SDK reference](https://docs.alterauth.com/reference/python-sdk) |
| Errors | [Error reference](https://docs.alterauth.com/reference/errors) |

## License

MIT. See `LICENSE`.

## Support

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

