developer portal
Get API key →

Rate limits

1800 requests per 30 minutes and 5 bad requests per 60 seconds, per identity.

The limits

WhatLimitWindow
Requests 1800 30 minutes
Bad requests 5 60 seconds

A "bad request" is any response with status code 400 through 500. Bad requests count in both meters: as a normal request and as a bad request. So fix auth and parameter shape before you start a loop.

What it counts per

The counter runs per identity, not per IP address and not per company. An identity is the pair user|company from your Authorization header. Two different users inside the same company each have their own budget. One service user calling from multiple servers shares one budget.

For OAuth flows each user counts separately, keyed on the sub in the access token.

Throttle response

Above the limit you get HTTP 429 Too Many Requests back, with a Retry-After header telling you how many seconds you're still blocked.

http throttle.txt
HTTP/1.1 429 Too Many Requests
Retry-After: 180
Content-Type: application/json

{ "error": "rate_limited" }

How the throttle window grows

Once you hit the request limit, you're blocked for 3 minutes for each extra request you still try. That window grows until 30 minutes have passed since you hit the limit. In practice: stop trying, wait the Retry-After value, then resume at a calmer pace.

StatusDescription
429Too Many Requests
401Unauthorized (counts as a bad request)

Respect Retry-After

node respect-retry-after.ts
async function call(url: string, headers: HeadersInit): Promise<Response> {
  const res = await fetch(url, { headers });

  if (res.status === 429) {
    const seconds = parseInt(res.headers.get("retry-after") ?? "60", 10);
    await new Promise(r => setTimeout(r, seconds * 1000));
    return call(url, headers);
  }

  return res;
}
python respect-retry-after.py
import time, requests

def call(url, headers):
    res = requests.get(url, headers=headers, timeout=10)
    if res.status_code == 429:
        seconds = int(res.headers.get("Retry-After", "60"))
        time.sleep(seconds)
        return call(url, headers)
    return res

Stay under the limit

More