API Gateway

A FastAPI-based gateway that exposes a single entrypoint for multiple upstream APIs, with a built-in web management console.

Features

  • Single entrypoint — consumers call /<service-slug>/<path> and the gateway proxies to the registered upstream (all HTTP methods, query strings, bodies, headers). /admin, /static, /docs and /health are reserved.

  • Endpoint catalog, auto-synced — each service's callable endpoints are mirrored from its OpenAPI document (/openapi.json, /swagger.json or /api-docs) whenever the API Keys page loads: new operations appear, removed ones are deleted (their grants with them). Services without a reachable spec keep their existing catalog. Patterns support {param} (one segment), * (within a segment) and ** (any depth).

  • Per-key access rights, hierarchical picker — every API key is granted a specific set of endpoints, chosen in a path tree (service → path segments → operations) where a parent checkbox selects everything beneath it. A request must match a listed endpoint AND the key must hold a grant on it; otherwise 404 (unknown_endpoint) or 403 (access_denied). Keys are hashed at rest, shown once at creation, revocable, with per-key rate limits.

  • Web management console (/admin) — manage connected APIs, users, and API keys; usage dashboards with charts. Every console user has full management access.

  • Transaction capture & request browser — every gateway request is recorded with service, endpoint, key, status, latency, client IP, query string, and the request/response payloads (textual bodies up to 64 KB; binary summarized). The Requests page filters by service / user / key / status class / path and links to a per-request detail view showing the complete transaction.

  • Usage monitoring — charts: traffic and average latency over time (adaptive buckets: 5 min / 1 h / 1 day), volume by service / user / endpoint, status codes, latency by service, top keys — filterable by time range (1 h 30 d), service, user and key.

  • Consumer docsGET /openapi.json (authenticated with X-API-Key) returns a merged OpenAPI document scoped to that key: every operation the key holds a grant on, across all services, rewritten to the gateway's routes. GET /docs serves a Swagger UI portal around it — paste a key, browse and try exactly what that key can call.

  • Machine catalog — a hierarchical, key-scoped catalog for agents/MCP clients: GET /catalog (available APIs with descriptions), then /catalog/{slug} (tags), then /catalog/{slug}/tags/{tag} (endpoints; oversized tags group by path prefix, drill with ?prefix=), then /catalog/{slug}/operation?method=&path= (full schema, $refs resolved inline). Authenticated with X-API-Key; responses carry ETags.

  • Retention — a background purge runs every 6 hours: request/response payloads are blanked after 7 days (the log row stays inspectable), whole log rows are deleted after 90 days, and freed pages are returned to the filesystem via incremental vacuum. Both windows are configurable; 0 disables that tier.

Quick start

pip install -r requirements.txt
uvicorn app.main:app --host 0.0.0.0 --port 8000

Open http://localhost:8000/admin — first startup seeds an admin account (admin / admin by default — change it immediately).

Docker

docker compose up -d

The console is served on http://localhost:8000/admin; the SQLite database persists in the gateway-data volume. Set GATEWAY_SECRET_KEY (and the admin credentials) in docker-compose.yml before deploying anywhere real. The image runs a single uvicorn worker on purpose — the rate limiter and the OpenAPI sync cache are in-memory.

Configuration (environment variables)

Variable Default Purpose
GATEWAY_DATABASE_URL sqlite:///./gateway.db SQLAlchemy database URL
GATEWAY_SECRET_KEY dev value Session cookie signing key — set in production
GATEWAY_ADMIN_USER / GATEWAY_ADMIN_PASSWORD admin / admin Seeded admin credentials
GATEWAY_PAYLOAD_RETENTION_DAYS 7 Blank stored payloads after N days (0 = keep forever)
GATEWAY_LOG_RETENTION_DAYS 90 Delete log rows after N days (0 = keep forever)

Using the gateway as a consumer

  1. Register a service (e.g. slug weatherhttps://api.example.com/v1) and list its endpoints (import from OpenAPI or add manually).
  2. Issue an API key and tick the endpoints it may call.
  3. The consumer calls:
curl -H "X-API-Key: gw_..." "http://localhost:8000/weather/forecast?city=Paris"

The gateway authenticates the key, matches the request against the service's endpoint list, checks the key's grant and the rate limit, proxies the request to https://api.example.com/v1/forecast?city=Paris, logs it, and returns the upstream response. Gateway-generated errors are JSON with an error code: missing_api_key (401), invalid_api_key / access_denied (403), unknown_service / unknown_endpoint (404), rate_limited (429), upstream_unreachable (502), upstream_timeout (504).

Notes & limits

  • The stats queries use SQLite date functions; if you point GATEWAY_DATABASE_URL at Postgres/MySQL, adapt app/admin/stats.py (strftime, iif).
  • The rate limiter is in-memory (single process). Run one worker, or swap in Redis for multi-worker deployments.
  • Streaming responses are buffered (fine for JSON APIs; not for large file proxying).
S
Description
No description provided
Readme
124 KiB
Languages
Python 59.3%
HTML 32.5%
CSS 7.7%
Dockerfile 0.5%