Rate Limits
API rate limits, headers, and error handling for rate-limited requests.
Rate Limits
All API requests are rate-limited per API key using a sliding window. Limits vary by endpoint category:
| Category | Limit | Endpoints |
|---|---|---|
| Videos | 5 req/min | /videos/* |
| Images | 10 req/min | /images/* |
| Voiceovers | 10 req/min | /voiceovers/* |
| Ad Library | 3 req/min | /ad-library/scrape |
| Reads | 60 req/min | All GET endpoints |
Rate Limit Headers
Every response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Handling Rate Limits
When rate limited, you'll receive a 429 Too Many Requests response with a Retry-After header:
JSON
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Try again in 30 seconds."
}
}Best Practices
- Check
X-RateLimit-Remainingbefore making requests - Use the
Retry-Afterheader to wait before retrying - Implement exponential backoff for retries
- Use idempotency keys to safely retry failed requests
- For bulk operations, space requests evenly within the rate window
async function fetchWithRetry(url: string, options: RequestInit, 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');
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}