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.
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.
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.
Workflows and business rules running inside Kustomer don't count against this limit.
Other request limits
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:
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.
Headers
Every response reports your org-wide budget:
HTTP/1.1 429 Too Many Requests
x-ratelimit-limit: 1000
x-ratelimit-remaining: 0
x-ratelimit-reset: 1761058860Handling 429s
Wait for the reset
On a
429, sleep untilx-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.
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.
- Bigger pages. Use the largest
pageSizethe 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.
- Skip no-op writes. Compare before you update. It saves budget and avoids object limits.
idsOnlysearches. Return just the IDs when that's all you need.