REST API

Rate Limits

Limits

Scope Limit
Read endpoints (GET) 60 requests per minute
Write endpoints (POST, PUT, DELETE) 30 requests per minute

Rate limits are tracked per API key using a fixed-window counter that resets every 60 seconds.

Response Headers

Every API response includes rate limit headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1742400120
Header Description
X-RateLimit-Limit Maximum requests allowed in the current window
X-RateLimit-Remaining Requests remaining in the current window
X-RateLimit-Reset Unix timestamp when the window resets

Handling 429 Responses

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

{
  "error": {
    "type": "rate_limit_error",
    "message": "Rate limit exceeded. Please retry after the reset time.",
    "status": 429
  }
}

Headers on 429 response:

Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1742400120

Best Practices

  1. Check X-RateLimit-Remaining before making requests. If it's low, slow down.
  2. Respect Retry-After — wait the indicated seconds before retrying.
  3. Use exponential backoff if you get repeated 429s.
  4. Cache responses when possible instead of re-fetching the same data.
  5. Batch operations — make fewer, more targeted requests rather than polling frequently.

Example: Retry Logic

async function apiCall(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) return response;

    const retryAfter = parseInt(response.headers.get('Retry-After') || '5');
    console.log(`Rate limited. Retrying in ${retryAfter}s...`);
    await new Promise(r => setTimeout(r, retryAfter * 1000));
  }
  throw new Error('Max retries exceeded');
}