Rate Limits
The Convotic API enforces rate limits to ensure fair usage and platform stability. Limits are applied per API key.
Default Limits
| Scope | Limit |
|---|---|
| Per API key | 1,000 requests per minute |
Rate Limit Headers
Every API response includes headers indicating your current rate limit status:
| Header | Description |
|---|---|
X-RateLimit-Limit | The maximum number of requests allowed per minute. |
X-RateLimit-Remaining | The number of requests remaining in the current window. |
Example Response Headers
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 994
Exceeding the Limit
When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 12 seconds."
}
}
The response will also include a Retry-After header indicating how many seconds to wait before making another request:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 12
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
Best Practices
- Monitor rate limit headers. Check
X-RateLimit-Remainingin each response to understand your current usage. - Implement exponential backoff. When you receive a
429response, wait for the duration specified in theRetry-Afterheader before retrying. If no header is present, use exponential backoff starting at 1 second. - Cache responses where possible. Avoid repeated calls for data that changes infrequently, such as
/v1/infoor/v1/blocks. - Batch your work. Use query parameters like
limitto retrieve more data per request instead of making many small requests. - Spread requests evenly. Avoid bursting all requests at once. Distribute them across the rate limit window for smoother throughput.
TypeScript Example with Retry
async function fetchWithRetry(
url: string,
apiKey: string,
maxRetries = 3
): Promise<any> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, {
headers: { "X-API-Key": apiKey },
});
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") ?? "1", 10);
console.warn(`Rate limited. Retrying in ${retryAfter}s...`);
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
continue;
}
return response.json();
}
throw new Error("Max retries exceeded");
}