Error Handling
HTTP status codes, error response format, and handling strategies
Error response format
All errors return a consistent JSON structure:
{
"message": "Human-readable description",
"code": "MACHINE_READABLE_CODE",
"details": {}
}HTTP status codes
| Status | Meaning |
|---|---|
200 | Success |
400 | Bad request — invalid parameters |
401 | Unauthorized — invalid or missing token |
402 | Payment required — insufficient balance |
403 | Forbidden — insufficient permissions |
404 | Not found |
429 | Rate limit exceeded |
500 | Internal server error |
Common error codes
| Code | Cause |
|---|---|
UNAUTHORIZED | Invalid or expired API token |
ACCESS_DENIED | Token lacks permission |
INVALID_PHONE | Phone number format is incorrect |
MESSAGE_TOO_LONG | Message exceeds 1530 characters |
INSUFFICIENT_BALANCE | Wallet balance too low |
RATE_LIMIT_EXCEEDED | Too many requests |
Handling errors in code
async function sendSms(payload) {
const response = await fetch('https://sms.lamah.com/api/sms/messages', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ERSAAL_API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`${error.code}: ${error.message}`);
}
return response.json();
}import requests
def send_sms(payload):
response = requests.post(
'https://sms.lamah.com/api/sms/messages',
headers={'Authorization': f'Bearer {API_TOKEN}'},
json=payload
)
if not response.ok:
error = response.json()
raise Exception(f"{error['code']}: {error['message']}")
return response.json()Retry with exponential backoff
For 429 and 500 errors, retry with increasing delays:
async function withRetry(fn, retries = 3, delay = 1000) {
for (let i = 0; i < retries; i++) {
try {
return await fn();
} catch (err) {
if (i === retries - 1) throw err;
await new Promise(r => setTimeout(r, delay * Math.pow(2, i)));
}
}
}