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 RequestsResponse Headers#
Every response includes rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1711234585Backends#
| Backend | Storage | Persistence | Use Case |
|---|---|---|---|
| In-memory | Python dict | Process lifetime | Single-instance deployments |
| Redis | Redis hashes | Persistent | Multi-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 secondAPI 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_a1B2c3D4e5F6g7H8i9J0k1L2m3N4o5P6q7R8s9T0u1V2Keys 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=7Per-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:
X-Api-Keyheader (API key)Authorization: Bearerheader (bearer token hash)ig_sessioncookie (session ID)- Client IP (fallback)
Public paths (health check, metrics, etc.) skip rate limiting entirely.