Rate Limits
The Extralt API applies token-bucket rate limiting per organization and a
separate protective budget before external API-key verification. Operational
limits may vary by environment or plan and are not part of the versioned API
schema. A 429 Too Many Requests response is always authoritative.
Rate-limit response
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests; retry after the delay in the Retry-After header",
"request_id": "019..."
}
}When present, Retry-After is a number of seconds. Wait at least that long.
Otherwise, use exponential backoff with random jitter and a bounded attempt
count.
import random
import time
def request_with_backoff(method, url, *, max_attempts=4, **kwargs):
for attempt in range(max_attempts):
response = requests.request(method, url, **kwargs)
if response.status_code != 429:
return response
retry_after = response.headers.get("Retry-After")
base_delay = float(retry_after) if retry_after else 2 ** attempt
time.sleep(base_delay + random.uniform(0, 0.5))
return responseasync function requestWithBackoff(url, options = {}, maxAttempts = 4) {
let response;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
response = await fetch(url, options);
if (response.status !== 429) return response;
const retryAfter = Number(response.headers.get("Retry-After"));
const baseDelayMs = Number.isFinite(retryAfter)
? retryAfter * 1000
: 1000 * 2 ** attempt;
const jitterMs = Math.random() * 500;
await new Promise((resolve) => setTimeout(resolve, baseDelayMs + jitterMs));
}
return response;
}Reads are generally safe to retry. For create and restart operations, reuse
the same request payload and Idempotency-Key; do not generate a new key for
each retry. Keep polling intervals bounded and use Capture export instead of
rapid pagination when downloading a complete Run or Import.