Rate Limits & Quotas
Every API key in Otesse is subject to rate limits that protect the platform from abuse and ensure fair resource allocation across all organizations. Rate limits are tiered by organization plan and enforced per-key. This page explains the rate limit tiers, how limits are communicated, and how to handle rate-limited responses.
Rate Limit Tiers
Rate limits vary by organization plan:
| Tier | Requests/Minute | Requests/Hour | Requests/Day | Burst Limit |
|---|---|---|---|---|
| Free | 30 | 500 | 5,000 | 10 |
| Pro | 120 | 5,000 | 50,000 | 30 |
| Enterprise | 600 | 30,000 | 300,000 | 100 |
What Each Limit Means
- Requests/Minute — The sustained request rate. Resets every 60 seconds
- Requests/Hour — Protects against prolonged high-volume usage. Resets every 60 minutes
- Requests/Day — The daily quota. Resets at midnight UTC
- Burst Limit — Maximum concurrent requests. Prevents sudden spikes from overwhelming the system
All limits are enforced per API key. If your organization has multiple keys, each key has its own independent limits.
Rate Limit Headers
Every API response includes rate limit headers so your application can track its usage:
| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window | 120 |
X-RateLimit-Remaining | Requests remaining before hitting the limit | 87 |
X-RateLimit-Reset | Unix timestamp when the current window resets | 1709312400 |
These headers appear on every response, not just rate-limited ones. Your application should monitor X-RateLimit-Remaining and throttle requests as it approaches zero.
Handling 429 Responses
When your application exceeds the rate limit, the API returns:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 15
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1709312400
{
"error": "rate_limited",
"message": "Rate limit exceeded. Try again in 15 seconds.",
"retryAfter": 15
}
Recommended Handling
- Read the Retry-After header — This tells you exactly how many seconds to wait before retrying
- Implement exponential backoff — If the first retry also fails, double the wait time
- Queue requests — Buffer outgoing requests and process them at a sustainable rate
- Spread requests over time — Instead of making 100 requests in 1 second, spread them across the minute
Example Retry Logic
async function apiCallWithRetry(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') || '10'
);
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Rate Limit Violations
When a rate limit is exceeded, the system creates a RateLimitViolation record:
| Field | Description |
|---|---|
| API Key ID | Which key triggered the violation |
| Violation Type | Which limit was exceeded (per-minute, per-hour, per-day, or burst) |
| Request Count | Number of requests in the window at violation time |
| Timestamp | When the violation occurred |
| Endpoint | Which API endpoint was being called |
| IP Address | Source IP of the request |
Administrators can view rate limit violations in the API key detail view under "Usage Summary." Repeated violations may indicate that:
- The application needs to be optimized for fewer API calls
- The organization should upgrade to a higher plan tier
- The application has a bug causing excessive requests (e.g., an infinite loop)
Usage Monitoring
Every API request creates an ApiUsageLog entry:
| Field | Description |
|---|---|
| Timestamp | When the request was made |
| Endpoint | The API path that was called |
| HTTP Method | GET, POST, PUT, PATCH, or DELETE |
| Status Code | The response status (200, 401, 429, etc.) |
| Response Time | How long the request took (milliseconds) |
| IP Address | Source IP |
| Rate Limited | Whether this request was rate limited |
The usage log is accessible from the API key detail view and can be filtered by date range, endpoint, status code, and IP address. This helps diagnose performance issues, identify unusual usage patterns, and plan for capacity.
Best Practices
- Cache responses — Store API responses locally and serve from cache when possible. This dramatically reduces request count.
- Use pagination efficiently — Request the maximum page size to minimize the number of list calls.
- Batch operations — Use bulk endpoints (where available) instead of individual record operations.
- Monitor the Remaining header — Proactively slow down before hitting the limit, rather than reacting to 429 responses.
- Set up alerts — Configure notifications for when API usage approaches your daily quota.
On this page