fastapi-keygate
API-key authentication, per-key rate limiting and per-key usage tracking for FastAPI — in a few lines, with zero setup (SQLite by default).
pip install fastapi-keygate
from fastapi import Depends, FastAPI
from keygate import ApiKey, KeyGate
app = FastAPI()
gate = KeyGate(app, admin_secret="change-me") # SQLite, zero setup
@app.get("/hello")
def hello(key: ApiKey = Depends(gate.require)):
return {"hello": key.owner_id}
if not gate.list_keys(): # demo only: mint a first key
print("Your API key:", gate.create_key("demo-tenant", per_minute=5).key)
uvicorn app:app
curl -H "X-API-Key: kg_..." localhost:8000/hello # 200, then 429 after 5/minute
(The package is fastapi-keygate on PyPI; you import keygate.)
What you get
- Auth —
Depends(gate.require)returns the caller'sApiKey(id,owner_id, limits). Missing/invalid/revoked →401. Keys are read fromX-API-KeyorAuthorization: Bearer, never from query strings (those leak into logs). - Per-key rate limits — requests per minute and/or hour, stored on each key. Over limit →
429withRetry-After; successful responses carryX-RateLimit-*headers. - Usage tracking — every authenticated request is logged (timestamp, method, route, status).
- Key management — from Python or an opt-in admin API.
Keys look like kg_<prefix>_<secret>. Only a SHA-256 hash is stored; the plaintext is shown once at creation.
Managing keys
k = gate.create_key("acme", name="prod", per_minute=60, per_hour=1000)
k.key # plaintext, only available here
gate.list_keys("acme") # [ApiKey, ...]
gate.revoke(k.id)
gate.usage(k.id, last_hours=24)
# UsageStats(total=…, by_status={200: …, 429: …}, by_endpoint={"GET /hello": …}, …)
Omitted limits use KeyGate(default_per_minute=60, default_per_hour=None); pass None for unlimited.
With admin_secret set, these endpoints are mounted (header X-Admin-Secret). Without it, nothing is exposed.
| Method | Path | |
|---|---|---|
| POST | /keygate/keys |
{"owner_id": "acme", "per_minute": 30} → returns the key once |
| GET | /keygate/keys?owner_id=acme |
list |
| DELETE | /keygate/keys/{id} |
revoke |
| GET | /keygate/keys/{id}/usage?last_hours=24 |
stats |
Configuration
KeyGate(
app,
db_url="postgresql+psycopg://user:pw@host/db", # any SQLAlchemy URL
limits_uri="redis://localhost:6379", # shared rate-limit store
admin_secret=...,
)
Things to know
- Multiple workers: the default rate-limit store is in memory, per process. With N Uvicorn/Gunicorn workers a
60/minlimit becomes up to60×N. Uselimits_uri="redis://..."(pip install fastapi-keygate[redis]) in that case. - Why not slowapi? Rate limiting uses
limits, the engine slowapi wraps. slowapi is built around per-endpoint decorators that need arequestargument; keygate's limits belong to the key, so they're enforced inside the auth dependency. You can still use slowapi alongside it. - Schema: tables are created on startup (
create_all); there are no migrations yet. - Not included (yet): async engines, key expiry, scopes/roles, rotation.
- Timestamps are naive UTC.
Development
pip install -e ".[dev]" && pytest
MIT licensed.
Metadata
Release files for fastapi-keygate 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fastapi_keygate-0.1.0.tar.gz | 10.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_keygate-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.4 kB
Release files / fastapi_keygate-0.1.0.tar.gz
| Download URL | fastapi_keygate-0.1.0.tar.gz |
|---|---|
| Size | 10.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
47f38a47b78d33db03ab5a1241d1fb4f2dae0da5c62ef3795b69e8117a447f05
|
|
BLAKE2b-256 checksum How to use checksums |
eb592376aa9dd4e3cb0d1ca8a4315a15280ef7bd87b9323a1f60a948e8a166cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency logRelease files / fastapi_keygate-0.1.0-py3-none-any.whl
| Download URL | fastapi_keygate-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5e4135d9bb519aeda8c5335d64303cc84735ff06f03d298d76c96e20b5cd77c1
|
|
BLAKE2b-256 checksum How to use checksums |
0a0e178dcf0d496de1dd1aed55eea366884ab058915c9d28dea6db8fa8ddf6a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.
Transparency log