# Rate limits

> Kustomer's org-wide request limits by plan, search and webhook limits, per-object update limits, rate-limit headers, and how to stay under them.

Source: https://developer.kustomer.com/docs/concepts/rate-limits

Kustomer limits how many API requests an org can make per minute, and how often a single record can be changed. Limits protect your org's performance for agents. When you exceed one, the API returns `429 Too Many Requests` until the window resets.

_Interactive simulation of the org-wide per-minute request budget. Choose a plan (Enterprise 1,000, Ultimate 2,000, or legacy Business 500 requests per minute) and a request rate. Requests drain the budget, 429 responses begin when it's empty, and it refills at the reset time shown in x-ratelimit-reset. A toggle shows a client that pauses until reset instead of retrying._

## Org-wide API limit

All API requests from your org count toward one shared budget, measured over 60 seconds. Every API key and every app user in the org draws from it, including bulk requests, paginated requests and requests made on behalf of agents.

| Plan                  | Requests per minute |
| --------------------- | ------------------- |
| Enterprise            | 1,000               |
| Ultimate              | 2,000               |
| Business (legacy)     | 500                 |
| Professional (legacy) | 300                 |

Workflows and business rules running inside Kustomer don't count against this limit.

## Other request limits

| What                                                | Limit                                                        |
| --------------------------------------------------- | ------------------------------------------------------------ |
| Search requests by machine users (API keys)         | 100 per minute                                               |
| Search requests by people using Kustomer            | Not limited                                                  |
| Requests by people using Kustomer (human app users) | 1,000 per minute                                             |
| Inbound webhooks and form hooks                     | 1,000 per minute (Enterprise) or 2,000 per minute (Ultimate) |
| Inbound webhook and form hook body size             | 400 KB                                                       |
| Outbound WhatsApp messages                          | 300 per minute per user                                      |
| Workflow executions                                 | 1,000 per 30 seconds per event type                          |

Kustomer's built-in integrations aren't subject to your org's limit. Inbound email has its own sender protection: 20 emails per hour from the same address.

## Object limits

To stop runaway loops, Kustomer also limits how often one record can change, no matter how much of your budget is left:

| What                                                                                      | Limit              |
| ----------------------------------------------------------------------------------------- | ------------------ |
| Updates to one conversation, company or message                                           | 100 per 10 minutes |
| Updates to one customer through the API                                                   | 600 per 10 minutes |
| Updates to one object by a single user                                                    | 50 per 10 minutes  |
| New drafts, messages, conversations, notes or KObjects for one customer, by a single user | 120 per minute     |

Records created with `importedAt` skip the per-customer create limit, so historical imports aren't throttled by it. They still count toward the org-wide limit.

> **Most object-limit 429s are loops:** If one record hits an object limit, look for a feedback loop: a webhook handler that updates the conversation that triggered it, or two systems syncing the same field back and forth. Compare the incoming change against what you'd write, and skip the update when nothing differs.

## Headers

Every response reports your org-wide budget:

| Header                  | Meaning                                      |
| ----------------------- | -------------------------------------------- |
| `x-ratelimit-limit`     | Requests allowed in the current window       |
| `x-ratelimit-remaining` | Requests left in the current window          |
| `x-ratelimit-reset`     | When the window resets, in UTC epoch seconds |

```http
HTTP/1.1 429 Too Many Requests
x-ratelimit-limit: 1000
x-ratelimit-remaining: 0
x-ratelimit-reset: 1761058860
```

## Handling 429s

#### Wait for the reset

On a `429`, sleep until `x-ratelimit-reset`, then retry. Add a little random jitter so parallel workers don't all retry at the same instant.

#### Slow down before you hit the limit

Watch `x-ratelimit-remaining`. When it falls below about 10% of the limit, space out requests until the reset.

#### Share the budget

If several services use the same org, give each a share (for example, 40% for the nightly sync and 20% for webhooks), and run them through a shared limiter or queue.

```ts title="Node.js"
class KustomerLimiter {
  private resetAt = 0
  private remaining = Infinity

  async request(url: string, init: RequestInit): Promise<Response> {
    if (this.remaining < 25 && Date.now() < this.resetAt) await sleep(this.resetAt - Date.now())
    const res = await fetch(url, init)
    this.remaining = Number(res.headers.get('x-ratelimit-remaining') ?? Infinity)
    this.resetAt = Number(res.headers.get('x-ratelimit-reset') ?? 0) * 1000
    if (res.status === 429) {
      await sleep(Math.max(this.resetAt - Date.now(), 1000) + Math.random() * 500)
      return this.request(url, init)
    }
    return res
  }
}

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))
```

## Using fewer requests

- **Bulk endpoints.** Create or update up to 100 records in one job. See [Bulk operations](https://developer.kustomer.com/docs/guides/bulk-operations).
- **Bigger pages.** Use the largest `pageSize` the endpoint allows.
- **`include`.** Side-load related records instead of fetching them one by one.
- **Webhooks over polling.** Let Kustomer tell you what changed. See [Outbound webhooks](https://developer.kustomer.com/docs/events/outbound-webhooks).
- **Skip no-op writes.** Compare before you update. It saves budget and avoids object limits.
- **`idsOnly` searches.** Return just the IDs when that's all you need.
