Skip to main content

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:
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix 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

EndpointStarterGrowthEnterprise
POST /v1/messages/sms30/min300/min3,000/min
POST /v1/messages/whatsapp30/min300/min3,000/min
POST /v1/messages/email60/min600/min6,000/min
POST /v1/messages/rcs30/min300/min3,000/min
POST /v1/messages/viber30/min300/min3,000/min
GET /v1/messages120/min600/min3,000/min
GET /v1/messages/{id}120/min600/min3,000/min

Voice

EndpointStarterGrowthEnterprise
POST /v1/voice/calls10/min60/min600/min
GET /v1/voice/calls120/min600/min3,000/min
POST /v1/voice/calls/{id}/hangup30/min300/min3,000/min

Agents

EndpointStarterGrowthEnterprise
POST /v1/agents/{id}/chat20/min120/min1,200/min
POST /v1/agents10/min30/min120/min
GET /v1/agents120/min600/min3,000/min

Numbers

EndpointStarterGrowthEnterprise
GET /v1/numbers/available30/min120/min600/min
POST /v1/numbers10/min30/min120/min
GET /v1/numbers120/min600/min3,000/min

Contacts & Campaigns

EndpointStarterGrowthEnterprise
POST /v1/contacts60/min300/min3,000/min
GET /v1/contacts120/min600/min3,000/min
POST /v1/campaigns10/min30/min120/min

Billing & Webhooks

EndpointStarterGrowthEnterprise
GET /v1/billing/*60/min60/min120/min
POST /v1/webhooks10/min30/min120/min
GET /v1/webhooks120/min600/min3,000/min

Handling Rate Limits

Best Practices

  1. Check headers proactively. Monitor X-RateLimit-Remaining and slow down before hitting zero.
  2. Implement exponential backoff. When receiving a 429, wait retry_after seconds, then retry with increasing delays.
  3. Queue and batch. For high-volume sends, queue messages and send in controlled batches.
  4. 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:
PlanMax Burst (per second)
Starter5 requests
Growth25 requests
Enterprise100 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.