Understanding Rate Limits
Every API has rate limits. Cito API's limits vary by plan:
- Free: 10 requests/minute
- Starter: 30 requests/minute
- Builder: 100 requests/minute
- Business: 500 requests/minute
Hitting these limits returns a 429 status code. Here's how to handle them gracefully.
Implementing Retry Logic
async function fetchWithRetry(url, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { const response = await fetch(url, options); if (response.status === 429) { const retryAfter = response.headers.get('Retry-After') || 60; await sleep(retryAfter * 1000); continue; } return response; } throw new Error('Max retries exceeded');}
const cache = new Map(); async function getCachedData(key, fetchFn, ttl = 30000) { const cached = cache.get(key); if (cached && Date.now() - cached.timestamp < ttl) { return cached.data; } const data = await fetchFn(); cache.set(key, { data, timestamp: Date.now() }); return data;}
const redis = new Redis(process.env.REDIS_URL); async function getCachedData(key, fetchFn, ttl = 30) { const cached = await redis.get(key); if (cached) { return JSON.parse(cached); } const data = await fetchFn(); await redis.setex(key, ttl, JSON.stringify(data)); return data;}
// Bad: 10 requestsfor (const playerId of playerIds) { await api.get(`/players/${playerId}`);} // Good: 1 requestconst players = await api.get('/players', { params: { ids: playerIds.join(',') }});
// Instead of polling every 30 secondssetInterval(fetchLiveMatches, 30000); // Use webhooks (Starter plan and above)app.post('/webhook', (req, res) => { const { event, data } = req.body; handleMatchUpdate(data); res.status(200).send('OK');});
const response = await api.get('/account/usage');console.log(`Used: ${response.data.requests_used}`);console.log(`Limit: ${response.data.requests_limit}`);
Conclusion
Good rate limit handling makes your app more reliable and your users happier. Implement caching, use webhooks where possible, and always handle 429s gracefully.
View our rate limit documentation