Skip to Content
DocumentationRate Limits

Rate Limits

The developer API is throttled per minute, per plan.

PlanRequests per minute
Free60
Pro600
Enterprise6,000

When you hit the limit you receive 429:

{ "success": false, "error": { "code": "rate_limit_exceeded", "message": "Rate limit exceeded" } }

Use the Retry-After header when present, then back off with jitter.

Working within the budget

  • Bulk in one call. To send one message to many recipients, use POST /v1/sms/bulk (up to 1000 recipients) instead of looping. The SDKs expose this as sms.bulk(...) and cap their own client-side batches at 100 — so don’t loop in a tight for at the API limit.
  • Send many client-side? Pace it. The SDKs’ send_many / sendMany / SendMany helpers accept a rate_limit_per_sec parameter (default 10) so you can send N distinct messages safely.
  • Prefer campaigns for thousands. For very large audiences, use the Campaigns feature in the dashboard — the worker handles throttling automatically.
  • Cache what doesn’t change. GET /v1/rates is public and stable; fetch it once and reuse it.
  • Watch the budget per workload. A single bulk call at 1000 recipients uses one request, not 1000.

SDK behavior

All three SDKs retry 429 responses automatically (honoring Retry-After), so most rate-limit pressure is absorbed transparently:

  • Go: up to WithMaxRetries (default 3), backoff 500 ms → 8 s — Go
  • Python: max_retries (default 3), backoff 500 ms → 8 s — Python
  • TypeScript: maxRetries (default 2), backoff 1 s → 8 s + jitter — TypeScript

If you still see 429 after the retries are exhausted, the SDK raises its typed rate-limit error (see Error Handling).

Last updated on