Understand and optimize your API usage
Rate limits protect the API from abuse and ensure stable performance for all users. Each API key has specific limits based on your plan.
Different plans have different rate limits:
Enterprise limits are customizable based on your needs
Need higher limits? Upgrade your plan
Each API response includes headers showing your current rate limit status:
X-RateLimit-Limit - Maximum requests per windowX-RateLimit-Remaining - Remaining requests in this windowX-RateLimit-Reset - Unix timestamp when limit resetsX-RateLimit-Limit: 60 X-RateLimit-Remaining: 45 X-RateLimit-Reset: 1704297600
// PHP $reset = $headers['X-RateLimit-Reset']; $secondsUntilReset = $reset - time(); echo "Rate limit resets in {$secondsUntilReset} seconds"; // JavaScript const reset = parseInt(headers['x-ratelimit-reset']); const secondsUntilReset = reset - Math.floor(Date.now() / 1000); console.log(`Rate limit resets in ${secondsUntilReset} seconds`);
When you exceed the rate limit, you'll receive a 429 response:
HTTP/1.1 429 Too Many Requests Retry-After: 60 X-RateLimit-Limit: 60 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1704297660 { "success": false, "error": { "code": "rate_limit_exceeded", "message": "Rate limit exceeded. Try again in 60 seconds." } }
429 responses include a Retry-After header telling you how many seconds to wait before trying again.
Wait progressively longer between retries (1s, 2s, 4s, 8s...)
Always use the Retry-After header if present
Add random variation to retry delays to avoid thundering herd
Set a maximum retry limit (e.g., 3-5 attempts)
Follow these best practices to stay within rate limits:
Always check the X-RateLimit-Remaining header and slow down when it gets low.
Limit your own requests proactively instead of waiting for 429 errors.
Instead of making repeated GET requests, use webhooks for real-time notifications.
Some endpoints support batch operations - use them to reduce request count.
Cache data that doesn't change often (products, categories, settings).
Only fetch the pages you need. Use the per_page parameter wisely.
Only fetch data you actually need. Avoid fetching the same data multiple times.
Use If-Modified-Since or If-None-Match headers when supported.
Examples of handling rate limiting in different languages:
function makeApiRequest($url, $apiKey, $maxRetries = 3) { $attempt = 0; while ($attempt < $maxRetries) { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer {$apiKey}"], CURLOPT_HEADER => true, ]); $response = curl_exec($ch); $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headers = substr($response, 0, $headerSize); $body = substr($response, $headerSize); curl_close($ch); if ($statusCode === 429) { // Extract Retry-After header preg_match('/Retry-After:\s*(\d+)/i', $headers, $matches); $retryAfter = $matches[1] ?? pow(2, $attempt); error_log("Rate limited. Retrying after {$retryAfter}s"); sleep($retryAfter); $attempt++; continue; } return json_decode($body, true); } throw new Exception('Max retries exceeded'); }
async function makeApiRequest(url, apiKey, maxRetries = 3) { let attempt = 0; while (attempt < maxRetries) { try { const response = await fetch(url, { headers: { 'Authorization': `Bearer ${apiKey}` } }); if (response.status === 429) { const retryAfter = parseInt( response.headers.get('retry-after') || Math.pow(2, attempt) ); console.log(`Rate limited. Retrying after ${retryAfter}s`); await new Promise(resolve => setTimeout(resolve, retryAfter * 1000)); attempt++; continue; } return await response.json(); } catch (error) { console.error('Request failed:', error); attempt++; } } throw new Error('Max retries exceeded'); }
import requests import time def make_api_request(url, api_key, max_retries=3): attempt = 0 headers = {'Authorization': f'Bearer {api_key}'} while attempt < max_retries: response = requests.get(url, headers=headers) if response.status_code == 429: retry_after = int( response.headers.get('retry-after', 2 ** attempt) ) print(f'Rate limited. Retrying after {retry_after}s') time.sleep(retry_after) attempt += 1 continue response.raise_for_status() return response.json() raise Exception('Max retries exceeded')
Keep track of your API usage:
View API usage statistics in the admin panel under Settings → API Keys.
Review detailed request logs with timestamps, endpoints, and status codes.
Configure email alerts when approaching your rate limit (Enterprise feature).
Log rate limit headers from each response to track usage over time.
Common rate limit issues and solutions:
Problem: You always get 429 errors even with few requests.
Solution:
Problem: You have periods of many requests followed by silence.
Solution:
Problem: All your users share the same API key and limit.
Solution:
Explore related topics: