Errors & Rate Limits
Complete reference for error codes, HTTP status mapping, rate limit policies, and retry strategies.
HTTP Status Codes
Modern REST API uses standard HTTP status codes. The response body includes a structured error object.
| Code | Status | Meaning |
|---|---|---|
| 400 | Bad Request | Request validation failed (missing or invalid parameters) |
| 401 | Unauthorized | Authentication required or invalid API key |
| 402 | Payment Required | Insufficient wallet balance to complete the action |
| 403 | Forbidden | Authenticated, but not authorized for this resource |
| 404 | Not Found | Resource not found (e.g. activation ID does not exist) |
| 409 | Conflict | Request conflicts with current state (e.g. activation already completed) |
| 422 | Unprocessable Entity | Request is well-formed but semantically invalid |
| 429 | Too Many Requests | Rate limit exceeded — see Retry-After header |
| 500 | Internal Server Error | Unexpected server error — retry with exponential backoff |
| 503 | Service Unavailable | Upstream provider unavailable — retry later |
Error response shape (JSON)
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 27937
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 2026-05-10T00:00:00.000Z
{
"error": "rate_limit_exceeded",
"message": "Daily API limit reached. Contact support for higher tier.",
"retryAfter": 27937,
"limit": 10000,
"usage": 10000
}SMS-Activate Text Codes
SMS-Activate compatible endpoint returns plain text codes. Each code maps to an HTTP status for tooling that needs both.
| Text Code | HTTP | Meaning |
|---|---|---|
| BAD_KEY | 401 | Invalid or missing API key |
| BAD_ACTION | 400 | Action parameter missing or malformed |
| BAD_SERVICE | 400 | Service code not recognized |
| BAD_COUNTRY | 400 | Country parameter not recognized |
| BAD_STATUS | 400 | Invalid status value for setStatus |
| WRONG_ACTION | 400 | Action name not supported |
| NO_BALANCE | 402 | Insufficient wallet balance |
| NO_NUMBERS | 404 | No numbers available for this service+country combination |
| NO_ACTIVATION | 404 | Activation ID not found or not yours |
| RATE_LIMITED | 429 | Rate limit exceeded — slow down or wait for reset |
| ERROR_SQL | 500 | Internal server error — retry later |
Rate Limits
Per-API-key throttle. Multiple servers using one key share a single bucket.
Burst limits
Three concurrent throttle tiers protect against bursts and sustained abuse. Hitting any tier returns 429.
Daily Quota
Default 10,000 requests per API key per day. Resets at UTC midnight.
- Public catalog endpoints (services, countries) are exempt from daily quota
- Quota counter increments on every authenticated request, regardless of response status
- Pro tier with higher limits available — contact support
Response Headers
Every authenticated API response includes rate limit headers so clients can self-throttle proactively.
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9543
X-RateLimit-Reset: 2026-05-10T00:00:00.000Z
Retry-After: 27937Retry Strategy
How to handle transient failures without flooding the API or losing data.
Do
- • Honor Retry-After header on 429 responses
- • Use exponential backoff for 5xx errors (1s, 2s, 4s, 8s)
- • Retry up to 5 times, then surface error to the user
Don’t
- • Retry 4xx errors except 429 — they are deterministic
- • Hammer the API after 429 — wait the full Retry-After period
- • Retry POST /activations without checking idempotency
Recommended retry pattern
# Pseudocode — exponential backoff with Retry-After
attempt = 0
while attempt < 5:
response = call_api()
if response.status == 200:
break # success
if response.status == 429:
wait = response.headers.get('Retry-After', 2 ** attempt)
sleep(wait)
attempt += 1
continue
if response.status >= 500:
sleep(2 ** attempt) # exponential
attempt += 1
continue
raise APIError(response) # 4xx other than 429Idempotency
Some operations charge your wallet — retrying naively can cause double charges.
POST /activations is not idempotent
If you retry a successful POST /activations, you will create a second activation and be charged twice. On any timeout or unclear response, list activations with GET /activations to verify state before retrying.
Need more details?
The interactive API reference shows error responses for every endpoint.
