For AI agents: a documentation index is available at /llms.txt. A markdown version of this page is available at /guide/api/rate-limits.md.

APIIntroduction

Rate limits

120 requests per minute and 5,000 per day per key, with headers telling you where you stand.

The Developer API enforces two limits at once. Exceeding either returns 429 Too Many Requests.

WindowLimit
Per minute120 requests
Per day5,000 requests

Both limits are counted per API key. Requests without an X-API-KEY header are counted per source IP instead — which matters when a misconfigured client starts failing authentication, because those attempts still consume quota.

#Response headers

Every response carries your current standing, so you can throttle before you get blocked rather than after:

less
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 43

When you are blocked, a third header tells you how long to wait:

makefile
Retry-After: 60

The value is in seconds. Honour it rather than guessing — retrying early just burns the daily allowance.

#Staying under the limits

  1. Batch with filters, not loops

    One tasks/list call with a filters object beats fetching every project and looping. Most list endpoints filter server-side.

  2. Cache what does not change

    The user directory and project list change rarely. Cache them for minutes, not seconds — this alone usually removes most of the traffic.

  3. Back off on 429

    Sleep for Retry-After, then retry with exponential backoff and jitter so a fleet of workers does not resynchronise into a thundering herd.

  4. Use a separate key per integration

    Limits are per key, so a nightly bulk sync on its own key cannot starve your interactive integrations.

Generate fresh signing values on every retry

A retry must carry a new X-TIMESTAMP, a new X-NONCE and a recomputed X-SIGNATURE. Replaying the original headers is rejected as a reused nonce — and if the wait exceeded five minutes, as an expired timestamp too.

#A worked backoff

js
async function callWithRetry(path, payload, attempt = 0) {
  const response = await call(path, payload); // re-signs on every invocation

  if (response.status !== 429 || attempt >= 4) return response;

  const retryAfter = Number(response.headers.get('Retry-After') ?? 60);
  // Exponential growth plus jitter, so parallel workers don't resynchronise.
  const backoff = retryAfter * 1000 * 2 ** attempt + Math.random() * 1000;

  await new Promise((resolve) => setTimeout(resolve, backoff));
  return callWithRetry(path, payload, attempt + 1);
}

#MCP traffic counts too

The MCP server authenticates with the same key, so tool calls from Claude, Cursor or Copilot draw on the same 120/minute and 5,000/day budget as your REST integrations. If an assistant is doing bulk work, give it its own key.

#Need more headroom?

The limits are configurable per deployment. If a legitimate integration needs more, contact your Orangescrum account manager with the expected request volume and pattern.