Compliance API

Rate limits

Every API key has a per-minute request limit (the rate_limit_per_minute column on api_keys). Default is 60 requests/minute; admin-tunable per key without a migration.

Headers on every response

X-RateLimit-Limit:     60
X-RateLimit-Remaining: 58
X-RateLimit-Reset:     1715731234   # unix epoch seconds

When you hit the limit

429 Too Many Requests with a Retry-After header (in seconds):

HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1715731257
Content-Type: application/json

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "API rate limit exceeded",
    "retry_after": 23
  }
}

Unauthenticated requests

Requests without a valid Bearer token are throttled by client IP at 30/minute, regardless of any per-key limit. This is to discourage prefix probing — 401s are not free.

Sensible client behavior

  • Read the headers. Don't blindly retry; check X-RateLimit-Remaining and back off when it approaches zero.
  • Honor Retry-After. Wait at least that many seconds before retrying.
  • Use ETags. If-None-Match: "MO-v4" returns a 304 with an empty body and still counts as one request, but is much cheaper for both sides.
  • Use the change feed for polling. GET /api/v1/compliance/changes?since=<last_seen> returns only what's changed since you last synced — far cheaper than walking all 51 states on a cron.