Rate Limits
Information about API rate limits and how to handle them.
Overview
The Courimax API implements rate limiting to ensure fair usage and system stability. Rate limits are applied per API key.
Rate Limit Headers
All API responses include rate limit information in the headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1629388800
| Header | Type | Description |
|---|---|---|
X-RateLimit-Limit | number | Maximum requests allowed in the time window |
X-RateLimit-Remaining | number | Remaining requests in current window |
X-RateLimit-Reset | number | Unix timestamp when the window resets |
Rate Limit Tiers
Integration Endpoints
| Endpoint | Limit | Window | Description |
|---|---|---|---|
| Order creation | 100 | 1 minute | POST /integrations/*/orders |
| Order queries | 500 | 1 minute | GET /integrations//orders/ |
| Delivery windows | 200 | 1 minute | GET /integrations/yango/delivery-windows |
| Bulk availability | 50 | 1 minute | GET /integrations/yango/availability-bulk |
| Zone export | 100 | 1 minute | GET /integrations/yango/zones/export |
| Order release | 100 | 1 minute | POST /integrations/yango/orders/*/release |
Provisioning Endpoints
| Endpoint | Limit | Window | Description |
|---|---|---|---|
| List organizations | 120 | 1 hour | GET /provisioning/organizations |
| Create organization | 30 | 1 hour | POST /provisioning/organizations |
| Add admin | 60 | 1 hour | POST /provisioning/organizations/*/admins |
| Resend invite | 30 | 1 hour | POST /provisioning/admins/*/resend-invite |
| Reset password | 30 | 1 hour | POST /provisioning/admins/*/reset-password |
| List API keys | 120 | 1 hour | GET /provisioning/organizations/*/api-keys |
| Create API key | 60 | 1 hour | POST /provisioning/organizations/*/api-keys |
| Rotate API key | 60 | 1 hour | POST /provisioning/organizations//api-keys//rotate |
| Revoke API key | 60 | 1 hour | DELETE /provisioning/organizations//api-keys/ |
Handling Rate Limits
Check Headers
Monitor rate limit headers to avoid hitting limits:
async function makeRequest(url, options) {
const response = await fetch(url, options);
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
const reset = parseInt(response.headers.get('X-RateLimit-Reset'));
if (remaining < 10) {
const waitTime = (reset - Date.now() / 1000) * 1000;
console.log(`Rate limit low. Waiting ${waitTime}ms`);
await sleep(waitTime);
}
return response;
}
Exponential Backoff
When you receive a 429 response, implement exponential backoff:
async function requestWithBackoff(url, options, maxRetries = 5) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const waitTime = retryAfter
? parseInt(retryAfter) * 1000
: Math.pow(2, i) * 1000;
console.log(`Rate limited. Waiting ${waitTime}ms`);
await sleep(waitTime);
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Request Queuing
Queue requests to stay within limits:
class RateLimitedQueue {
constructor(limit, windowMs) {
this.limit = limit;
this.windowMs = windowMs;
this.queue = [];
this.running = 0;
this.lastReset = Date.now();
}
async add(request) {
return new Promise((resolve, reject) => {
this.queue.push({ request, resolve, reject });
this.process();
});
}
async process() {
if (this.running >= this.limit) return;
if (this.queue.length === 0) return;
// Reset counter if window has passed
if (Date.now() - this.lastReset > this.windowMs) {
this.running = 0;
this.lastReset = Date.now();
}
const { request, resolve, reject } = this.queue.shift();
this.running++;
try {
const result = await request();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.process();
}
}
}
// Usage
const queue = new RateLimitedQueue(100, 60000); // 100 requests per minute
const result = await queue.add(() =>
fetch('https://api.courimax.com/api/integrations/yango/orders', {
method: 'POST',
headers: { 'X-API-Key': API_KEY },
body: JSON.stringify(orderData)
})
);
Best Practices
Batch Operations
Use bulk endpoints when possible:
// Instead of multiple individual requests
for (const date of dates) {
await fetch(`/delivery-windows?zone=${zone}&date=${date}`);
}
// Use bulk endpoint
await fetch(`/availability-bulk?fromDate=${startDate}&toDate=${endDate}`);
Caching
Cache responses when appropriate:
const cache = new Map();
async function getDeliveryWindows(zone, date) {
const cacheKey = `${zone}-${date}`;
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const response = await fetch(
`/delivery-windows?zone=${zone}&date=${date}`
);
const data = await response.json();
// Cache for 5 minutes
cache.set(cacheKey, data);
setTimeout(() => cache.delete(cacheKey), 5 * 60 * 1000);
return data;
}
Request Prioritization
Prioritize critical requests:
const criticalQueue = new RateLimitedQueue(50, 60000);
const normalQueue = new RateLimitedQueue(50, 60000);
// Critical: Order creation
await criticalQueue.add(() => createOrder(orderData));
// Normal: Order queries
await normalQueue.add(() => getOrderStatus(orderId));
Monitoring
Monitor your rate limit usage:
class RateLimitMonitor {
constructor() {
this.usage = [];
}
track(response) {
const limit = parseInt(response.headers.get('X-RateLimit-Limit'));
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
const used = limit - remaining;
const percentUsed = (used / limit) * 100;
this.usage.push({
timestamp: Date.now(),
limit,
remaining,
percentUsed
});
if (percentUsed > 80) {
console.warn(`Rate limit usage at ${percentUsed}%`);
}
}
}
Increasing Limits
If you need higher rate limits:
- Optimize your integration - Use bulk endpoints, caching, and batching
- Contact support - Email support@courimax.com with:
- Your organization ID
- Current usage patterns
- Required limits
- Business justification
Rate Limit Errors
When you exceed the rate limit, you'll receive:
{
"statusCode": 429,
"message": "Too many requests, please try again later",
"error": "Too Many Requests"
}
Response headers include:
Retry-After: 60
Wait for the specified number of seconds before retrying.
Monitoring Tools
Dashboard
Monitor your API usage in the admin dashboard:
- Navigate to Settings → API Usage
- View real-time rate limit usage
- Analyze historical usage patterns
- Set up alerts for high usage
Alerts
Set up alerts for rate limit warnings:
// In your webhook handler
if (remaining < 20) {
sendAlert({
type: 'rate_limit_warning',
remaining,
limit,
endpoint: url
});
}
Next Steps
- Error Codes - Complete error reference
- Best Practices - API usage best practices