02Reference · Rate limits

Per-key budgets, headed honestly.

We enforce a per-key, per-minute ceiling at the gateway and a separate per-user ceiling on key-management endpoints. Every response — success or failure — exposes where you stand.

Public-API budgets

Per key, per minute (configurable at key creation)

FieldTypeNotes
default60 req/minApplied to every new key unless you specify rate_limit_per_min at creation.
minimum1 req/minLower bound enforced server-side.
maximum600 req/minUpper bound enforced server-side. Need more? Email us.

Limits are scoped per api_key_id. Multiple keys belonging to the same user get independent budgets. Hitting the budget returns 429 with Retry-After.

Dashboard endpoint budgets

Per user, on key-management routes

FieldTypeNotes
POST /api/api-keys5 / hourCreate a new key.
GET /api/api-keys30 / minList your keys.
DELETE /api/api-keys/[id]30 / minRevoke a key.
GET /api/api-keys/[id]/usage30 / minPer-key usage rollup.

Response headers

On every gateway response you'll find:

Headers

FieldTypeNotes
X-RateLimit-LimitintegerYour per-key per-minute ceiling.
X-RateLimit-RemainingintegerCalls left in the current window.
X-RateLimit-Resetunix secondsWhen the window resets.
Retry-AftersecondsSent on 429 only. Wait at least this long before retrying.
curl
# A 429 response carries Retry-After + the standard
# X-RateLimit-* headers. Honour Retry-After before retrying.
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1761350400
Content-Type: application/json

{ "error": "Too many requests", "message": "Rate limit exceeded. Please retry shortly." }
javascript
async function callWithBackoff(url, init, attempt = 0) {
const res = await fetch(url, init);
if (res.status !== 429) return res;
const retryAfter = parseInt(res.headers.get("Retry-After") || "1", 10);
const wait = Math.max(retryAfter, Math.pow(2, attempt)) * 1000;
await new Promise((r) => setTimeout(r, wait));
return callWithBackoff(url, init, attempt + 1);
}
python
import time, requests

def call_with_backoff(method, url, **kw):
for attempt in range(6):
r = requests.request(method, url, **kw)
if r.status_code != 429:
return r
wait = max(int(r.headers.get("Retry-After", "1")), 2 ** attempt)
time.sleep(wait)
r.raise_for_status()

Was this page helpful?