Rate Limits

Understand how rate limiting works and how to optimize your API usage.

Overview

Rate limits protect our API from abuse and ensure fair usage for all users. Limits are applied per API key and vary based on your plan.

Monthly API limits

API request limits reset on the 1st of each month at midnight UTC. QR code limits are based on your current plan allocation.

Limits by Plan

Each plan has different rate limits and quotas:

Free

API requests per month

100

Static QR codes

5

Dynamic QR codes

1

  • All QR types
  • Custom colors
  • Basic analytics (7 days)

Pro

API requests per month

1,000

Static QR codes

30

Dynamic QR codes

10

  • All QR types
  • Logo upload
  • Analytics (30 days)
  • Scan limits

Business

API requests per month

10,000

Static QR codes

Unlimited

Dynamic QR codes

100

  • Everything in Pro
  • Advanced analytics (1 year)
  • Team collaboration
  • Bulk operations

Rate Limit Headers

Every API response includes headers to help you track your usage:

HeaderDescriptionExample
X-RateLimit-LimitMax requests per month for your plan1000
X-RateLimit-RemainingRequests remaining this month847
X-RateLimit-ResetUnix timestamp when limits reset (1st of next month)1735689600
Retry-AfterSeconds to wait (only on 429 responses)3600
Example Response Headers
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1735689600

Handling Rate Limits

When you exceed the rate limit, you'll receive a 429 response. Here's how to handle it:

429 Response
{
  "success": false,
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Please retry after 30 seconds.",
    "details": {
      "retryAfter": 30
    }
  }
}

Implementing Exponential Backoff

Use exponential backoff with jitter for the most resilient implementation:

JavaScript
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.ok) {
      return response.json();
    }

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After');
      const waitTime = retryAfter
        ? parseInt(retryAfter, 10) * 1000
        : Math.min(1000 * Math.pow(2, attempt) + Math.random() * 1000, 60000);

      console.log(`Rate limited. Waiting ${waitTime}ms before retry...`);
      await new Promise(resolve => setTimeout(resolve, waitTime));
      continue;
    }

    // Non-retryable error
    const error = await response.json();
    throw new Error(error.error?.message || 'Request failed');
  }

  throw new Error('Max retries exceeded');
}

// Usage
const qrCode = await fetchWithRetry('https://quality-qr.app/api/v1/qr', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ type: 'url', content: 'https://example.com' }),
});

Best Practices

Monitor your usage

Check the X-RateLimit-Remaining header to avoid hitting limits unexpectedly.

Use bulk endpoints

When generating multiple QR codes, use the bulk endpoint to create up to 100 codes in a single request.

Cache responses

Cache generated QR codes on your end to avoid regenerating the same codes repeatedly.

Implement request queuing

Queue requests client-side and process them at a rate below your limit for smoother performance.

Avoid request bursts

Spread requests evenly over time instead of sending many at once. Bursting can trigger rate limits even if you're under the daily quota.

Need Higher Limits?

Upgrade to a higher plan for increased rate limits, or contact us for custom enterprise limits.