Reference
Rate limits
Per-endpoint request limits for the Macaaw Public API and how to handle 429 responses.
Limits are counted per user over a 60-second sliding window, separately for each group of endpoints. Sandbox keys share one small limit for everything.
Limits per endpoint group#
| Endpoints | Live keys (requests / minute) |
|---|---|
| List, status and delete | 600 |
| Document details | 300 |
| Create document | 100 |
| Send, remind and void | 100 |
| Downloads | 100 |
| Create task | 120 |
| Webhook subscriptions and events | 60 |
| Signing sessions | 100 |
Sandbox keys: 10 requests per minute in total, across all endpoints.
Every endpoint#
| Endpoint | Live limit / minute |
|---|---|
GET/documents | 600 |
POST/documents | 100 |
GET/documents/{id} | 600 |
DELETE/documents/{id} | 600 |
GET/documents/{id}/details | 300 |
POST/documents/{id}/send | 100 |
POST/documents/{id}/remind | 100 |
PATCH/documents/{id}/status | 100 |
GET/documents/{id}/download | 100 |
POST/documents/{id}/session | 100 |
GET/tools | 600 |
POST/tasks | 120 |
GET/tasks/{id} | 600 |
DELETE/tasks/{id} | 600 |
GET/tasks/{id}/download | 100 |
POST/invoice-checks | 120 |
GET/invoice-checks/{id} | 600 |
GET/webhook-subscriptions | 60 |
POST/webhook-subscriptions | 60 |
GET/webhook-subscriptions/{uuid} | 60 |
PATCH/webhook-subscriptions/{uuid} | 60 |
DELETE/webhook-subscriptions/{uuid} | 60 |
POST/webhook-subscriptions/{uuid}/shared-key | 60 |
GET/webhook-events | 60 |
POST/webhook-events/{id}/resend | 60 |
Headers#
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed in the window for this endpoint group. |
X-RateLimit-Remaining | Requests left in the current window. |
Retry-After | On a 429 only: seconds to wait before trying again. |
429 Too Many Requests
{
"type": "rate_limit",
"code": "RATE_LIMITED",
"detail": "Too many requests. Please wait a moment."
}Handling 429#
Wait for Retry-After seconds, then retry. Spread bulk work out instead of sending it in bursts, and prefer webhooks to polling.
async function call(url, init, tries = 5) {
const res = await fetch(url, init);
if (res.status !== 429 || tries === 0) return res;
const wait = Number(res.headers.get('Retry-After') ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
return call(url, init, tries - 1);
}