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 |
Admin API Keys have separate, higher rate limits for system operations.
Every API response includes rate limit headers to help you monitor your usage:
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:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please try again later.",
"details": {
"limit": 300,
"reset": 1640995200,
"retryAfter": 3600
}
}
}
Best Practices
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
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
// 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
}
// 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
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
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
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:
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
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.