Conventions
Rate limits
Per-key request budgets, Retry-After, and backoff strategy.
The Dolores API enforces two limits per API key:
| Window | Budget |
|---|---|
| Per second | 100 requests |
| Per minute | 5,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-Afteris the recommended wait in seconds. Honour it; don't immediately retry.- The
codefield tells you which band tripped (rate_limited_per_secondvsrate_limited_per_minute).
Headers on every response
Successful responses carry one observability header:
| Header | Description |
|---|---|
Dolores-RateLimit-Remaining | Approximate floor of remaining tokens across both bands. |
When this dips, slow down before you hit the wall.
Backoff strategy
A correct client:
- Catches HTTP 429.
- Reads
Retry-After(in seconds). - Waits that long, then retries the exact same request.
- If the second attempt also 429s, doubles the wait (capped at 60s) and retries again.
- 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.