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.

Identity resolution is how the SDK decides which grant backs a given app.request() call. Three modes exist, and every call site uses exactly one. Pick the mode based on what the call site has on hand:
  1. JWT identity — there’s a logged-in end user, the app has an IDP configured.
  2. Explicit grant_id — the call has no end user, or explicit grant control is needed.
  3. Headless — the call has no end user and no grant_id yet (one-time bootstrap flows).
The mode picks how the SDK finds the grant, not what credential is behind it. An OAuth connection and a managed secret bound to the same user resolve under JWT identity the same way.

1. JWT identity — for apps with logged-in users

The app has an identity provider configured. Construct the SDK with a user_token_getter that returns the calling user’s JWT; the SDK includes the JWT on every request and the backend resolves the user’s grant from it.
app = App(
    api_key=ALTER_API_KEY,
    user_token_getter=lambda: get_jwt_from_request(),
)

# No grant_id — the backend resolves Alice's Google grant from her JWT.
response = await app.request("GET", url, provider="google")
When to use: any flow where a logged-in user is the reason for the call. SaaS products, agentic apps with a user session, anything that already has a JWT in scope. Why it’s the default: the app stops tracking grant_id in its own database. Deprovisioning a user in the IDP automatically locks them out of grants they own.

2. Explicit grant_id — for scripts, batch jobs, system-principal grants

Pass an explicit grant_id per call. Use this when:
  • The call has no end user (cron jobs, webhook handlers, system-principal managed secrets).
  • Explicit control over which grant a request uses is required.
app = App(api_key=ALTER_API_KEY)
response = await app.request("GET", url, grant_id=STRIPE_GRANT_ID)
A managed-secret grant bound to a user or group does not require this mode — it resolves under JWT identity (mode 1) automatically.

3. Headless — for CLIs, notebooks, agent bootstrap

app.connect() opens a browser, walks through OAuth, and returns a grant_id usable immediately. No frontend, no callback URL, no JWT.
app = App(api_key=ALTER_API_KEY)
results = await app.connect(providers=["github"])
grant_id = results[0].grant_id
When to use: local scripts, Jupyter notebooks, server-side workloads bootstrapping a long-lived grant, the Quickstart walkthrough.

Picking one

Is there a logged-in user with a JWT?
├── Yes → JWT
└── No  → Is a grant_id already known?
         ├── Yes → grant_id
         └── No  → Headless
Modes can be mixed in one application — different SDK instances for different code paths. For agent workloads, see Give an agent scoped access.

Ambiguous resolution

A JWT can match more than one grant if the user has connected the same provider multiple times (personal + work Gmail). The backend raises AmbiguousGrantError with the matching account identifiers; application code passes account=… on retry to pick one.

What’s next