Python
apikee for Python — FastAPI, Flask, Starlette, and raw ASGI.
Python
Installation
pip install apikee # local validation only (zero deps)
pip install "apikee[server]" # + AES-256-GCM encrypted server channel
pip install "apikee[fast]" # + msgpack (faster serialisation)
pip install "apikee[fastapi]" # + FastAPI middleware
pip install "apikee[all]" # everythingFastAPI
SecuredFastAPI is a drop-in replacement for FastAPI(). It automatically:
- Registers the ASGI validation middleware
- Patches
openapi()to injectApikeeAuthinto every path and the global security block - Exports
ApikeeDepends(),get_claims(), andrequire_scope()as ready-to-use dependencies
from apikee.fastapi import SecuredFastAPI, ApikeeDepends, require_scope
from apikee import ApikeeClaims
from fastapi import Depends
app = SecuredFastAPI(
title="My API",
secrets=["your-signing-secret"],
exclude_paths={"/health", "/keys"}, # paths that skip validation
# server_key="sk_live_...", # uncomment for server mode
# project_env="my-app-production",
)
@app.get("/data")
def get_data(claims: ApikeeClaims = ApikeeDepends()):
return {"tenant": claims.tenant, "scopes": claims.scopes}
@app.delete("/users/{id}", dependencies=[Depends(require_scope("admin"))])
def delete_user(id: str, claims: ApikeeClaims = ApikeeDepends()):
return {"deleted": id}Issuing keys
@app.post("/keys", tags=["auth"])
def create_key(tenant: str, scopes: str = "read,write"):
key = app.apikee.create(
tenant=tenant,
scopes=scopes.split(","),
expires_in=timedelta(days=90),
)
return {"key": key}Opening /docs after adding SecuredFastAPI shows a 🔒 lock icon on every endpoint. The Authorize button lets you paste a key and test all routes directly in Swagger UI.
Flask
from flask import Flask
from apikee.flask import init_apikee, apikee_required, require_scope, get_claims
app = Flask(__name__)
apikee = init_apikee(app, secrets=["your-signing-secret"])
@app.get("/data")
@apikee_required
def get_data():
claims = get_claims()
return {"tenant": claims.tenant}
@app.post("/items")
@require_scope("write")
def create_item():
claims = get_claims()
return {"created": True, "tenant": claims.tenant}, 201
@app.delete("/items/<int:id>")
@require_scope("admin")
def delete_item(id):
return {"deleted": id}Starlette (raw ASGI)
from starlette.applications import Starlette
from apikee import Apikee
apikee = Apikee(secrets=["your-signing-secret"])
app = Starlette(routes=[...])
# One line — works with any ASGI framework
app.add_middleware(apikee.middleware)Claims are available on request.state.apikee in every route handler.
Configuration reference
| Parameter | Type | Default | Description |
|---|---|---|---|
secrets | list[str] | required | Signing secrets. First is current; rest accepted for rotation. |
server_key | str | None | apikee.dev project key (sk_live_...). Enables server mode. |
project_env | str | None | apikee.dev project_env slug, e.g. my-app-production. |
header_name | str | "x-api-key" | Header to read the key from. |
default_expiry | timedelta | 90d | Default expiry for new keys. |
auto_register_endpoints | bool | True | Register endpoints with apikee.dev on first request (server mode). |
auto_create_clients | bool | True | Auto-create client on apikee.dev when issuing a key (server mode). |
fail_open | bool | True | If server call fails, allow request through. |
ApikeeClaims fields
| Field | Type | Description |
|---|---|---|
id | str | Unique key ID (ULID-style) |
tenant | str | Tenant / owner identifier |
scopes | list[str] | Permission scopes |
environment | str | Environment tag (production, staging, etc.) |
expires_at | datetime | None | Expiry as a timezone-aware datetime |
not_before | datetime | None | Not-valid-before as a timezone-aware datetime |
meta | dict | Arbitrary user-defined metadata |
raw_key | str | Original key string |
Errors
All validation failures raise ApikeeError with a code attribute:
| Code | Cause |
|---|---|
MISSING_KEY | No key in request header |
INVALID_PREFIX | Key doesn't start with apikee_ |
INVALID_FORMAT | Missing . separator |
DECODE_ERROR | Invalid base62 or JSON |
INVALID_SIGNATURE | HMAC check failed |
EXPIRED | exp timestamp is in the past |
NOT_YET_VALID | nbf timestamp is in the future |
INSUFFICIENT_SCOPE | Key missing required scope |
SERVER_REJECTED | apikee.dev rejected the request (server mode) |

