Skip to main content

fastapi-keygate

CI

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's ApiKey (id, owner_id, limits). Missing/invalid/revoked → 401. Keys are read from X-API-Key or Authorization: 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 → 429 with Retry-After; successful responses carry X-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": …}, …)

Give keys scopes and guard routes with them (missing scope → 403; the "*" scope matches everything):

k = gate.create_key("acme", scopes=["read", "write"])

@app.delete("/items/{id}")
def delete(id: int, key: ApiKey = Depends(gate.require_scopes("write"))): ...

Rotate a key without downtime: new = gate.rotate(k.id, grace=timedelta(hours=24)) returns a replacement with the same owner, limits and scopes, and the old key keeps working until the grace period ends (POST /keygate/keys/{id}/rotate?grace_hours=24 in the admin API). Rate-limit counters are per key, so during the grace period the two keys each get their own allowance.

Keys never expire unless you set expires_at= (naive UTC datetime) or expires_in=timedelta(days=30); expired keys get 401. 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, "expires_at": "2027-01-01T00:00:00", "scopes": ["read"]} → returns the key once
GET /keygate/keys?owner_id=acme list
DELETE /keygate/keys/{id} revoke
POST /keygate/keys/{id}/rotate?grace_hours=24 replacement key, old one expires after the grace period
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/min limit becomes up to 60×N. Use limits_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 a request argument; 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.
  • Timestamps are naive UTC.

Development

pip install -e ".[dev]" && pytest

MIT licensed.

Metadata

Release files for fastapi-keygate 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastapi-keygate 0.2.0
File Size Uploaded
fastapi_keygate-0.2.0.tar.gz 13.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fastapi-keygate 0.2.0
File Interpreter ABI Platform
fastapi_keygate-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 27.0 kB

Release files / fastapi_keygate-0.2.0.tar.gz

Download URL fastapi_keygate-0.2.0.tar.gz
Size 13.6 kB
Tags Source
SHA-256 checksum
How to use checksums
2faa7707df091274b29a79bc674fd39d21c53a0b6ef0fb66020835d3df2e1bdd
BLAKE2b-256 checksum
How to use checksums
3e2134dc4b178fc00bd4f1efbd7e43f08fc184ecaad53b78e8ce4201d09475ab
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

Release files / fastapi_keygate-0.2.0-py3-none-any.whl

Download URL fastapi_keygate-0.2.0-py3-none-any.whl
Size 13.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e4464c4a5fe5650ed02634a4e28b9f1f6458cffc045666affb05a37b1e3d84dd
BLAKE2b-256 checksum
How to use checksums
046ef3545ec533a76560c6db2da29a3c716b2ec7714930411523bb240509da30
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

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page