Rate limits
Per-organization rate limits, quota responses, retry behavior, and how concurrency is governed for outbound calls.
zoxaAI enforces two distinct limits: request rate (per second / minute) and call concurrency (active calls at one moment).
Request rate
Request rate is enforced per organization. Exceeding the limit returns:
HTTP/1.1 429 Too Many Requests{ "detail": "Rate limit exceeded" }Limits aren't published as exact numbers
Limits are tuned per organization based on plan and historical usage. Backoff on 429 and you'll be inside the budget — there is no per-endpoint quota header to read.
Recommended retry strategy
| Strategy | Setting |
|---|---|
| Algorithm | Exponential backoff with jitter |
| Initial delay | 1 second |
| Multiplier | 2× |
| Max delay | 30 seconds |
| Max attempts | 5 |
Don't retry tight in a loop — that'll just keep tripping the limit.
Call concurrency
Outbound calls also have a concurrency ceiling — the maximum number of calls a single organization can have active at the same time. This applies across all transports (phone + WebSocket + WebRTC).
When you exceed concurrency:
| Path | Response |
|---|---|
POST /call type=outbound | 429 with quota message |
| Campaign dispatch | Slot acquisition pauses until a call ends. No rejection — the dispatcher backpressures itself. |
Campaigns are the right tool for high-volume outbound — they manage the concurrency dance for you.
Per-call quotas
Independent of rate limiting, an organization has monthly minute / call quotas. When exhausted:
HTTP/1.1 402 Payment Required{ "detail": "Your organization has exceeded its monthly call minutes quota. Please upgrade your plan." }402 is the signal — there's no automatic recovery. The user upgrades, or the next billing period resets the counter.
Checking your current usage
GET /api/v1/wallet/dashboard/usage-summary?from=2026-06-01&to=2026-07-01Returns call counts, billed minutes, average duration, spend, and success rate for the [from, to) window. See Usage / current period.
What's NOT rate-limited
- WebSocket frames inside an open
/ws/audio/{callId}connection. Once the call is established, audio flows at media rate without REST rate-limiting. - Inbound webhook traffic from providers (Twilio/Vobiz POSTing to
/telephony/run). zoxaAI accepts every legitimate inbound call regardless of how many you're running.
Best practices
| Practice | Why |
|---|---|
| Backoff exponentially | Avoids amplifying the spike that tripped the limit. |
| Add jitter | Spreads retries across the cluster so you don't synchronize and hammer the same window. |
Watch 402 separately from 429 | 402 is a billing event, not a transient condition. Retry won't help. |
| Use campaigns for bulk outbound | Built-in concurrency management + retry config + circuit breaker. |
Monitor /wallet/dashboard/usage-summary periodically | Track spend and call volume before a balance issue lands in production. |