DoloresDocs
Conventions

Rate limits

Per-key request budgets, Retry-After, and backoff strategy.

The Dolores API enforces two limits per API key:

WindowBudget
Per second100 requests
Per minute5,000 requests

Both bands run as token buckets. Idle time refills tokens; you can burst up to the full bucket and then sustain the per-second rate.

When you hit the limit

The API returns 429 rate_limit_error:

HTTP/1.1 429 Too Many Requests
Retry-After: 1
Dolores-RateLimit-Remaining: 0
Content-Type: application/json
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limited_per_second",
    "message": "Rate limit exceeded. Retry after 1s.",
    "request_id": "req_01HXY..."
  }
}
  • Retry-After is the recommended wait in seconds. Honour it; don't immediately retry.
  • The code field tells you which band tripped (rate_limited_per_second vs rate_limited_per_minute).

Headers on every response

Successful responses carry one observability header:

HeaderDescription
Dolores-RateLimit-RemainingApproximate floor of remaining tokens across both bands.

When this dips, slow down before you hit the wall.

Backoff strategy

A correct client:

  1. Catches HTTP 429.
  2. Reads Retry-After (in seconds).
  3. Waits that long, then retries the exact same request.
  4. If the second attempt also 429s, doubles the wait (capped at 60s) and retries again.
  5. Gives up after 5–10 attempts. The user should see "rate limited; try again later" — silently retrying for minutes is worse than failing fast.
async function callWithBackoff(fn, maxAttempts = 5) {
  let attempt = 0;
  while (true) {
    const res = await fn();
    if (res.status !== 429) return res;
    if (++attempt >= maxAttempts) return res;
    const retry = parseInt(res.headers.get('retry-after') || '1', 10);
    const wait = Math.min(retry * 1000 * Math.pow(2, attempt - 1), 60000);
    await new Promise(r => setTimeout(r, wait));
  }
}

Future bands

We may add longer windows (e.g. per-hour, per-day) for fair-use enforcement on bulk-export flows. We'll add new code values (rate_limited_per_hour, etc.) and announce in the changelog before tightening anything.