> ## Documentation Index
> Fetch the complete documentation index at: https://docs.suprsonic.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate Limits

> Understanding API rate limits

# Rate Limits

The SuprSonic API implements rate limiting to ensure fair usage and maintain service quality for all users. Rate limits are applied per API key and vary based on your subscription plan.

## Rate Limit Tiers

| Plan           | Requests per Minute | Requests per Hour | Burst Limit |
| -------------- | ------------------- | ----------------- | ----------- |
| **Free**       | 60                  | 1,000             | 10          |
| **Pro**        | 300                 | 10,000            | 50          |
| **Business**   | 1,200               | 50,000            | 100         |
| **Enterprise** | Custom              | Custom            | Custom      |

<Info>
  **Admin API Keys** have separate, higher rate limits for system operations.
</Info>

## Rate Limit Headers

Every API response includes rate limit headers to help you monitor your usage:

```http theme={null}
HTTP/1.1 200 OK
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 245
X-RateLimit-Reset: 1640995200
X-RateLimit-Retry-After: 3600
```

| Header                    | Description                          |
| ------------------------- | ------------------------------------ |
| `X-RateLimit-Limit`       | Maximum requests allowed per window  |
| `X-RateLimit-Remaining`   | Requests remaining in current window |
| `X-RateLimit-Reset`       | Timestamp when the rate limit resets |
| `X-RateLimit-Retry-After` | Seconds until rate limit resets      |

## Rate Limit Exceeded Response

When you exceed your rate limit, the API returns a `429 Too Many Requests` response:

```json theme={null}
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please try again later.",
    "details": {
      "limit": 300,
      "reset": 1640995200,
      "retryAfter": 3600
    }
  }
}
```

## Best Practices

### 1. Monitor Rate Limit Headers

```javascript theme={null}
async function makeApiRequest(url, options) {
  const response = await fetch(url, options);
  
  // 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(`Low rate limit: ${remaining} requests remaining`);
    console.warn(`Resets at: ${new Date(reset * 1000)}`);
  }
  
  return response;
}
```

### 2. Implement Exponential Backoff

```javascript theme={null}
async function apiRequestWithBackoff(url, options, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get('X-RateLimit-Retry-After')) || 60;
        const delay = Math.min(retryAfter * 1000, Math.pow(2, attempt) * 1000);
        
        console.log(`Rate limited. Waiting ${delay}ms before retry ${attempt}/${maxRetries}`);
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      
      return response;
      
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      const delay = Math.pow(2, attempt) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
```

### 3. Batch Requests Efficiently

```javascript theme={null}
// Good: Batch multiple items in single request
const articles = await createArticles([
  { title: "Article 1", content: "..." },
  { title: "Article 2", content: "..." },
  { title: "Article 3", content: "..." }
]);

// Avoid: Multiple individual requests
for (const articleData of articles) {
  await createArticle(articleData); // Each call counts against rate limit
}
```

### 4. Use Pagination Wisely

```javascript theme={null}
// Good: Reasonable page sizes
const articles = await getArticles({ limit: 50 }); // 1 request for 50 items

// Avoid: Too many small requests
const articles = [];
for (let page = 1; page <= 50; page++) {
  const response = await getArticles({ page, limit: 1 }); // 50 requests for 50 items
  articles.push(...response.data);
}
```

## Implementation Examples

### JavaScript Rate Limiter Class

```javascript theme={null}
class RateLimitedClient {
  constructor(apiKey, maxRequestsPerMinute = 60) {
    this.apiKey = apiKey;
    this.maxRequests = maxRequestsPerMinute;
    this.requests = [];
    this.baseUrl = 'https://www.suprsonic.com/api/v1';
  }

  async makeRequest(endpoint, options = {}) {
    await this.enforceRateLimit();
    
    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      ...options,
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        'Content-Type': 'application/json',
        ...options.headers
      }
    });

    // Track request timestamp
    this.requests.push(Date.now());

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('X-RateLimit-Retry-After')) || 60;
      console.warn(`Rate limited. Waiting ${retryAfter} seconds...`);
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      return this.makeRequest(endpoint, options); // Retry
    }

    return response;
  }

  async enforceRateLimit() {
    const now = Date.now();
    const oneMinuteAgo = now - 60000;
    
    // Remove old requests
    this.requests = this.requests.filter(time => time > oneMinuteAgo);
    
    // If at limit, wait
    if (this.requests.length >= this.maxRequests) {
      const oldestRequest = this.requests[0];
      const waitTime = 60000 - (now - oldestRequest);
      
      if (waitTime > 0) {
        console.log(`Rate limit reached. Waiting ${waitTime}ms...`);
        await new Promise(resolve => setTimeout(resolve, waitTime));
      }
    }
  }
}

// Usage
const client = new RateLimitedClient('your-api-key', 60);
const response = await client.makeRequest('/articles');
```

