> ## Documentation Index
> Fetch the complete documentation index at: https://developers.workchats.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate limits & retries

> Limits, how they're enforced, and how to back off

## Limits

| Endpoint(s) | Limit |
| - | - |
| `POST /v1/messages`, per installation | 5/s sustained, bursts of 20 |
| `POST /v1/messages`, per destination (same user, group or channel) | 1/s sustained, bursts of 5 |
| `PATCH /v1/messages/{id}`, `DELETE /v1/messages/{id}` | 60/min |
| `GET /v1/users`, `GET /v1/conversations`, `GET /v1/conversations/{conversation_id}/messages` | 20/min |
| `GET /v1/users/{id}`, `GET /v1/users/lookup` | 100/min |
| `GET /v1/auth/test`, `GET /v1/conversations/{id}`, `GET /v1/conversations/{conversation_id}/files/{id}` | 100/min |
| `POST /oauth/token`, `POST /oauth/revoke` | 20/min per App |

These are published as minimums — treat them as the ceiling to design
against, even though the actual enforcement can occasionally allow a bit
more.

## Going over

```json theme={null}
{ "ok": false, "error": { "code": "rate_limited", "message": "…" }, "request_id": "…" }
```

`429 rate_limited` comes with a `Retry-After` header, in seconds. Wait
exactly that long, then retry — don't guess your own backoff for this one,
the header already tells you the right number.

## Bursty sends

If you're delivering a burst of related events (an import, a bulk import
of leads, or similar), collapse them into fewer messages rather than
sending one per item — a single summary message
("214 new leads from import *Q4 list*") stays well under the per-second
limits that many individual posts would hit.

## Retrying failures

`429` and `5xx` are safe to retry — the request either never took effect or
your [`Idempotency-Key`](/guides/idempotency) makes a repeat harmless. `4xx`
other than `429` won't succeed on retry without changing the request; fix
the request instead.
