Rate Limits
Prepzo enforces rate limits to ensure fair usage and platform stability. Limits are transparent and communicated via response headers.
Limits by Plan
| Plan | Requests/Minute |
|---|---|
| Free | 100 |
| Pro ($49/mo) | 1,000 |
| Scale ($149/mo) | 5,000 |
| Enterprise | 10,000 |
Response Headers
Every API response includes rate limit headers:
X-RateLimit-Limit: 1000 # Your plan's limit per minute
X-RateLimit-Remaining: 847 # Requests remaining in current window
X-RateLimit-Reset: 1708345260 # Unix timestamp when the window resetsExceeding the Limit
When you exceed your rate limit, you'll receive a 429 Too Many Requests response:
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Remaining: 0
{
"success": false,
"data": null,
"errors": [{ "code": "rate_limited", "message": "Rate limit exceeded" }]
}Best Practices
- Check headers: Monitor
X-RateLimit-Remainingto avoid hitting limits - Use Retry-After: When you get a 429, wait the number of seconds in the
Retry-Afterheader - Exponential backoff: On repeated 429s, increase wait time exponentially
- Batch with bulk: Use
/api/v1/bulkfor mass operations instead of individual calls - Cache responses: Cache list responses when data doesn't change frequently
- Use webhooks: Instead of polling for changes, set up webhooks for real-time updates
Example: Rate Limit Handling
async function apiCall(url, apiKey, retries = 3) {
for (let i = 0; i < retries; i++) {
const res = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` }
});
if (res.status === 429) {
const retryAfter = parseInt(res.headers.get('Retry-After') || '60');
console.log(`Rate limited. Waiting ${retryAfter}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}
return res.json();
}
throw new Error('Max retries exceeded');
}