Skip to content
KnockDevelopers

Rate limits

How many requests you can send, the rate-limit headers on every response, and how to retry after a 429.

Chat with a Developer

The Knock API limits how many requests you can send per minute. Two limits apply, and every response tells you where you stand.

Limits

LimitDefaultScope
Per account600 requests per minuteOne shared budget for all requests made with your account's API keys, across every endpoint: submits, reads and key checks.
Per IP address3,000 requests per minuteCounted per IP address and endpoint, before the API key is checked. Every client behind the same outbound IP shares it.

These are the defaults. Your account's limit can differ, so read it from the X-RateLimit-Limit header rather than hard-coding it. If you need a higher limit, ask your Knock account team.

What counts. Every authenticated request counts toward your account's limit, whatever its outcome, including 400 validation, 404 and 5xx responses. Requests rejected with 401 or 403 don't count toward your account's limit, but they still count toward the per-IP limit.

Batch to save requests. One POST can carry up to 100 people or companies and counts as a single request. Send full batches instead of one item per request.

Rate-limit headers

Successful responses carry three headers that describe your account's current window:

HeaderDescription
X-RateLimit-LimitThe maximum number of requests in the current window.
X-RateLimit-RemainingHow many requests you have left in the current window.
X-RateLimit-ResetSeconds until the current window resets.
Response headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 587
X-RateLimit-Reset: 41

The 429 response

When you go over your account's limit, the API answers 429 Too Many Requests and tells you how long to wait:

429 Too Many Requests
HTTP/1.1 429 Too Many Requests
Retry-After: 42
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 42
Content-Type: application/json; charset=utf-8

{
  "errors": ["Rate limit exceeded"],
  "code": "external-api.rate-limit.exceeded",
  "metadata": { "limit": 600, "retryAfterSeconds": 42 }
}
Header or fieldDescription
Retry-AfterSeconds to wait before sending another request.
metadata.limitYour account's limit for the window.
metadata.retryAfterSecondsSame value as Retry-After.

Going over the per-IP limit also returns 429 with a Retry-After header, but with a plain body and no code:

429 Too Many Requests (per IP)
{
  "statusCode": 429,
  "message": "ThrottlerException: Too Many Requests"
}

A 429 means nothing was processed, so retrying the same request is always safe.

Retry after a 429

Wait the number of seconds in Retry-After, then retry. If the header is missing, fall back to exponential backoff with jitter. The helpers below also retry the temporary errors that are safe to retry (see Retrying safely).

knock-fetch.mjs
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

/**
 * fetch() with retries for 429, 502 and brief 401s on any method,
 * and for other 5xx responses on GET.
 */
export async function knockFetch(url, init = {}, { maxAttempts = 5 } = {}) {
  const method = (init.method ?? 'GET').toUpperCase();

  for (let attempt = 1; ; attempt++) {
    const res = await fetch(url, {
      ...init,
      headers: { 'x-api-key': process.env.KNOCK_API_KEY, ...init.headers },
    });

    const retryable =
      res.status === 429 ||
      res.status === 502 ||
      res.status === 401 ||
      (method === 'GET' && res.status >= 500);

    if (!retryable || attempt >= maxAttempts) return res;

    const retryAfter = Number(res.headers.get('retry-after'));
    const backoff = 2 ** (attempt - 1) * 1000 + Math.random() * 1000;
    await sleep(retryAfter > 0 ? retryAfter * 1000 : backoff);
  }
}

Use it like fetch or requests:

Example
const res = await knockFetch('https://app.knock-ai.com/v1/enrichment-requests/people', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ people: [{ email: 'jane@acme.com' }] }),
});

Stay under the limit

  • Share the budget deliberately. The per-account limit is shared by every key, worker and endpoint on your account. If several services call the API, coordinate them, for example through one queue.
  • Watch X-RateLimit-Remaining. Slow down before you reach zero instead of waiting for a 429.
  • Poll with backoff. Reading results counts too. The polling recipe backs off to one read every 2 minutes per request.
  • Spread bursts. If you have thousands of records to enrich, submit them in batches of 100 at a steady pace rather than all at once.
Chat with a Developer

On this page