Skip to content

Rate Limiting ​

The MyWarranties API implements rate limiting to ensure fair usage and protect against abuse.

Rate Limits ​

By User Role ​

RoleRequestsTime Window
Anonymous201 minute
CUSTOMER1001 hour
SUPPLIER2001 hour
RESELLER2001 hour
ADMIN5001 hour

By Endpoint Type ​

Endpoint TypeAdditional Limit
Authentication10 per 5 minutes
File Uploads20 per hour
Webhooks1000 per hour

Response Headers ​

Every API response includes rate limit information:

http
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1709568000
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when limit resets

Rate Limit Exceeded ​

When you exceed the rate limit, the API returns:

Status: 429 Too Many Requests

Response:

json
{
  "error": "RateLimitError",
  "message": "Too many requests. Please try again in 45 seconds.",
  "code": "RATE_LIMIT_EXCEEDED",
  "details": {
    "retry_after": 45,
    "limit": 100,
    "period": "1 hour"
  }
}

Headers:

http
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1709568045

Implementation ​

Rate limiting is based on:

  • User ID (for authenticated requests)
  • IP Address (for anonymous requests)
  • Endpoint (different limits per endpoint type)

Best Practices ​

Respect Rate Limits ​

Always check response headers and respect limits:

typescript
async function makeRequest(url: string) {
  const response = await fetch(url, {
    headers: { 'Authorization': `Bearer ${token}` }
  });

  // Check rate limit headers
  const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
  const reset = parseInt(response.headers.get('X-RateLimit-Reset'));

  if (remaining < 10) {
    console.warn(`Only ${remaining} requests remaining`);
  }

  if (response.status === 429) {
    const retryAfter = parseInt(response.headers.get('Retry-After'));
    console.log(`Rate limited. Retry in ${retryAfter} seconds`);
    await sleep(retryAfter * 1000);
    return makeRequest(url); // Retry
  }

  return response.json();
}

Implement Exponential Backoff ​

typescript
async function fetchWithRetry(
  url: string,
  maxRetries: number = 3,
  baseDelay: number = 1000
) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url);

      if (response.status === 429) {
        const retryAfter = parseInt(
          response.headers.get('Retry-After') || '60'
        );
        const delay = retryAfter * 1000;

        console.log(`Rate limited. Waiting ${retryAfter}s before retry ${i + 1}/${maxRetries}`);
        await sleep(delay);
        continue;
      }

      return response;
    } catch (error) {
      if (i === maxRetries - 1) throw error;

      // Exponential backoff for other errors
      const delay = baseDelay * Math.pow(2, i);
      await sleep(delay);
    }
  }
}

Batch Requests ​

Instead of making many individual requests, batch them:

typescript
// Bad: 100 individual requests
for (const productId of productIds) {
  await fetch(`/api/products/${productId}`);
}

// Good: 1 batch request
const products = await fetch('/api/products', {
  method: 'POST',
  body: JSON.stringify({ ids: productIds })
});

Cache Responses ​

Cache API responses to reduce requests:

typescript
const cache = new Map();

async function getCachedProduct(id: number) {
  if (cache.has(id)) {
    return cache.get(id);
  }

  const product = await fetch(`/api/products/${id}`).then(r => r.json());
  cache.set(id, product);

  // Expire after 5 minutes
  setTimeout(() => cache.delete(id), 5 * 60 * 1000);

  return product;
}

Monitoring Rate Limits ​

Track Usage ​

typescript
class RateLimitTracker {
  private remaining: number = 100;
  private limit: number = 100;
  private resetAt: number = 0;

  updateFromHeaders(headers: Headers) {
    this.limit = parseInt(headers.get('X-RateLimit-Limit') || '100');
    this.remaining = parseInt(headers.get('X-RateLimit-Remaining') || '0');
    this.resetAt = parseInt(headers.get('X-RateLimit-Reset') || '0');
  }

  getPercentageRemaining(): number {
    return (this.remaining / this.limit) * 100;
  }

  getSecondsUntilReset(): number {
    return Math.max(0, this.resetAt - Math.floor(Date.now() / 1000));
  }

  shouldWait(): boolean {
    return this.remaining < 5; // Wait if less than 5 requests remaining
  }
}

Display to Users ​

typescript
function RateLimitIndicator({ tracker }: { tracker: RateLimitTracker }) {
  const percentage = tracker.getPercentageRemaining();
  const color = percentage > 50 ? 'green' : percentage > 20 ? 'yellow' : 'red';

  return (
    <div>
      <div style={{ color }}>
        API Quota: {tracker.remaining}/{tracker.limit}
      </div>
      {tracker.shouldWait() && (
        <div>
          Rate limit low. Resets in {tracker.getSecondsUntilReset()}s
        </div>
      )}
    </div>
  );
}

Increasing Limits ​

Contact support to request higher rate limits:

  • Email: support@my-warranties.nl
  • Subject: Rate Limit Increase Request
  • Include: Use case, expected request volume, account email

Webhook Rate Limits ​

Webhooks have separate, higher limits:

Webhook TypeLimit
Email Inbound1000/hour
General500/hour

Webhook rate limits are per source IP, not per user.

MyWarranties - Warranty Management System