Rate Limits
Orbit enforces rate limits to ensure platform stability and fair usage across all customers. Limits are applied per API key at the endpoint level.
Overview
Every API response includes rate limit headers:
| Header | Description |
|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
When you exceed a rate limit, Orbit returns 429 Too Many Requests with the RATE_LIMIT_EXCEEDED error code.
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Retry after 12 seconds.",
"status": 429,
"details": {
"retry_after": 12,
"limit": 100,
"window": "60s"
}
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-03-08T12:00:00Z"
}
}
Limits by Endpoint
Messaging
| Endpoint | Starter | Growth | Enterprise |
|---|
POST /v1/messages/sms | 30/min | 300/min | 3,000/min |
POST /v1/messages/whatsapp | 30/min | 300/min | 3,000/min |
POST /v1/messages/email | 60/min | 600/min | 6,000/min |
POST /v1/messages/rcs | 30/min | 300/min | 3,000/min |
POST /v1/messages/viber | 30/min | 300/min | 3,000/min |
GET /v1/messages | 120/min | 600/min | 3,000/min |
GET /v1/messages/{id} | 120/min | 600/min | 3,000/min |
Voice
| Endpoint | Starter | Growth | Enterprise |
|---|
POST /v1/voice/calls | 10/min | 60/min | 600/min |
GET /v1/voice/calls | 120/min | 600/min | 3,000/min |
POST /v1/voice/calls/{id}/hangup | 30/min | 300/min | 3,000/min |
Agents
| Endpoint | Starter | Growth | Enterprise |
|---|
POST /v1/agents/{id}/chat | 20/min | 120/min | 1,200/min |
POST /v1/agents | 10/min | 30/min | 120/min |
GET /v1/agents | 120/min | 600/min | 3,000/min |
Numbers
| Endpoint | Starter | Growth | Enterprise |
|---|
GET /v1/numbers/available | 30/min | 120/min | 600/min |
POST /v1/numbers | 10/min | 30/min | 120/min |
GET /v1/numbers | 120/min | 600/min | 3,000/min |
| Endpoint | Starter | Growth | Enterprise |
|---|
POST /v1/contacts | 60/min | 300/min | 3,000/min |
GET /v1/contacts | 120/min | 600/min | 3,000/min |
POST /v1/campaigns | 10/min | 30/min | 120/min |
Billing & Webhooks
| Endpoint | Starter | Growth | Enterprise |
|---|
GET /v1/billing/* | 60/min | 60/min | 120/min |
POST /v1/webhooks | 10/min | 30/min | 120/min |
GET /v1/webhooks | 120/min | 600/min | 3,000/min |
Handling Rate Limits
Best Practices
- Check headers proactively. Monitor
X-RateLimit-Remaining and slow down before hitting zero.
- Implement exponential backoff. When receiving a
429, wait retry_after seconds, then retry with increasing delays.
- Queue and batch. For high-volume sends, queue messages and send in controlled batches.
- Use webhooks instead of polling. Subscribe to status webhooks rather than polling
GET /v1/messages/{id}.
Retry Example
async function sendWithRetry(params, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await orbit.messages.send(params)
} catch (error) {
if (error.status === 429 && attempt < maxRetries - 1) {
const retryAfter = error.details?.retry_after ?? Math.pow(2, attempt)
await new Promise(r => setTimeout(r, retryAfter * 1000))
continue
}
throw error
}
}
}
import time
def send_with_retry(params, max_retries=3):
for attempt in range(max_retries):
try:
return orbit.messages.send(**params)
except OrbitError as e:
if e.status == 429 and attempt < max_retries - 1:
retry_after = e.details.get("retry_after", 2 ** attempt)
time.sleep(retry_after)
continue
raise
Burst Limits
In addition to per-minute limits, Orbit enforces burst limits to prevent sudden spikes:
| Plan | Max Burst (per second) |
|---|
| Starter | 5 requests |
| Growth | 25 requests |
| Enterprise | 100 requests |
Bursts exceeding these thresholds are queued for up to 5 seconds before being rejected.
Requesting Higher Limits
Enterprise customers can request custom rate limits. Contact your account manager or reach out to support@devotel.io.
If you consistently hit rate limits, consider upgrading your plan or optimizing your integration to use webhooks and batching.