Skip to content

Rate limits

The BatchRouter API is rate-limited to keep the platform stable and fair across all accounts. Limits are enforced per API key and per account. When you exceed a limit, the API responds with HTTP 429 Too Many Requests; your client should back off and retry rather than hammering the endpoint.

This page explains how to detect rate limiting and how to handle it. For the current limits and any per-endpoint details, consult the interactive API reference and the response headers you receive at runtime.

Rate limits apply at two scopes:

  • Per API key — each br_live_… key is metered independently.
  • Per account — usage is also aggregated across all of an account’s keys.

Limits are enforced on request volume over a rolling window. BatchRouter is built for batch workloads, so the design intent is that you submit a small number of large batches rather than a high volume of tiny requests — a single POST /v1/batches call can carry many thousands of items, which is far more efficient than one request per item.

A few endpoints have their own dedicated, stricter limits — for example, registration endpoints are tightly throttled to deter abuse. Those constraints are documented alongside the relevant operation in the API reference.

When you exceed a limit, the API returns HTTP 429 Too Many Requests. The response may include a Retry-After header indicating how long to wait before retrying — in seconds, or as an HTTP date. Always prefer the value the server gives you over a fixed delay of your own.

The correct response to a 429 is to wait and retry with exponential backoff and jitter: increase the delay on each successive failure, and add a small random offset so that many clients retrying at once don’t synchronize into a new spike. If a Retry-After header is present, honor it as the minimum wait.

cURL doesn’t loop on its own, so back off in your shell. This retries up to five times, honoring Retry-After when present and otherwise doubling the delay:

Terminal window
url="https://api.batchrouter.com/v1/batches"
delay=1
for attempt in $(seq 1 5); do
response=$(curl -s -w "\n%{http_code}" -D /tmp/headers.txt "$url" \
-H "Authorization: Bearer $BATCHROUTER_API_KEY")
code=$(printf '%s' "$response" | tail -n1)
if [ "$code" != "429" ]; then
printf '%s\n' "$response" | sed '$d'
break
fi
retry_after=$(grep -i '^retry-after:' /tmp/headers.txt | awk '{print $2}' | tr -d '\r')
wait=${retry_after:-$delay}
echo "429 received; waiting ${wait}s before retry $attempt" >&2
sleep "$wait"
delay=$((delay * 2))
done
  • Batch, don’t spray. Put many items into one POST /v1/batches request instead of issuing one request per item. This is the single biggest factor in staying under any limit.
  • Poll on a sensible interval. When checking batch status with GET /v1/batches/{batchId}, poll periodically (for example, every few seconds for fast lanes, less often for flex) rather than in a tight loop. Prefer webhooks to learn about completion instead of aggressive polling where you can.
  • Always honor Retry-After. Treat the server’s wait hint as a hard minimum.
  • Add jitter. Randomize backoff slightly so concurrent workers don’t resynchronize into a new burst.
  • Cap your retries. After a reasonable number of attempts, surface the failure to your own error handling rather than retrying forever.