Rate Limits
Rate limits are applied per endpoint over a rolling 60-second window. Each endpoint has its own counter, so hitting the limit on one route never affects another. Exceeding a limit returns 429 Too Many Requests.
How it works
- The window is 1 minute for every endpoint.
- Limits are isolated per endpoint —
list-boardsandsend-messagecount separately. - Every response carries rate-limit headers so you can pace yourself before hitting the cap.
Response headers
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed for this endpoint per window. |
X-RateLimit-Remaining | Requests remaining in the current window. |
X-RateLimit-Reset | When the current window resets. |
Retry-After | Seconds to wait before retrying (sent on 429 only). |
Limits by category
Limits cluster into a few tiers. The exact cap depends on how heavy the operation is.
| Category | Typical limit (per minute) | Examples |
|---|---|---|
| Reads | 50 | List boards, get a row, list channels, list notifications, list bookings |
| Heavier reads | 30 | Docs tree, drive tree, all /workspace/* reads |
| Writes | 30 | Create/update/delete rows, docs, comments, folders; upload presigned URLs |
| Heavy writes | 20 | Markdown writes (row, column, doc), multipart upload start/finalize |
| Search | 60 | The cross-entity /search endpoint (docs/drive search are 50) |
| Notification mutations | 60 | Mark read/unread, delete |
| Messaging | 100 | Send channel message, send direct message |
| Export | 10 | Async table export (the most restricted endpoint) |
Representative endpoint limits
| Endpoint | Method | Limit / min |
|---|---|---|
/board/list-boards | GET | 50 |
/board/{boardId}/table/{tableId}/rows | GET | 50 |
/board/{boardId}/table/{tableId}/row | POST | 30 |
/board/{boardId}/table/{tableId}/row/{rowId}/md | POST | 20 |
/board/{boardId}/table/{tableId}/export | POST | 10 |
/docs/tree | GET | 30 |
/docs/{docId}/md | POST | 20 |
/drive/files/upload/multipart/start | POST | 20 |
/search | GET | 60 |
/notifications | GET | 50 |
/notifications/{notificationId} | PATCH / DELETE | 60 |
/workspace/info | GET | 30 |
/chat/channels | GET | 50 |
/chat/channel/{channelId}/send-message | POST | 100 |
note
These numbers are accurate at the time of writing but may change. Always read the X-RateLimit-* headers at runtime rather than hardcoding limits — and consult the API Reference for the current value on a specific endpoint.
The 429 response
When you exceed a limit, the endpoint returns:
{
"statusCode": 429,
"error": "Too Many Requests",
"message": "Too many requests, please try again later",
"retryAfter": 27
}
The Retry-After header carries the same value (in seconds) as the retryAfter body field — the time until the window resets.
Backoff guidance
- Honor
Retry-After. On a429, wait the number of seconds it specifies before retrying. - Use exponential backoff as a fallback. If no
Retry-Afteris present (for example on a5xx), back off exponentially: 1s, 2s, 4s, … - Watch
X-RateLimit-Remaining. Slow down proactively as it approaches zero instead of waiting for a429. - Spread bulk work. When iterating large lists or batch-creating rows, add a small delay between calls to stay under the per-minute cap.
- Cap retries. Give up after a few attempts and surface the error rather than retrying forever.
See Error Handling for a complete retry example.