rate_limited
Too many requests. Back off and retry using the Retry-After header.
HTTP 429You have hit a rate limit.
When it fires
You have exceeded the request quota for the workspace's plan. Limits are tracked separately by:
- Per-key requests per minute — protects against runaway loops.
- Per-workspace requests per month — your plan cap.
- Per-workspace AI requests per day — capped separately so a runaway agent loop does not eat your monthly quota.
The scope field on the error tells you which limit you hit, and resets_at tells you when it clears.
Response shape
Every Repull error follows the same envelope. The code is stable and safe to switch on.
{
"error": {
"code": "rate_limited",
"message": "<human-readable explanation of what went wrong>",
"docs_url": "https://repull.dev/docs/errors/rate_limited"
}
}How to fix
- Check the `Retry-After` response header — it tells you how many seconds to wait before retrying.
- Read `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` on every response so you can throttle proactively, before you hit the cap.
- Implement exponential backoff with jitter: wait `Retry-After * 2^attempt + random(0,1)s`, capped at 60 seconds.
- If you are batching, switch to a single request — the AI endpoints in particular have batch shapes that cost one quota slot for many records.
- If you are consistently bumping the cap, upgrade your plan from /dashboard/billing.
Common gotchas
- Daily AI quota is separate. If
scopecomes back asdaily_ai, you are not out of monthly requests — you are out of AI calls for today specifically. Other endpoints will still work. Retry-Afteris in seconds, not milliseconds. Doubling it accidentally is a common JS bug.- Retries against an
idempotency-keynever count against the rate limit twice — Repull dedupes before counting. Use Idempotency Keys on every retryable request. - The error code returned today is
rate_limit_exceededin some surfaces — it is being unified torate_limitedacross all endpoints. Treat both as the same signal.
Examples
curl
# A 429 response includes Retry-After
HTTP/1.1 429 Too Many Requests
Retry-After: 12
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 2026-05-02T12:34:56Z
{
"error": {
"code": "rate_limited",
"message": "You have exceeded the per-minute request quota.",
"scope": "minute",
"limit": 60,
"used": 60,
"resets_at": "2026-05-02T12:34:56Z"
}
}
# Recovery
sleep 12
curl https://api.repull.dev/v1/listings -H "Authorization: Bearer sk_test_YOUR_KEY"TypeScript
import { Repull } from '@repull/sdk'
const repull = new Repull({ apiKey: process.env.REPULL_KEY! })
async function withBackoff<T>(fn: () => Promise<T>, maxAttempts = 4): Promise<T> {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn()
} catch (err: any) {
if (err.code !== 'rate_limited' || attempt === maxAttempts - 1) throw err
const retryAfter = Number(err.headers?.['retry-after'] ?? 1)
const delayMs = Math.min(60_000, retryAfter * 1000 * Math.pow(2, attempt) + Math.random() * 1000)
await new Promise(r => setTimeout(r, delayMs))
}
}
throw new Error('unreachable')
}
const listings = await withBackoff(() => repull.listings.list())If you're an AI agent
You are sending requests faster than the workspace's plan allows. STOP and wait Retry-After seconds (from the response headers) before retrying. If you keep hitting it, batch your calls or pause the loop entirely until X-RateLimit-Reset.
Related
- Error reference — the full table of error codes
- Using Repull from AI agents — patterns for handling errors in agent loops
- Rate Limits
- Idempotency Keys
Hit an error that isn't covered? Email hello@repull.dev with the request id from the response headers.
AI