Skip to content

Rate limits

Each API key may send a set number of requests a minute, by plan. Every response says where the key stands, and a 429 says how long to wait.

Each API key may send a set number of requests a minute. The number comes from your plan. Every response tells you where the key stands, so you can slow down before you are refused, and a request over the limit answers 429 with the number of seconds to wait.

On every responseHTTP
X-RateLimit-Limit: 1500
X-RateLimit-Remaining: 1499
X-RateLimit-Reset: 1791450240
LimitFreeStarterGrowthBusiness
Requests a minute, per API key603006001,500
Objects in one batch request1050100100

A change of plan applies from the next request. The same numbers are on Billing and under Plan limits in Settings, Organisation.

How requests are counted

  • Per key. Every key has its own count. Two keys of one project have two budgets, and a live key and a test key get the same number.
  • By the clock minute. A window is a minute of the clock, from second 0 to second 59 in UTC. It is not the 60 seconds after your first request.
  • Across the whole API. One count covers every endpoint. A batch of 100 objects is one request.
  • Whatever the answer. A request that is refused with 403, 404, 422 or 429 still counts, and so does an idempotent replay. A request refused with 401 does not, because no key was recognised.

Because windows follow the clock, a burst at the end of one minute and another at the start of the next can both pass. Read X-RateLimit-Remaining in place of counting on your side.

The headers

X-RateLimit-Limitinteger

The key's requests a minute.

X-RateLimit-Remaininginteger

What is left in this window after this request. It never goes below 0.

X-RateLimit-Resetinteger

When the next window starts, in seconds since the Unix epoch.

Over the limit

429 Too Many RequestsHTTP
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 1500
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1791450240
Retry-After: 43

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded for this API key",
    "details": [],
    "request_id": "req_a58d9c4fb7ac4fcfb891295a5560a52e"
  }
}

Retry-After is the number of seconds until the next window, from 1 to 60. Wait that long and send the request again. Requests sent while you are over the limit are refused and counted, but they do not push the window back.

async function send(url, options) {
  for (;;) {
    const response = await fetch(url, options);
    if (response.status !== 429) return response;

    // Retry-After is the number of seconds until the next window.
    const seconds = Number(response.headers.get("Retry-After")) || 1;
    await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
  }
}

Batch size

POST /v1/moderations/batch takes 1 to 100 objects, and the plan can set a lower ceiling: the second row of the table above. A batch larger than the plan takes answers 403 plan_limit before anything runs. One with more than 100 objects answers 422.

Batches says when a batch answers in the same response and when it is queued.

Rate and checks are two budgets

The rate limit counts requests. Checks count what was screened. A batch of 100 objects is one request against the first and up to 100 moderations against the second, and running out of checks answers 402 quota_exceeded, not 429.

When the headers are missing

  • On a 401. The key was not recognised, so there is no count to report.
  • On a body that could not be read. A 400 invalid_json and a 413 payload_too_large are answered before the key is looked at. They are not counted.
  • When the limiter cannot be reached. A request never fails because of that. In that rare moment requests are not limited and the three headers are absent.

Next

Something missing or unclear on this page? Write to support@useinfrared.com.