xcaDocs
Getting started

Rate limits and quotas

How many requests you can make and what happens when you hit a limit.

Limits depend on your plan and are counted per API key.

Requests per minute#

A rolling one-minute window per key. Every successful response carries X-RateLimit-Remaining with the requests left in the current window. Above the limit you get 429 rateLimited with error.retryAfter in seconds.

200
X-RateLimit-Remaining: 59
429
{
  "error": {
    "code": "rateLimited",
    "message": "Rate limit exceeded",
    "retryAfter": 12
  }
}

Monthly quota#

Each key has a monthly request quota that resets on the 1st of every month at 00:00 UTC. When it runs out, requests return 429 rateLimited with error.reason set to quota until the next month.

429
{
  "error": {
    "code": "rateLimited",
    "message": "Monthly quota exceeded",
    "reason": "quota"
  }
}

Daily scans#

A POST /scans call that actually starts a scan uses one scan from your plan's daily scan limit, shared with scans you start in the app. Reading reports, and scan calls that return a fresh cached report, don't use the scan limit (they still count as API requests).

Limits by plan#

PlanRequests / minuteRequests / month
Pro60100,000

Best practices#

  • Cache token reports on your side; a report stays fresh for several minutes.
  • On 429, wait for retryAfter seconds, then retry with exponential backoff and jitter.
  • Poll scans every 3–5 seconds, not in a tight loop.
  • Spread batch jobs over time instead of firing them in parallel.