Rate Limits
The ceilings that apply to the API and to inbound webhooks, how they are counted, the headers that describe them, and how to back off.
Rate limits protect a platform shared by every workspace. A valid key is never exempt: an integration that sends a burst is slowed down before it can slow down anyone else.
The ceilings of the REST API
A request to /api/v1 meets these five ceilings in this order, and stops at the first one that refuses it:
| Policy | Limit | Window | Counted per | Checked |
|---|---|---|---|---|
api:ip | 1,000 | 1 minute, fixed | Client IP address | First, before the key is read |
api:burst | 10 | 1 second, fixed | Integration | After the key's signature is checked, before any database read |
api:token | 600 | 1 minute, fixed | Integration | After the key is verified |
api:global | 600 | 1 minute, sliding | Integration | After the key is verified |
api:global-org | 600 + 300 per active seat | 1 minute, fixed | Workspace | After the key is verified |
In practice:
- 10 requests per second per integration is the ceiling you meet first, and 600 per minute over any 60 seconds. Every key of an integration shares the same budget: a new key does not open a new one.
api:ipis wide on purpose, because an office shares one IP address. It is shared with the Kasar MCP connector called from the same address.api:global-orgcaps the whole workspace: every integration, plus the members using the Kasar MCP connector. A workspace with 10 active seats has 3,600 requests per minute in total.- No route has a ceiling of its own: listing, reading and writing records all count the same.
How requests are counted
- Every request counts, including one that is then refused: by authentication, by a later ceiling, by validation, or by the ceiling itself. Retrying in a loop while refused keeps you refused on the sliding window.
- A fixed window opens with the first request and closes after its duration; a sliding window counts the requests of the last 60 seconds, whenever they arrived.
api:ipandapi:burstare counted before Kasar reads anything from its database.
Headers on every response
Every response of the API carries the state of one ceiling, successes and errors alike:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | The limit of that ceiling |
X-RateLimit-Remaining | Requests left in its window |
X-RateLimit-Reset | Unix time, in seconds, by which the window has reset: the time of the request plus the window's duration |
X-RateLimit-Policy | Which ceiling it is: api:ip, api:burst, api:token, api:global or api:global-org |
The ceiling reported is the one that leaves this request the least room, as a share of its limit. That is usually api:burst. A request refused before its key was read (a missing key, for instance) only went through api:ip, so api:ip is reported.
The 429 response
A refused request returns 429 with the standard error envelope:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded for api:burst. Retry in 1s.",
"suggestion": "Reduce call frequency, or wait for the window to reset."
}
}HTTP/1.1 429 Too Many Requests
Retry-After: 1
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1791891001
X-RateLimit-Policy: api:burst
X-Request-Id: 6f1c2a9e-3b7d-4e05-8c4a-2d9f0b1e7a63The X-RateLimit-* headers of a 429 describe the ceiling that refused it. Retry-After is the duration of that ceiling's window, in seconds: 1 for api:burst, 60 for the per-minute ceilings. The delay is never in the body.
Backing off correctly
- Honor
Retry-After. It is never shorter than the wait you need. - Pace yourself under 10 requests per second per integration. Parallel workers sharing one integration share one budget: give them a common pacer rather than letting each fire at will.
- Watch
X-RateLimit-Remainingand slow down before reaching zero. - Add exponential backoff with jitter to automated retries: a fleet retrying on a fixed timer recreates the spike that got it refused.
- Read in pages of 100 (
limit=100) rather than record by record, and follow changes with webhooks instead of polling.
Inbound webhooks
The inbound webhook endpoints (the /api/webhooks/in/... addresses Kasar gives you for a third-party system to post to) have two ceilings of their own, separate from the REST API:
| Policy | Limit | Window | Counted per | Checked |
|---|---|---|---|---|
webhook-in:pre-auth | 600 | 1 minute, fixed | Workspace and sender IP address | First, before the token is looked up |
webhook-in:hook | 120 | 1 minute, sliding | Endpoint | Once the token is recognized |
- The pre-authentication ceiling is counted per sender IP address within a workspace: a sender that floods an endpoint, or tries tokens at random, exhausts its own budget and nobody else's.
- The per-endpoint ceiling is a sliding window: no more than 120 calls are accepted in any 60 seconds.
A refused call returns 429 with Retry-After and the X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and X-RateLimit-Policy headers of the ceiling that refused it. Its body is not the REST API envelope:
{ "error": "Too many requests", "policy": "webhook-in:hook", "retryAfterSeconds": 60 }A call refused by the per-endpoint ceiling is logged in the endpoint's activity in Kasar. Senders such as HubSpot and Zapier honor Retry-After and resend later. On inbound endpoints, the rate-limit headers are sent with the 429 only.