Skip to content

Rate limits

Each API key has its own request budget. Limits are returned in the key’s /me response and enforced per minute on a rolling window.

Endpoint groupRequests per minute
Read endpoints (GET)300
Write endpoints (POST, PATCH, PUT, DELETE)30

Higher limits may be granted on request — contact your account manager.

Every response carries the current state of your budget:

HTTP/1.1 200 OK
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1748340060
HeaderMeaning
X-RateLimit-LimitMaximum requests in the current window.
X-RateLimit-RemainingRequests left before the window resets.
X-RateLimit-ResetUnix epoch (seconds) when the window resets.

When the budget is exhausted the API returns 429 Too Many Requests with a Retry-After header:

HTTP/1.1 429 Too Many Requests
Retry-After: 23
Content-Type: application/json
{ "error": { "code": "rate_limited", "message": "Too many requests" } }

Retry-After is the number of seconds until the next request will succeed. Sleep at least that long before retrying.

async function withRetry(fn, { maxAttempts = 5 } = {}) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const res = await fn();
if (res.status !== 429) return res;
const retryAfter = Number(res.headers.get('retry-after') ?? 1);
const backoff = Math.min(retryAfter, 2 ** attempt);
await new Promise((r) => setTimeout(r, backoff * 1000));
}
throw new Error('rate-limit retry budget exhausted');
}

The same shape works in Python:

import time, httpx
def with_retry(call, max_attempts=5):
for attempt in range(1, max_attempts + 1):
res = call()
if res.status_code != 429:
return res
retry_after = int(res.headers.get('retry-after', '1'))
time.sleep(min(retry_after, 2 ** attempt))
raise RuntimeError('rate-limit retry budget exhausted')

Call GET /api/v1/me to inspect your key’s configured rateLimit:

{
"rateLimit": { "limit": 300, "remaining": 287, "reset": 1748340060 }
}

This is the same data as the response headers, useful for dashboards that don’t make a real request per check.