Verify access tokens and handle webhooks in any Python framework.

Python SDK

The ascendkit Python package provides access token verification and webhook signature validation. It works with any Python framework — FastAPI, Flask, Django, Starlette, or plain scripts.

Install

pip install ascendkit

Requires Python 3.10+. Dependencies: httpx, pydantic, pyjwt[crypto].

Access token verification

Verify RS256 access tokens issued by AscendKit using JWKS. Keys are cached in memory for 1 hour.

from ascendkit import AccessTokenVerifier, AuthError

verifier = AccessTokenVerifier()

# Sync
claims = verifier.verify(token)
print(claims["sub"])  # usr_...
print(claims["email"])

# Async
claims = await verifier.verify_async(token)

The constructor reads ASCENDKIT_ENV_KEY from your environment. If the variable is missing, it raises an error at initialization so you catch configuration issues immediately.

Raises AuthError with appropriate status codes:

  • 401 — expired or invalid token
  • 503 — JWKS endpoint unreachable

Framework integration

from fastapi import FastAPI, Depends, Header, HTTPException
from ascendkit import AccessTokenVerifier, AuthError

app = FastAPI()
verifier = AccessTokenVerifier()

async def get_current_user(authorization: str = Header()) -> dict:
    token = authorization.removeprefix("Bearer ").strip()
    try:
        return await verifier.verify_async(token)
    except AuthError as e:
        raise HTTPException(status_code=e.status_code, detail=str(e))

@app.get("/api/profile")
async def profile(user: dict = Depends(get_current_user)):
    return {"email": user["email"], "id": user["sub"]}

Webhook verification

Verify webhook signatures using HMAC-SHA256. Includes timestamp validation (5-minute tolerance) to prevent replay attacks.

from fastapi import Request, Response
from ascendkit import verify_webhook_signature
import os

WEBHOOK_SECRET = os.environ["ASCENDKIT_WEBHOOK_SECRET"]

@app.post("/webhooks/ascendkit")
async def handle_webhook(request: Request) -> Response:
    body = await request.body()
    signature = request.headers.get("x-ascendkit-signature", "")

    if not verify_webhook_signature(
        secret=WEBHOOK_SECRET,
        signature_header=signature,
        payload=body.decode(),
    ):
        return Response(status_code=401, content="Invalid signature")

    event = await request.json()
    # Handle event by type: user.created, user.approved, etc.
    return Response(status_code=200, content="OK")

Server-side analytics

Track events from your backend with trusted identity (secret key auth):

from ascendkit import Analytics

analytics = Analytics()

analytics.track("usr_456", "checkout.completed", {"total": 99.99})

The constructor reads ASCENDKIT_SECRET_KEY from your environment. If missing, it raises an error at initialization.

Events batch in memory and flush every 30 seconds or when the batch fills (10 events). Call analytics.shutdown() for graceful cleanup.