Skip to main content

Rate Limits

KlayrAI enforces rate limits to ensure fair usage and platform stability. Limits are applied per API key.

Default limits

Operation typeLimitWindow
Read requests (GET)120 requestsPer minute
Write requests (POST, PUT, DELETE)10 requestsPer minute
Diagnostic runs10 runsPer minute
Report generations5 generationsPer minute
These limits apply to the Agency plan API. Dashboard usage has separate, more generous limits that are not publicly documented.

Rate limit information

Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After) are not currently returned in HTTP response headers. Instead, rate limit information is included in the JSON response body in the meta.remaining_requests field.

Example response with rate limit info

{
  "data": [ ... ],
  "meta": {
    "remaining_requests": 87
  },
  "pagination": {
    "total": 12,
    "page": 1,
    "page_size": 20,
    "hasMore": false
  }
}

Handling rate limits

When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
  "error": {
    "type": "rate_limit_error",
    "message": "Rate limit exceeded. Please retry after 12 seconds."
  }
}
Implement exponential backoff with jitter:
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

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

    if (attempt === maxRetries) {
      throw new Error("Rate limit exceeded after maximum retries");
    }

    // Exponential backoff: 1s, 2s, 4s
    const baseDelay = Math.pow(2, attempt) * 1000;

    // Add jitter: random delay between 0-1000ms
    const jitter = Math.random() * 1000;
    const delay = baseDelay + jitter;

    await new Promise((resolve) => setTimeout(resolve, delay));
  }
}

Best practices

Check the meta.remaining_requests field in each JSON response. When it drops below 10% of the limit, slow down your request rate proactively rather than waiting for a 429.
Instead of making individual requests for each campaign, use list endpoints with filters to fetch multiple records in a single request.
# Instead of 10 individual requests:
# GET /v1/campaigns/camp_001
# GET /v1/campaigns/camp_002
# ...

# Use a single list request:
curl "https://api.klayrai.com/v1/campaigns?page_size=100"
Campaign and account data changes infrequently. Cache GET responses for 60-300 seconds to reduce unnecessary API calls.
When waiting for a diagnostic or report to complete, poll GET /v1/diagnostics/{id} at reasonable intervals (every 2-3 seconds) rather than sending rapid requests. Diagnostics typically complete within 5-10 seconds.
If you need to run diagnostics on 50 campaigns, don’t fire all 50 at once. Spread them over 5 minutes (10 per minute) to stay within limits.

Rate limit increases

If your use case requires higher limits, contact us at support@klayrai.com with:
  • Your workspace ID
  • Current usage patterns
  • Requested limits with justification
  • Expected request volume
Rate limit increases are reviewed on a case-by-case basis and typically granted within 1-2 business days.