Rate Limiting
The Otesse API enforces rate limits to ensure fair usage and platform stability.
Default Limits
| Plan | Rate Limit | Burst Limit |
|---|---|---|
| Standard | 100 requests/minute | 20 requests/second |
| Professional | 500 requests/minute | 50 requests/second |
| Enterprise | 2,000 requests/minute | 200 requests/second |
Limits are applied per API key. If you have multiple keys, each has its own independent limit.
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1709000400
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Handling 429 Responses
When you exceed the rate limit, the API returns:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
{
"error": {
"type": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please retry after 30 seconds.",
"retry_after": 30
}
}
Implementing Backoff
async function apiRequestWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '30');
console.log(`Rate limited. Retrying after ${retryAfter}s (attempt ${attempt + 1})`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Best Practices
- Cache responses — Store frequently-accessed data locally instead of re-fetching
- Use webhooks — Subscribe to events instead of polling for changes
- Batch operations — Use list endpoints with filters instead of individual lookups
- Monitor usage — Track your
X-RateLimit-Remainingto proactively slow down - Use exponential backoff — When rate limited, wait progressively longer between retries
On this page