Usage limits, response headers, and best practices for staying within quota.
Rate limits are applied per API key. If you exceed the limit, the API returns a 429 Too Many Requests response.
| Tier | Per Minute | Per Day | Per Week |
|---|---|---|---|
| Free | 10 req | 100 req | 50 conversions |
| Pro | 60 req | 10,000 req | 200 conversions |
| Team | 300 req | 100,000 req | 500 conversions |
Every API response includes rate-limit headers so you can proactively manage your usage:
| Header | Description |
|---|---|
| X-RateLimit-Limit | The maximum number of requests allowed in the current time window. |
| X-RateLimit-Remaining | The number of requests remaining in the current time window. |
| X-RateLimit-Reset | Unix timestamp (seconds) when the current window resets. |
Example response headers:
HTTP/1.1 200 OK X-RateLimit-Limit: 60 X-RateLimit-Remaining: 42 X-RateLimit-Reset: 1705312800
When you receive a 429 response, the body includes a retry_after field indicating how many seconds to wait before retrying:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please retry after 12 seconds.",
"status": 429,
"retry_after": 12
}
}X-RateLimit-Remaining header proactively to throttle your requests before hitting the limit.For production systems, implement exponential backoff with jitter to gracefully handle rate limits and transient errors:
async function requestWithBackoff(url, options, maxRetries = 5) {
let attempt = 0;
while (attempt < maxRetries) {
const res = await fetch(url, options);
if (res.ok) {
return res.json();
}
// Only retry on rate-limit or server errors
if (res.status !== 429 && res.status < 500) {
const { error } = await res.json();
throw new Error(error.message);
}
const { error } = await res.json();
// Use server-provided retry_after, or calculate backoff
const retryAfter = error.retry_after
? error.retry_after * 1000
: Math.min(1000 * Math.pow(2, attempt), 30000);
// Add jitter (0-25% of wait time)
const jitter = retryAfter * Math.random() * 0.25;
const waitMs = retryAfter + jitter;
console.log(
`Rate limited. Retrying in ${Math.round(waitMs / 1000)}s `
+ `(attempt ${attempt + 1}/${maxRetries})`
);
await new Promise(resolve => setTimeout(resolve, waitMs));
attempt++;
}
throw new Error('Max retries exceeded');
}import time
import random
import requests
def request_with_backoff(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.post(url, headers=headers)
if response.ok:
return response.json()
if response.status_code not in (429, 500, 502, 503):
error = response.json().get("error", {})
raise Exception(error.get("message", "Request failed"))
error = response.json().get("error", {})
retry_after = error.get("retry_after", min(2 ** attempt, 30))
# Add jitter
jitter = retry_after * random.uniform(0, 0.25)
wait = retry_after + jitter
print(f"Rate limited. Retrying in {wait:.1f}s "
f"(attempt {attempt + 1}/{max_retries})")
time.sleep(wait)
raise Exception("Max retries exceeded")retry_after value when provided.