API Rate Limiting & Key Management#

The management API has a token bucket rate limiter, per-key rate limits, API key lifecycle management (create, revoke, rotate), and usage tracking with quotas.

Rate Limiting#

Token Bucket Algorithm#

Each client (identified by API key, bearer token, session, or IP) gets a token bucket with a configurable capacity and refill rate. Every request consumes one token. If the bucket is empty, the request gets a 429 response with Retry-After and X-RateLimit-* headers.

Bucket capacity: 60 tokens
Refill rate: 1 token/second

Request arrives -> check tokens >= 1
  yes -> consume 1 token, serve request
  no  -> 429 Too Many Requests

Response Headers#

Every response includes rate limit headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1711234585

Backends#

BackendStoragePersistenceUse Case
In-memoryPython dictProcess lifetimeSingle-instance deployments
RedisRedis hashesPersistentMulti-instance or restartable deployments

The Redis backend sets a TTL on each bucket key to avoid stale entries.

Configuration#

api:
  rate_limit:
    enabled: true
    backend: "memory"             # "memory" or "redis"
    redis_url: "redis://localhost:6379/0"
    default_capacity: 60          # max tokens
    default_refill_rate: 1.0      # tokens per second

API Key Management#

API keys provide programmatic access with per-key rate limits and quotas.

Key Format#

Keys are prefixed with ig_ followed by 32 bytes of URL-safe base64:

ig_a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6q7R8s9T0u1V2

Keys are stored as SHA-256 hashes. The plaintext is only returned once at creation time.

Endpoints#

# List all API keys
curl -H "Authorization: Bearer $TOKEN" https://ig:8080/api/keys

# Create a new key
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "automation", "rate_limit_capacity": 120, "rate_limit_refill_rate": 2.0}' \
  https://ig:8080/api/keys

# Revoke a key
curl -X DELETE -H "Authorization: Bearer $TOKEN" \
  https://ig:8080/api/keys/{key_id}

# Rotate a key (revoke old, create new with same metadata)
curl -X POST -H "Authorization: Bearer $TOKEN" \
  https://ig:8080/api/keys/{key_id}/rotate

# Get usage stats for a key
curl -H "Authorization: Bearer $TOKEN" \
  https://ig:8080/api/keys/{key_id}/usage?days=7

Per-Key Rate Limits#

Each API key can have its own rate limit capacity and refill rate that override the defaults:

{
  "name": "high-volume-automation",
  "rate_limit_capacity": 300,
  "rate_limit_refill_rate": 5.0,
  "quota_limit": 10000,
  "quota_window_seconds": 86400
}

Usage Tracking & Quotas#

The UsageTracker records every API request per key and enforces optional quotas.

Quota Enforcement#

When a key has quota_limit and quota_window_seconds set, the tracker counts requests in the rolling window. Exceeding the quota returns 429 with quota details:

{
  "error": "Quota exceeded",
  "quota": {
    "current_usage": 10001,
    "quota_limit": 10000,
    "reset_at": "2025-03-16T00:00:00Z"
  }
}

Usage Summary#

Daily usage counts for the past N days:

curl -H "Authorization: Bearer $TOKEN" \
  https://ig:8080/api/keys/{key_id}/usage?days=7
{
  "key_id": "abc123",
  "days": 7,
  "usage": [
    {"date": "2025-03-15", "count": 1247},
    {"date": "2025-03-14", "count": 983},
    ...
  ]
}

Rate Limit Key Priority#

The middleware determines the rate limit key from the request in this order:

  1. X-Api-Key header (API key)
  2. Authorization: Bearer header (bearer token hash)
  3. ig_session cookie (session ID)
  4. Client IP (fallback)

Public paths (health check, metrics, etc.) skip rate limiting entirely.