Using the API well
Rate limits
Limits keep one integration from slowing down everyone else. They are token buckets: you can burst above the steady rate for a moment, and every response tells you how much room is left.
The limits
| Scope | Steady rate | Burst | Applies to |
|---|---|---|---|
key | 50 requests/s | 100 | Each API key. |
account | 100 requests/s, or your plan’s rate | 2 × the rate | All keys and users of one account together. |
sender-management | 20 requests/s | 40 | Registering numbers, display names and WhatsApp Business Account changes (WhatsApp meters these itself). |
campaign-create | 5 requests/s | 10 | Creating campaigns. |
The sandbox allows 10% of your plan’s account rate. Sending speed to WhatsApp is a separate matter: each number has its own throughput set by WhatsApp, and messages above it wait in the queue (queuedReason) instead of failing.
Headers on every response
RateLimit-Limit: 100
RateLimit-Remaining: 97
RateLimit-Reset: 1
RateLimit-Policy: 100;w=2;scope=key, 200;w=2;scope=accountThese numbers illustrate a 50 requests/s key and a 100 requests/s account, each with a two-second burst. They are not your allocated quota. Read your actual response headers; Sandbox quotas may be lower than Live quotas.
RateLimit-Limit, -Remaining and -Reset (seconds) describe the tightest limit for this request; RateLimit-Policy lists each limit that applied, as <burst>;w=<window seconds>;scope=<name>.
When you hit a limit
The API answers 429 with RATE_LIMITED, a Retry-After header and retryAfterSeconds in the body. Wait that long, then retry with the same Idempotency-Key. The SDKs do this automatically. To stay under the limits, spread bulk work over time, or use campaigns, which pace sending for you.
When Toutye itself is saturated the API sheds load with 503 and INTERNAL_TEMPORARY_ERROR, not a 429: no limit of yours was reached, so there are no RateLimit headers. Nothing was saved. Wait Retry-After, then retry with the same Idempotency-Key.