Rate Limits
To ensure API stability and fair usage, Zenovay implements rate limiting across all API endpoints. Rate limits vary based on your subscription tier and are designed to support typical usage patterns while preventing abuse.
Rate Limit Tiers
Rate limits are enforced per API key and reset every minute:
| Subscription Tier | Requests per Minute | Monthly Limit |
|---|---|---|
| Free | 10 | 1,000 |
| Pro | 30 | 10,000 |
| Scale | 60 | 100,000 |
| Enterprise | 120 | 1,000,000 |
Enterprise plans can request custom rate limits based on their specific needs. Contact our sales team for more information.
Rate Limit Headers
Every API response includes the following headers to help you track your current rate limit status:
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 29
X-RateLimit-Reset: 1642771200
The X-RateLimit-Limit value reflects your plan's per-minute limit (e.g., 10 for Free, 30 for Pro, 60 for Scale, 120 for Enterprise).
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum number of requests allowed in the current time window |
X-RateLimit-Remaining | Number of requests remaining in the current time window |
X-RateLimit-Reset | Unix timestamp when the rate limit window resets |
Rate Limit Exceeded
When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
"error": {
"message": "Rate limit exceeded. Please try again later.",
"code": "rate_limit_exceeded",
"retry_after": 45
}
}
The response includes a Retry-After header indicating how many seconds you should wait before making another request.
Handling Rate Limits
Implement Exponential Backoff
When you receive a 429 response, implement exponential backoff to avoid overwhelming the API:
async function makeRequestWithRetry(url: string, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return response;
} catch (error) {
if (i === maxRetries - 1) throw error;
}
}
}
Monitor Rate Limit Headers
Track the X-RateLimit-Remaining header and slow down requests before hitting the limit:
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining') || '0');
if (remaining < 10) {
// Slow down requests when approaching limit
await new Promise(resolve => setTimeout(resolve, 1000));
}
Batch Requests
Where possible, batch multiple operations into a single API call to reduce the number of requests:
// Instead of multiple requests
for (const event of events) {
await trackEvent(event); // 100 requests
}
// Batch into a single request
await trackEvents(events); // 1 request
Rate Limits by Endpoint
Different endpoints may have different rate limits based on their resource intensity:
| Endpoint Category | Rate Limit Multiplier |
|---|---|
| Event Tracking | 1x (standard) |
| Analytics Queries | 1x (standard) |
| Bulk Data Export | 0.5x (more lenient) |
| Administrative Operations | 2x (more restrictive) |
Abuse of the API or attempts to bypass rate limiting may result in temporary or permanent suspension of API access.
Upgrading Your Plan
If you consistently hit rate limits, consider upgrading your subscription plan:
- Pro Plan: 3x increase in rate limits
- Scale Plan: 6x increase in rate limits
- Enterprise Plan: 12x increase in rate limits
Visit zenovay.com to compare plans and upgrade your account.
Best Practices
- Cache responses when data doesn't change frequently
- Use the live endpoint for real-time visitor counts (public, no API key needed)
- Implement retry logic with exponential backoff
- Monitor rate limit headers to avoid hitting limits
- Use aggregated endpoints to reduce request count
Need Higher Limits?
If you require higher rate limits for a specific use case, please contact our support team at [email protected] with details about your integration.