Errors & retries
Every non-2xx response returns a JSON body with ok: false and an error string. Rate limits add retryAfterSec.
Error response shape
{
"ok": false,
"error": "Invalid or missing API key."
}Error codes
| Status | Meaning | What to do |
|---|---|---|
400 | Bad request — invalid params, payload too large, or wrong content-type. | Fix the request; do not retry. |
401 | Missing, invalid, or revoked API key. | Check Authorization header; if revoked, request a new key. |
403 | Key valid but lacks permission. | Contact support — key needs the reseller role. |
404 | Endpoint does not exist. | Check the URL. |
429 | Rate limit exceeded. | Read retryAfterSec and wait before retrying. |
500 | Server error. | Retry with exponential backoff; report if persistent. |
503 | Service temporarily unavailable. | Retry with backoff. |
Retrying safely
Retry only on 429, 500, and 503. Use exponential backoff with a small random jitter, and respect retryAfterSec if present.
JavaScript
async function requestWithRetry(url, options, maxAttempts = 3) {
let attempt = 0;
while (attempt < maxAttempts) {
const res = await fetch(url, options);
if (res.ok) return res.json();
const data = await res.json().catch(() => ({}));
if (res.status === 429 && data.retryAfterSec) {
await new Promise((r) => setTimeout(r, data.retryAfterSec * 1000));
} else if (res.status >= 500) {
await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt + Math.random() * 500));
} else {
throw new Error(data.error || `HTTP ${res.status}`);
}
attempt++;
}
throw new Error("Max retries exceeded");
}Python
import time, random, requests
def request_with_retry(url, headers, params=None, max_attempts=3):
for attempt in range(max_attempts):
r = requests.get(url, headers=headers, params=params, timeout=30)
if r.ok:
return r.json()
try:
data = r.json()
except Exception:
data = {}
if r.status_code == 429 and "retryAfterSec" in data:
time.sleep(data["retryAfterSec"])
elif r.status_code >= 500:
time.sleep(2 ** attempt + random.random() * 0.5)
else:
raise Exception(data.get("error", f"HTTP {r.status_code}"))
raise Exception("Max retries exceeded")