Rate limits
Hourly scan quotas, response headers, and what happens when you run out.
Every scan — API key or dashboard — consumes one unit of your hourly quota. The counter is stored per user, not per key, so two keys on the same account share the same bucket.
Window
The window is the current clock hour (truncated to the hour). At 14:00:00 the counter resets, regardless of when the first scan in the previous hour happened.
Headers
Successful scans include:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Plan allowance for the hour |
X-RateLimit-Remaining | Scans left in this window |
X-RateLimit-Reset | Unix timestamp (seconds) when the window ends |
These headers are also exposed to browsers via CORS.
When you hit the limit
The API responds with 429 Too Many Requests:
429
{
"error": "Rate limit exceeded",
"message": "...",
"limit": 5,
"resetTime": 1710000000,
"retryAfter": 842
}
Plus:
Retry-After— seconds to waitX-RateLimit-Remaining: 0X-RateLimit-Reset— same timestamp asresetTime
The dashboard scanner surfaces the same condition as a quota error and points you to billing.
Other throttles
Billing actions (overview, checkout, portal, sync) have their own short windows so a client cannot hammer Stripe:
- reads: 60 per minute
- writes: 10 per minute
Those limits are independent from scan quota.
The API rate limits page shows the same contract with copy-paste header handling.