Skip to content

Rate Limits

Rate limits protect the API and ensure fair usage across all developers. Limits apply per developer account on a sliding 1-hour window and cover all API calls (session start, upload-complete, result retrieval). Your specific limits depend on your account configuration — check the response headers below.

Every API response includes headers showing your current rate limit status:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 1712005400
HeaderDescription
X-RateLimit-LimitMaximum requests allowed per hour
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the rate limit window resets

When you exceed the rate limit, the API returns a 429 response with a Retry-After header:

{
"error": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"retryable": true
}

Response headers on 429:

Retry-After: 45
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1712005400

Always respect the Retry-After header — it tells you how many seconds to wait before retrying:

async function callWithRateLimit(url: string, options: RequestInit) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10);
console.log(`Rate limited. Retrying in ${retryAfter} seconds.`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
return fetch(url, options);
}
return response;
}
  • Monitor remaining requests via X-RateLimit-Remaining headers to avoid hitting limits
  • Implement backoff — never retry immediately on a 429 response
  • Cache results — once you retrieve session results, store them on your side. Don’t poll repeatedly for the same session

Contact sales@circadify.com to discuss higher rate limits.