Guides · Rate limits
Rate limits
Two limits protect the API: a general per-key request rate, and your plan's monthly event quota on ingestion. Both return 429 with a Retry-After header telling you exactly how long to wait.
The two limits
| Limit | Applies to | When you hit it |
|---|---|---|
| General API rate limit | Every endpoint. 100 requests per 15 minutes. | 429 with Retry-After and RateLimit-* headers. |
| Plan event quota | Usage ingestion (POST /usage-events and /usage-events/batch). Your plan's monthly event allotment. | Single events: 429 with X-RateLimit-* + Retry-After. Batch: per-item rejections inside the 202 (see below). |
Batch ingestion never returns a batch-level 429
When your plan's event quota is exhausted, POST /usage-events/batch still returns 202. The quota rejection surfaces per event, inside the response body, not as a top-level status. Always inspect each item's status in a batch response rather than trusting the 202 alone.
Response headers
A rate-limited response carries the state you need to back off precisely.
| Header | Meaning |
|---|---|
Retry-After | Seconds to wait before retrying. Always honor this first. |
RateLimit-Reset | Seconds until the general rate-limit window resets. |
X-RateLimit-Limit | Your plan's event quota for the current period. |
X-RateLimit-Remaining | Events left in the current period. |
The body is the standard error envelope:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Slow down and retry after the current window resets.",
"correlationId": "OLIVE-DINOSAUR-1b2fE4",
"details": { "retryable": true }
}
}
Handling a 429
A 429 is retryable: true. Wait for the Retry-After interval, then retry; if it is absent, fall back to exponential backoff. Never retry in a tight loop, and never retry a 4xx that is not a 429. The SDKs implement this for you.
Reach for the SDK retry helper
The Error handling guide has a ready-made retry-with-backoff wrapper for Node.js and Python that honors Retry-After automatically.