ExtraltExtralt

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 response
async 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.