Rate Limits
LumoAuth applies rate limits per API key and per endpoint category to ensure service availability for all organizations.
Rate Limit Headers
Every API response includes rate limit headers:
Response Headers
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1706799060
Retry-After: 30
| 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 |
Retry-After | Seconds to wait (only present on 429 responses) |
Limits by Endpoint
| Endpoint Category | Limit | Window |
|---|---|---|
| Admin API (read) | 1,000 requests | per minute |
| Admin API (write) | 100 requests | per minute |
| OAuth token endpoint | 30 requests | per minute per client |
| SCIM endpoints | 200 requests | per minute |
| JIT / AAuth endpoints | 60 requests | per minute |
| Audit log export | 10 requests | per hour |
Handling 429
429 Too Many Requests
{
"error": "rate_limit_exceeded",
"message": "Too many requests. Please retry after 30 seconds.",
"status": 429,
"retryAfter": 30
}
Implement exponential back-off with jitter when handling 429 responses:
Exponential Back-off (JavaScript)
async function requestWithRetry(fn, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const res = await fn();
if (res.status !== 429) return res;
const retryAfter = parseInt(res.headers.get("Retry-After") ?? "1", 10);
const jitter = Math.random() * 1000;
await new Promise((r) => setTimeout(r, retryAfter * 1000 + jitter));
}
throw new Error("Max retries exceeded");
}
tip
For bulk provisioning (e.g. importing large user sets), use the SCIM Bulk endpoint to reduce the number of individual API calls by combining multiple operations in a single request.