How-to guide
Rate limits
Know how many requests your key may make, read the limit headers, and back off when you hit it.
What you'll build
A client that stays under its request limit and recovers by itself when it goes over.
Prerequisites
- A secret API key. See Authentication and API keys.
The limits
- Each API key may make 600 requests per minute by default, counted in fixed 60-second windows. Your workspace's plan or settings can set a different number for a key.
- Requests without a valid key are limited per IP address.
- Some channels add their own limits on top, such as a carrier's sending rate. Those come back as channel errors (below), not as the request limit.
Step 1: Read the headers
Every response under the limit carries:
| Header | Meaning |
|---|---|
x-ratelimit-limit | Requests this key may make per window |
x-ratelimit-remaining | Requests left in the current window |
Slow down when x-ratelimit-remaining gets close to zero.
Step 2: Handle 429
Past the limit, requests answer 429 with a retry-after header (seconds) and this body:
{ "error": "rate_limit_exceeded", "message": "Too many requests. Slow down and retry shortly.", "limit": 600, "window_seconds": 60 }Wait for retry-after, then retry. If you send messages, retry with the same idempotency key so nothing is sent twice (see Errors, retries and idempotency).
Step 3: Stay under the limit
- Receive events with webhooks or the stream instead of polling.
- When you poll, use
waitSeconGET /v1/eventsrather than a tight loop. - Spread bulk sends over time instead of sending them at once.
Test it
Test keys have the same request limits as live keys. Watch x-ratelimit-remaining drop as you make requests.
Common errors
These limits come from the channel or from test mode, not the request limit:
| Error | Status | How to fix |
|---|---|---|
rate_limited | 429 | Wait for retry-after, then retry (with the same Idempotency-Key for a send). |
provider_retry_later | 503 | Retry after retry-after, with the same Idempotency-Key. |
test_limit_reached | 429 | Try again after midnight UTC, or ask for a higher test limit. |
sms_refused | 403, 429 | For a 403, change what is sent (another number, a destination the workspace may text, consent on file, the recipient's allowed hours). For a 429, retry after the delay, or ask for bulk sending to be enabled. |