Rate Limits & Backoff
The Rate Limits page lists the per-endpoint limits. This guide explains the model and how to build a client that stays under it gracefully.
The token-bucket model#
Each API token has its own bucket. A limit of “60 / minute” means the bucket holds ~60 requests and refills steadily over the window. Send requests faster than the refill rate and the bucket empties; the next request gets 429 Too Many Requests with a Retry-After header telling you how many seconds until the bucket has room again.
Because buckets are per-token, you can parallelize across tokens but not around a single token's limit. Size your concurrency to the limit of the endpoint you're hitting.
Backoff is the fallback. Every successful response also reports how much of the bucket is left in X-RateLimit-Remaining, so the cheaper move is to slow down before you empty it — see Rate Limits for the full set of headers.
Jittered exponential backoff#
On a 429, wait, then retry — but two rules matter: honor Retry-After when present, and add jitter so many clients (or many threads) don't retry in lockstep and re-collide (the “thundering herd”).
# cURL has no built-in backoff. In a shell, honor Retry-After:
url="https://api.cornect.io/api/v1/companies/search"
for attempt in 0 1 2 3 4; do
code=$(curl -s -o /tmp/out -w "%{http_code}" -X POST "$url" \
-H "Authorization: Bearer cornect_your_token_here" \
-H "Content-Type: application/json" -d '{"query":"saas"}')
[ "$code" != "429" ] && break
sleep $(( (2 ** attempt) + RANDOM % 2 ))
done
cat /tmp/outCommon mistakes#
- Retrying immediately. A retry with no delay just burns another request and stays 429.
- Ignoring
Retry-After. The server tells you exactly how long to wait — use it. - No jitter. Synchronized retries re-collide. Always randomize.
- Unbounded retries. Cap attempts and surface a clear error rather than looping forever.
- Backing off on 4xx. Only
429and5xxare worth retrying; other 4xx won't fix themselves.