Skip to main content

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
HeaderTypeDescription
X-RateLimit-LimitnumberMaximum requests allowed in the time window
X-RateLimit-RemainingnumberRemaining requests in current window
X-RateLimit-ResetnumberUnix timestamp when the window resets

Rate Limit Tiers

Integration Endpoints

EndpointLimitWindowDescription
Order creation1001 minutePOST /integrations/*/orders
Order queries5001 minuteGET /integrations//orders/
Delivery windows2001 minuteGET /integrations/yango/delivery-windows
Bulk availability501 minuteGET /integrations/yango/availability-bulk
Zone export1001 minuteGET /integrations/yango/zones/export
Order release1001 minutePOST /integrations/yango/orders/*/release

Provisioning Endpoints

EndpointLimitWindowDescription
List organizations1201 hourGET /provisioning/organizations
Create organization301 hourPOST /provisioning/organizations
Add admin601 hourPOST /provisioning/organizations/*/admins
Resend invite301 hourPOST /provisioning/admins/*/resend-invite
Reset password301 hourPOST /provisioning/admins/*/reset-password
List API keys1201 hourGET /provisioning/organizations/*/api-keys
Create API key601 hourPOST /provisioning/organizations/*/api-keys
Rotate API key601 hourPOST /provisioning/organizations//api-keys//rotate
Revoke API key601 hourDELETE /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:

  1. Optimize your integration - Use bulk endpoints, caching, and batching
  2. 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:

  1. Navigate to SettingsAPI Usage
  2. View real-time rate limit usage
  3. Analyze historical usage patterns
  4. 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