Rate Limiting
Understanding and handling API rate limits to build reliable integrations.
Rate Limit Overview
Rate limits protect the platform and ensure fair usage. Limits are applied per API key and vary by endpoint and plan.
Default Limits
| Plan | Requests/Second | Requests/Day |
|---|---|---|
| Starter | 10 | 10,000 |
| Professional | 50 | 100,000 |
| Enterprise | Custom | Custom |
Endpoint-Specific Limits
| Endpoint Category | Limit | Notes |
|---|---|---|
| Read operations | 100/s | GET requests |
| Write operations | 20/s | POST, PUT, DELETE |
| Transaction signing | 5/s | Security measure |
| AI inference | 10/s | Model dependent |
Rate Limit Headers
Every response includes rate limit information:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705312800
Retry-After: 60| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests in the window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the limit resets |
Retry-After | Seconds to wait (only on 429 response) |
Handling Rate Limits
429 Too Many Requests
When you exceed rate limits, the API returns a 429 status:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Please retry after 60 seconds.",
"retryAfter": 60
}
}Exponential Backoff
Implement exponential backoff for retry logic:
async function requestWithRetry(
url: string,
options: RequestInit,
maxRetries = 3
): Promise<Response> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429) {
return response;
}
const retryAfter = response.headers.get('Retry-After');
const delay = retryAfter
? parseInt(retryAfter) * 1000
: Math.pow(2, attempt) * 1000;
await new Promise(r => setTimeout(r, delay));
}
throw new Error('Max retries exceeded');
}Best Practices
Request Batching
Batch multiple operations when possible:
// Instead of multiple requests
for (const wallet of wallets) {
await api.getWallet(wallet.id);
}
// Use batch endpoint
const wallets = await api.getWallets({ ids: walletIds });Caching
Cache responses when appropriate:
const cache = new Map();
const CACHE_TTL = 60000; // 1 minute
async function getCachedWallet(id: string) {
const cached = cache.get(id);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const wallet = await api.getWallet(id);
cache.set(id, { data: wallet, timestamp: Date.now() });
return wallet;
}Client-Side Rate Limiting
Implement client-side limits to prevent hitting server limits:
import Bottleneck from 'bottleneck';
const limiter = new Bottleneck({
minTime: 100, // 10 requests per second
maxConcurrent: 5 // Max 5 concurrent requests
});
const limitedFetch = limiter.wrap(fetch);
// All requests go through the limiter
const response = await limitedFetch('/api/wallet/list');Monitoring Usage
Track your API usage to avoid hitting limits:
- Monitor
X-RateLimit-Remainingheaders - Set up alerts when usage exceeds 80%
- Review usage patterns in the console dashboard
- Contact support to increase limits if needed