### Python Rate Limiter

```python theme={null}
import time
import requests
from collections import deque
from typing import Optional

class RateLimitedClient:
    def __init__(self, api_key: str, max_requests_per_minute: int = 60):
        self.api_key = api_key
        self.max_requests = max_requests_per_minute
        self.requests = deque()
        self.base_url = "https://www.suprsonic.com/api/v1"
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        })

    def _enforce_rate_limit(self):
        """Enforce rate limit before making request."""
        now = time.time()
        minute_ago = now - 60
        
        # Remove old requests
        while self.requests and self.requests[0] <= minute_ago:
            self.requests.popleft()
        
        # If at limit, wait
        if len(self.requests) >= self.max_requests:
            sleep_time = 60 - (now - self.requests[0])
            if sleep_time > 0:
                print(f"Rate limit reached. Sleeping for {sleep_time:.2f} seconds...")
                time.sleep(sleep_time)

    def make_request(self, endpoint: str, method: str = "GET", **kwargs):
        """Make a rate-limited API request."""
        self._enforce_rate_limit()
        
        url = f"{self.base_url}{endpoint}"
        response = self.session.request(method, url, **kwargs)
        
        # Track request
        self.requests.append(time.time())
        
        if response.status_code == 429:
            retry_after = int(response.headers.get('X-RateLimit-Retry-After', 60))
            print(f"Rate limited. Waiting {retry_after} seconds...")
            time.sleep(retry_after)
            return self.make_request(endpoint, method, **kwargs)  # Retry
        
        return response

# Usage
client = RateLimitedClient("your-api-key", max_requests_per_minute=60)
response = client.make_request("/articles")
```

## Advanced Strategies

### 1. Request Queuing

```javascript theme={null}
class QueuedApiClient {
  constructor(apiKey, requestsPerSecond = 1) {
    this.apiKey = apiKey;
    this.interval = 1000 / requestsPerSecond;
    this.queue = [];
    this.processing = false;
  }

  async request(endpoint, options) {
    return new Promise((resolve, reject) => {
      this.queue.push({ endpoint, options, resolve, reject });
      this.processQueue();
    });
  }

  async processQueue() {
    if (this.processing || this.queue.length === 0) return;
    
    this.processing = true;
    
    while (this.queue.length > 0) {
      const { endpoint, options, resolve, reject } = this.queue.shift();
      
      try {
        const response = await fetch(`https://www.suprsonic.com/api/v1${endpoint}`, {
          ...options,
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            ...options?.headers
          }
        });
        
        resolve(response);
      } catch (error) {
        reject(error);
      }
      
      // Wait before processing next request
      if (this.queue.length > 0) {
        await new Promise(resolve => setTimeout(resolve, this.interval));
      }
    }
    
    this.processing = false;
  }
}
```

### 2. Distributed Rate Limiting

For applications with multiple instances, consider using Redis for shared rate limiting:

```javascript theme={null}
const redis = require('redis');
const client = redis.createClient();

async function isRateLimited(apiKey, limit = 60) {
  const key = `rate_limit:${apiKey}`;
  const current = await client.incr(key);
  
  if (current === 1) {
    await client.expire(key, 60); // 1 minute window
  }
  
  return current > limit;
}

// Usage in your API client
if (await isRateLimited('your-api-key')) {
  throw new Error('Rate limit exceeded');
}
```

## Monitoring and Alerts

### Track Rate Limit Usage

```javascript theme={null}
class MonitoredApiClient {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.stats = {
      requests: 0,
      rateLimited: 0,
      lastReset: Date.now()
    };
  }

  async makeRequest(endpoint, options) {
    this.stats.requests++;
    
            const response = await fetch(`https://www.suprsonic.com/api/v1${endpoint}`, {
      ...options,
      headers: {
        'Authorization': `Bearer ${this.apiKey}`,
        ...options?.headers
      }
    });

    if (response.status === 429) {
      this.stats.rateLimited++;
      console.warn(`Rate limited! Total rate limits: ${this.stats.rateLimited}`);
    }

    // Log usage every hour
    if (Date.now() - this.stats.lastReset > 3600000) {
      console.log(`Hourly stats: ${this.stats.requests} requests, ${this.stats.rateLimited} rate limits`);
      this.stats = { requests: 0, rateLimited: 0, lastReset: Date.now() };
    }

    return response;
  }
}
```

## Enterprise Solutions

For high-volume applications, consider:

* **Dedicated API Keys**: Higher rate limits for production environments
* **Custom Rate Limits**: Tailored limits based on your usage patterns
* **Priority Support**: Faster response for rate limit adjustments
* **Multiple API Keys**: Distribute load across multiple keys with proper rotation

Contact our enterprise team to discuss custom rate limiting solutions for your specific needs.
