documentation_url field links to the relevant section
of this page for every error code.
{
"error": {
"code": "INVALID_PHONE_NUMBER",
"message": "The provided phone number is invalid",
"field": "to",
"documentation_url": "https://smsroute.cc/errors"
}
}
HTTP Status Codes
Every API response includes an HTTP status code that indicates the
broad category of the result. Successful requests return
200 OK. Errors return one of the codes below.
| Status | Meaning | Typical Cause |
|---|---|---|
| 200 OK | Request succeeded. The response body contains the result. | Message sent, balance retrieved, etc. |
| 400 Bad Request | The request body or parameters are invalid. | Missing required field, invalid phone number format, or malformed JSON. |
| 401 Unauthorized | Missing or invalid API key. | Authorization header is missing, malformed, or the API key is revoked. |
| 402 Payment Required | Insufficient account balance. | Your USD balance is lower than the cost of the requested operation. |
| 403 Forbidden | API key lacks permission for this operation. | Attempting to access an admin endpoint with a user-level key. |
| 404 Not Found | The requested resource does not exist. | Invalid message ID, batch ID, or endpoint path. |
| 429 Too Many Requests | Rate limit exceeded. | More than 100 requests/second. Check Retry-After header. |
| 500 Internal Server Error | Gateway or server error. | Temporary internal failure. Retry with exponential backoff. |
| 503 Service Unavailable | Temporary outage. | Planned maintenance or carrier upstream issue. Retry later. |
Error Codes
The code field in the error response body provides a
machine-readable identifier for the specific problem. Use it in your
error-handling logic to branch on the failure mode.
| Code | HTTP Status | Description | Action |
|---|---|---|---|
INVALID_NUMBER |
400 | The phone number format is invalid or not supported. | Verify the number is in E.164 format (e.g. +1234567890) and belongs to a supported country.
|
INSUFFICIENT_BALANCE |
402 | Account balance is too low to send the message. | Top up your account via the dashboard. SMSRoute accepts BTC, ETH, USDT, LTC, XMR, and SOL. |
RATE_LIMIT_EXCEEDED |
429 | Too many requests sent in a short period. | Wait the number of seconds specified in the Retry-After header before sending the next
request. Default limit is 100 requests/second. |
UNAUTHORIZED |
401 | Invalid or missing API key. | Ensure the Authorization: Bearer YOUR_API_KEY header is set correctly. Generate a new key
from the dashboard if needed. |
FORBIDDEN |
403 | API key does not have permission for this operation. | Check that you are using the correct API key scope. Some endpoints require admin-level keys. |
MESSAGE_TOO_LONG |
400 | Message content exceeds maximum length. | Shorten the message. Maximum is 1600 characters. Longer messages are automatically split into multiple segments. |
INVALID_SENDER |
400 | Sender ID is invalid or not allowed. | Alphanumeric sender IDs must be 11 characters or fewer. Numeric sender IDs must be a valid phone number. |
COUNTRY_NOT_SUPPORTED |
400 | SMS delivery to this country is not supported. | Check the pricing page for the list of 149 supported countries. Contact support if your target country is missing. |
NETWORK_ERROR |
500 | Temporary network error. | Retry the request. If the error persists, check status.smsroute.cc for ongoing incidents. |
INTERNAL_ERROR |
500 | Internal server error. | Retry with exponential backoff. Contact support if the error persists beyond a few minutes. |
documentation_url field that points to the relevant section
of this page. Log it — it helps during debugging and makes
error-handling code self-documenting.
Error Response Fields
| Field | Type | Description |
|---|---|---|
error.code |
string | Machine-readable error code. Use this in conditional error-handling logic. |
error.message |
string | Human-readable description of the error. Suitable for logging and display. |
error.field |
string | The specific input field that caused the error (only present on validation errors). |
error.documentation_url |
string | URL to this error reference page for further guidance. |
Handling Errors in Production
Retry Logic
For 429 (rate limit) and 5xx (server error)
responses, implement retry logic with exponential backoff. Respect the
Retry-After header when present — it tells you exactly how
many seconds to wait.
import time
def send_sms_with_retry(payload, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.post(url, json=payload, headers=headers, timeout=10)
response.raise_for_status()
return response.json()
except requests.exceptions.Timeout:
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
continue
raise
except requests.exceptions.HTTPError as e:
if e.response.status_code == 429:
# Rate limited — wait and retry
time.sleep(60)
continue
elif e.response.status_code >= 500:
# Server error — retry
if attempt < max_retries - 1:
time.sleep(5)
continue
raise # 4xx errors are not retryable
Webhook Delivery Receipts
For asynchronous delivery status, provide a callback_url
when sending SMS. SMSRoute will POST delivery receipts to your endpoint
as messages transition through queued →
sent → delivered or failed.
Acknowledge webhooks with 200 OK to prevent retries.
Idempotency Keys
Pass an Idempotency-Key header on POST requests. If the
same key is used within 24 hours, the API returns the original response
without duplicating the operation. This lets you safely retry on network
errors without risk of double-sending.