Skip to main content
Every authenticated request takes one token from two buckets: one for who is asking and one for the workspace. A request goes through only when both buckets have a token. Buckets refill continuously, not once a minute. A key that’s used up its 600 gets a new token every 100 ms, so a steady 10 requests a second never hits the limit, while a burst of 600 at once is also fine.
These limits are about request volume. How many calls can run at the same time is a separate limit per workspace; going over it returns 429 capacity_exceeded. See Errors.

Headers on every response

Every authenticated response tells you where you stand, using the IETF RateLimit header fields. The numbers describe whichever of your two buckets is closest to empty.

When you hit the limit

You get 429 with code rate_limited, a Retry-After header in seconds, and the same RateLimit-* headers:
Refused requests don’t take a token, so waiting Retry-After seconds and retrying always works.

Staying under the limit

  • Use webhooks instead of polling. One call.ended event replaces dozens of GET /v1/calls/{id} requests.
  • Use limit=100 when walking lists, rather than many small pages.
  • Slow down early. When RateLimit-Remaining gets low, spread requests out instead of waiting for a 429.
  • One key per integration. Each key has its own 600-a-minute bucket, and the workspace bucket is shared by all of them.
The public web chat endpoints your website widget uses have their own limits (per visitor, per widget and per IP address), separate from the buckets above.