Skip to main content

Python quickstart

Python 3.9+. Framework integrations: FastAPI · Flask · Django.

pip install latchvector-sso
# framework extras pull nothing in unless imported:
pip install "latchvector-sso[fastapi]" # or [flask], [django]
The SDK is the whole product — you rarely touch raw HTTP

The SDK wraps every endpoint: authentication, and the full management surface (users, organizations, roles, applications, API clients, webhooks, audit, bulk import, data export/erase, MFA & devices). Reach for the API reference only to look up an exact request/response shape.

1. Protect an API​

Native integrations for FastAPI, Flask, and Django do the token-checking for you — guard routes the way each framework expects. Tokens are verified locally (no call to the SSO service per request).

FastAPI​

from fastapi import Depends, FastAPI
from latchvector_sso import Principal, TokenVerifier
from latchvector_sso.fastapi import SsoAuth

auth = SsoAuth(TokenVerifier(issuer="https://sso.yourdomain.com",
audience="https://api.yourcompany.com"))
app = FastAPI()

@app.get("/invoices")
def list_invoices(user: Principal = Depends(auth.required)):
return {"owner": user.uid}

@app.post("/invoices/{invoice_id}/approve")
def approve(invoice_id: int, user: Principal = Depends(auth.requires("invoice.approve"))):
...

Flask​

from latchvector_sso.flask import SsoAuth, current_principal

auth = SsoAuth(app, TokenVerifier(issuer=..., audience=...))

@app.get("/invoices")
@auth.required
def list_invoices():
return {"owner": current_principal().uid}

@app.post("/invoices/<int:invoice_id>/approve")
@auth.requires("invoice.approve")
def approve(invoice_id):
...

Django​

# settings.py
LATCHVECTOR_SSO = {"ISSUER": "https://sso.yourdomain.com", "AUDIENCE": "https://api.yourcompany.com"}
MIDDLEWARE = [..., "latchvector_sso.django.SsoAuthenticationMiddleware"]

# views.py
from latchvector_sso.django import sso_required, sso_requires

@sso_required
def invoices(request):
return JsonResponse({"owner": request.principal.uid})

@sso_requires("invoice.approve")
def approve(request, pk):
...

Not on one of these? A framework-agnostic TokenVerifier verifies an Authorization header directly:

principal = verifier.verify_authorization_header(request.headers.get("Authorization"))

2. Log a user in​

from latchvector_sso import SsoClient, TokenPair

sso = SsoClient(issuer="https://sso.yourdomain.com",
audience="https://api.yourcompany.com")

result = sso.login(email, password)
if isinstance(result, TokenPair):
access, refresh = result.access_token, result.refresh_token

Rotate with sso.refresh(refresh_token); persist the new refresh token.

3. Manage everything — one client​

ManagementClient wraps the entire management surface as typed groups, so the whole product is reachable from code — you rarely write a raw request.

from latchvector_sso import ManagementClient

mgmt = ManagementClient(issuer, lambda: current_access_token)

mgmt.users.create(organizationId=org_id, email=email, fullName=name, roleId=role_id)
mgmt.organizations.create(name=name, slug=slug, parentId=parent_id)
mgmt.roles.create(organizationId=org_id, name="Doctor", scope="SUBTREE",
permissionCodes=["USER_MANAGE"])
mgmt.applications.create(organizationId=org_id, identifier=identifier, name=name)
mgmt.clients.register(organizationId=org_id, name=name, scopes=["reports.read"])
mgmt.webhooks.register(organizationId=org_id, applicationId=app_id, url=url)
mgmt.audit.search(organizationId=org_id, q="role.revoked")
mgmt.import_.validate(payload) # bulk migrate
mgmt.privacy.export_user(user_id) # export / erase
mgmt.mfa.begin() # the caller's own MFA
mgmt.devices.list() # the caller's devices
mgmt.sandbox.provision(...) # platform operators

Anything not covered by a group — including endpoints added after this SDK shipped — is reachable via mgmt.request(method, path, query=..., body=...).

Deeper reference

The PyPI README has the full recipes (multitenancy, go-live checks). Exact request/response shapes: API reference.