OrdstageDocs

Concepts

Rate limits

Per-key request limits, the X-RateLimit headers and handling 429 answers.

Each API key may make a set number of requests per minute (a sliding one-minute window). The limit depends on the plan; it is always in the X-RateLimit-Limit header, so read it instead of hard-coding a number.

Every authenticated answer carries:

Header Meaning
X-RateLimit-Limit Requests this key may make per minute.
X-RateLimit-Remaining Requests left in the current window.
X-RateLimit-Reset Unix time (seconds) when a request is next freed.

Over the limit, the API answers 429 with code rate_limited and a Retry-After header (seconds). Refused requests don't count against the limit.

{
  "error": {
    "type": "rate_limit",
    "code": "rate_limited",
    "message": "Too many requests for this key. Wait and try again.",
    "param": null,
    "request_id": "req_4f2a9c0d1e7b3a5c6d8e9f01"
  }
}

Handling 429

async function request(url, options, attempt = 0) {
  const response = await fetch(url, options);
  if ((response.status === 429 || response.status === 503) && attempt < 5) {
    const wait = Number(response.headers.get("Retry-After") ?? 2 ** attempt);
    await new Promise((resolve) => setTimeout(resolve, (wait + Math.random()) * 1000));
    return request(url, options, attempt + 1);
  }
  return response;
}

Other limits

  • Invalid keys: more than 20 failed authentications in a minute from one address block that address for 15 minutes (429 too_many_invalid_keys, with Retry-After).
  • Limiter unavailable: if Ordstage briefly can't check limits, the API answers 503 rate_limiter_unavailable with Retry-After: 5 rather than run unlimited. Retry after the wait.
  • Request size: request bodies are limited to 10 MB (413).

To stay well inside the limits, use webhooks instead of polling, and spread bulk jobs over time.