Rate Limiting

Understand and optimize your API usage

Overview

Rate limits protect the API from abuse and ensure stable performance for all users. Each API key has specific limits based on your plan.

Why Rate Limits?

Rate Limit Tiers

Different plans have different rate limits:

Starter Plan

  • 60 requests per minute
  • 1,000 requests per hour
  • 10,000 requests per day

Professional Plan

  • 300 requests per minute
  • 5,000 requests per hour
  • 50,000 requests per day

Enterprise Plan

  • 1,000+ requests per minute
  • 20,000+ requests per hour
  • 200,000+ requests per day

Enterprise limits are customizable based on your needs

Need higher limits? Upgrade your plan

Rate Limit Headers

Each API response includes headers showing your current rate limit status:

Example Headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1704297600

Calculate time until reset

// 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`);

Handling 429 Too Many Requests

When you exceed the rate limit, you'll receive a 429 response:

429 Response Format

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."
  }
}

Retry-After Header

429 responses include a Retry-After header telling you how many seconds to wait before trying again.

Retry Strategies

Exponential Backoff

Wait progressively longer between retries (1s, 2s, 4s, 8s...)

Respect Retry-After

Always use the Retry-After header if present

Implement Jitter

Add random variation to retry delays to avoid thundering herd

Max Retries

Set a maximum retry limit (e.g., 3-5 attempts)

Best Practices

Follow these best practices to stay within rate limits:

Monitor rate limit headers

Always check the X-RateLimit-Remaining header and slow down when it gets low.

Implement client-side rate limiting

Limit your own requests proactively instead of waiting for 429 errors.

Use webhooks instead of polling

Instead of making repeated GET requests, use webhooks for real-time notifications.

Batch requests where possible

Some endpoints support batch operations - use them to reduce request count.

Cache API responses

Cache data that doesn't change often (products, categories, settings).

Optimize pagination

Only fetch the pages you need. Use the per_page parameter wisely.

Avoid unnecessary requests

Only fetch data you actually need. Avoid fetching the same data multiple times.

Use conditional requests

Use If-Modified-Since or If-None-Match headers when supported.

Code Examples

Examples of handling rate limiting in different languages:

PHP with Retry Logic

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');
}

Node.js with Exponential Backoff

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');
}

Python with Rate Limit Tracking

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')

Monitoring API Usage

Keep track of your API usage:

Admin Panel Dashboard

View API usage statistics in the admin panel under Settings → API Keys.

API Request Logs

Review detailed request logs with timestamps, endpoints, and status codes.

Alerts

Configure email alerts when approaching your rate limit (Enterprise feature).

Response Headers

Log rate limit headers from each response to track usage over time.

Troubleshooting

Common rate limit issues and solutions:

Consistent 429 errors

Problem: You always get 429 errors even with few requests.

Solution:

  • Check if you have multiple processes/workers sharing the same API key
  • Verify you're respecting Retry-After headers
  • Consider upgrading your plan for higher limits

Bursty traffic patterns

Problem: You have periods of many requests followed by silence.

Solution:

  • Implement a request queue with rate limiting
  • Spread requests evenly over time instead of bursts
  • Use background jobs with controlled concurrency

Multi-tenant applications

Problem: All your users share the same API key and limit.

Solution:

  • Create separate API keys per customer (Enterprise feature)
  • Implement your own per-user rate limiting
  • Prioritize critical operations over nice-to-have features

Next Steps

Explore related topics:

Error Handling

Learn to handle all API error codes, not just 429

Error Handling

Webhooks

Reduce API calls by using webhooks instead of polling

Webhooks

Authentication

Understand how rate limits apply per API key

Authentication

Code Examples

See more advanced examples of rate limit handling

Code Examples