Files
stack/sdks/implementations/python
Ejiro Asiuwhu 131bb89d6e docs: clarify why 429 retries apply to all HTTP methods
A 429 guarantees the server did not process the request, so retrying
is safe regardless of idempotency. This differs from network error
retries which are restricted to idempotent methods. Added inline
comments to both sync and async client request loops.
2026-03-26 09:48:12 +01:00
..

Stack Auth Python SDK

Python SDK for Stack Auth — the open-source authentication platform. Provides StackServerApp for server-side user management, team operations, JWT verification, and more.

Installation

pip install stack-auth

Quick Start

from stack_auth import StackServerApp

app = StackServerApp(
    project_id="your-project-id",
    secret_server_key="your-secret-server-key",
)

# List users
users = app.list_users(limit=10)
for user in users.items:
    print(f"{user.display_name} ({user.primary_email})")

# Create a user
user = app.create_user(
    primary_email="[email protected]",
    password="securepassword",
    display_name="Jane Doe",
)

# Get a user
user = app.get_user("user-id")

# Update a user
updated = app.update_user("user-id", display_name="New Name")

# Delete a user
app.delete_user("user-id")

Async Support

Every method has an async equivalent via AsyncStackServerApp:

from stack_auth import AsyncStackServerApp

app = AsyncStackServerApp(
    project_id="your-project-id",
    secret_server_key="your-secret-server-key",
)

user = await app.get_user("user-id")
users = await app.list_users(limit=10)
team = await app.create_team(display_name="Engineering")

Authentication

Verify incoming request tokens without framework-specific middleware:

from stack_auth._auth import sync_authenticate_request
from stack_auth._jwt import SyncJWKSFetcher

fetcher = SyncJWKSFetcher(
    project_id="your-project-id",
    base_url="https://api.stack-auth.com",
)

# Works with any object that has a .headers mapping
result = sync_authenticate_request(request, fetcher=fetcher)

if result.status == "authenticated":
    print(f"User: {result.user_id}")
else:
    print("Not authenticated")

FastAPI Example

from fastapi import Depends, HTTPException, Request
from stack_auth._auth import sync_authenticate_request
from stack_auth._jwt import SyncJWKSFetcher

fetcher = SyncJWKSFetcher(project_id="...", base_url="https://api.stack-auth.com")

def get_user_id(request: Request) -> str:
    result = sync_authenticate_request(request, fetcher=fetcher)
    if result.status != "authenticated":
        raise HTTPException(status_code=401)
    return result.user_id

@app.get("/protected")
def protected_route(user_id: str = Depends(get_user_id)):
    return {"user_id": user_id}

Error Handling

All API errors raise typed exceptions:

from stack_auth.errors import (
    StackAuthError,
    AuthenticationError,
    NotFoundError,
    ValidationError,
)

try:
    user = app.get_user("invalid-id")
except NotFoundError as e:
    print(f"Not found: {e.message}")
except AuthenticationError as e:
    print(f"Auth failed: {e.code}")
except StackAuthError as e:
    print(f"API error: {e.code} - {e.message}")

Teams

# Create a team
team = app.create_team(
    display_name="Engineering",
    creator_user_id="user-id",
)

# List teams
teams = app.list_teams(user_id="user-id")

# Manage members
app.add_team_member(team_id=team.id, user_id="another-user-id")
profiles = app.list_team_member_profiles(team_id=team.id)

# Permissions
app.grant_team_permission(
    team_id=team.id,
    user_id="user-id",
    permission_id="admin",
)

Self-Hosted

Point to your self-hosted Stack Auth instance:

app = StackServerApp(
    project_id="your-project-id",
    secret_server_key="your-secret-key",
    base_url="https://your-stack-auth.example.com",
)

API Reference

StackServerApp / AsyncStackServerApp

Constructor:

  • project_id (str) — Your Stack Auth project ID
  • secret_server_key (str) — Server secret key from the dashboard
  • base_url (str, optional) — API base URL (default: https://api.stack-auth.com)
  • publishable_client_key (str, optional) — Required for projects with requirePublishableClientKey
  • token_store (optional) — Token storage strategy

User methods: get_user, list_users, create_user, update_user, delete_user, get_user_by_api_key, get_partial_user

Team methods: get_team, list_teams, create_team, update_team, delete_team, get_team_by_api_key, add_team_member, remove_team_member, list_team_member_profiles, get_team_member_profile, send_team_invitation, list_team_invitations, revoke_team_invitation

Permission methods: grant_team_permission, revoke_team_permission, list_team_permissions, grant_user_permission, revoke_user_permission, list_user_permissions

Session methods: list_sessions, get_session, revoke_session

Contact channel methods: send_contact_channel_verification, verify_contact_channel, check_contact_channel_verification

API key methods: create_user_api_key, list_user_api_keys, revoke_user_api_key, create_team_api_key, list_team_api_keys, revoke_team_api_key, check_api_key

OAuth methods: list_oauth_providers, create_oauth_provider, get_oauth_provider, list_connected_accounts

Payment methods: list_products, get_item, grant_product, cancel_subscription

Email methods: send_email, get_email_delivery_stats

Data vault: get_data_vault_store → returns DataVaultStore with get, set, delete, list_keys

Development

# Clone the repo
git clone https://github.com/stack-auth/stack-auth.git
cd stack-auth/sdks/implementations/python

# Install in dev mode
pip install -e ".[dev]"

# Run unit tests (no server needed)
python3 -m pytest tests/ -v

# Run E2E tests (requires running Stack Auth)
# First: pnpm start-deps && pnpm dev (from monorepo root)
STACK_E2E=1 python3 -m pytest tests/test_e2e.py -v -s

Requirements

  • Python >= 3.10
  • httpx
  • PyJWT[crypto]
  • pydantic >= 2.7

License

MIT — same as Stack Auth.