Rate limits and governor quotas

The daily tenant quota, the per-user share, per-IP limits on public endpoints, the 429 contract, and batch and page-size ceilings.

Daily tenant quota#

Every authenticated request counts against the tenant’s apiCallsPerDay governor limit — one shared budget for all users, tokens and integrations of the tenant, reset daily. Past it, the gateway answers 429 RATE_LIMIT_EXCEEDED with a Retry-After header (see Handling 429). Current usage:

GET /api/governor-limits     # apiCallsUsed / apiCallsLimit, plus the other quotas

(Setup → Platform → Governor limits; kelta limits get.) See Governor limits.

Per-user share#

Inside the tenant window, no single member may consume more than a configured share of it (default 90 %). This bounds a runaway script or a stolen token so it cannot exhaust the whole tenant; it is not a fair-share divider. The key is the member’s email, so switching from a JWT to a PAT does not double the budget. A rejected request does not spend the tenant’s budget.

Public endpoints#

Unauthenticated paths — inbound flow webhooks, module webhooks, health — have separate per-IP, per-minute budgets keyed by path prefix. They protect the platform from bursts; they do not count against your tenant.

Metering per token#

A personal access token’s lifetime requestCount (GET /api/me/tokens) counts every authenticated call made with it, refused or not. It is a usage readout, not a limit.

Other ceilings#

LimitValue
page[size]200
POST /api/operations batch size100 by default; a deployment may raise it to at most 500
Full-text search limit100
Realtime subscriptions per socket50
Realtime connections per tenant100
Flow QUERY_RECORDS pageSize / SQL_QUERY maxRows200 default / 1000 default, 10 000 max

Handling 429#

A rate-limited request gets the standard error envelope:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 42
X-RateLimit-Limit: 69
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1792828800
{
  "errors": [
    {
      "status": "429",
      "code": "RATE_LIMIT_EXCEEDED",
      "title": "RATE_LIMIT_EXCEEDED",
      "detail": "Rate limit exceeded. Retry after 42 seconds.",
      "meta": { "requestId": "3f2b9c1e-…" }
    }
  ]
}
HeaderMeaning
Retry-Afterseconds until the window resets
X-RateLimit-Limitrequests allowed in the current window
X-RateLimit-Remaining0 on a 429; set on every allowed request too
X-RateLimit-ResetUnix time (seconds) the window resets

The per-user share and the tenant quota answer with the same body. meta.requestId is the request’s X-Correlation-ID. The CLI exits 5 and prints a hint to wait Retry-After seconds.

Honour Retry-After. Prefer fewer, larger requests: page at 200, use include instead of N+1 fetches, batch writes through /api/operations, and subscribe to realtime events instead of polling.

Edit this page on GitHub