Error Codes

The SMS Gateway API uses standard HTTP status codes and returns structured JSON error responses to help you quickly diagnose and resolve issues.

Error Response Format

All error responses follow a consistent JSON format:

error-response.json
1{
2 "statusCode": 400,
3 "message": ["phone must be a valid phone number"],
4 "error": "Bad Request",
5 "timestamp": "2025-01-15T10:30:00.000Z",
6 "path": "/api/v1/sms/send"
7}
statusCodeThe HTTP status code of the error.
messageArray of human-readable error messages.
errorThe HTTP status text.
timestampISO 8601 timestamp when the error occurred.
pathThe API endpoint path that returned the error.

HTTP Status Codes

StatusMeaning
200
Success
400
Bad Request
401
Unauthorized
403
Forbidden
404
Not Found
409
Conflict
422
Unprocessable Entity
429
Too Many Requests
500
Internal Server Error

Common Error Scenarios

Invalid Phone Number Format

422

Phone number must be in E.164 format (e.g. +251911234567)

error.json
1{
2 "statusCode": 422,
3 "message": ["phone must be a valid E.164 phone number"],
4 "error": "Unprocessable Entity",
5 "timestamp": "2025-01-15T10:30:00.000Z",
6 "path": "/api/v1/sms/send"
7}

Insufficient Wallet Balance

402

Your wallet does not have enough funds for this operation

error.json
1{
2 "statusCode": 402,
3 "message": ["Insufficient wallet balance. Required: 0.012 ETB, Available: 0.005 ETB"],
4 "error": "Payment Required",
5 "timestamp": "2025-01-15T10:30:00.000Z",
6 "path": "/api/v1/sms/send"
7}

Expired API Key

401

The API key has passed its expiration date

error.json
1{
2 "statusCode": 401,
3 "message": ["API key has expired"],
4 "error": "Unauthorized",
5 "timestamp": "2025-01-15T10:30:00.000Z",
6 "path": "/api/v1/sms/send"
7}

Rate Limit Exceeded

429

Too many requests in the current time window

error.json
1{
2 "statusCode": 429,
3 "message": ["Rate limit exceeded. Try again in 45 seconds"],
4 "error": "Too Many Requests",
5 "timestamp": "2025-01-15T10:30:00.000Z",
6 "path": "/api/v1/sms/send"
7}

Check the Retry-After header for the recommended wait time before retrying.

Invalid OTP Code

400

The provided OTP code is incorrect or has expired

error.json
1{
2 "statusCode": 400,
3 "message": ["Invalid OTP code", "Maximum verification attempts exceeded"],
4 "error": "Bad Request",
5 "timestamp": "2025-01-15T10:35:30.000Z",
6 "path": "/api/v1/otp/verify"
7}

Validation Error (Multiple Fields)

400

Request body failed validation on multiple fields

error.json
1{
2 "statusCode": 400,
3 "message": [
4 "to must be a valid phone number",
5 "body must be between 1 and 1600 characters",
6 "from must not be empty"
7 ],
8 "error": "Bad Request",
9 "timestamp": "2025-01-15T10:30:00.000Z",
10 "path": "/api/v1/sms/send"
11}

Business Error Codes

In addition to HTTP status codes, the API uses specific business error codes for programmatic error handling:

CodeHTTP Status
INVALID_PHONE_FORMAT
422
INSUFFICIENT_BALANCE
402
API_KEY_EXPIRED
401
API_KEY_DISABLED
401
API_KEY_REVOKED
401
IP_NOT_WHITELISTED
403
RATE_LIMIT_EXCEEDED
429
OTP_EXPIRED
400
OTP_INVALID
400
OTP_MAX_ATTEMPTS
400
WEBHOOK_URL_UNREACHABLE
422
DUPLICATE_WEBHOOK
409
CAMPAIGN_INACTIVE
409
CONTACT_BLOCKED
403

Handling Errors in Code

error-handling.ts
1interface ApiError {
2 statusCode: number;
3 message: string[];
4 error: string;
5 timestamp: string;
6 path: string;
7}
8
9async function sendSms(body: unknown): Promise<Response> {
10 const response = await fetch('https://api.smsgateway.com/api/v1/sms/send', {
11 method: 'POST',
12 headers: {
13 'Authorization': 'Bearer sg_live_your_key',
14 'Content-Type': 'application/json',
15 },
16 body: JSON.stringify(body),
17 });
18
19 if (!response.ok) {
20 const error: ApiError = await response.json();
21
22 switch (error.statusCode) {
23 case 401:
24 // Handle auth errors (expired/invalid key)
25 console.error('Authentication failed:', error.message);
26 break;
27 case 402:
28 // Handle insufficient balance
29 console.error('Insufficient balance:', error.message);
30 break;
31 case 429:
32 // Handle rate limits
33 const retryAfter = response.headers.get('Retry-After');
34 console.error(`Rate limited. Retry after ${retryAfter}s`);
35 break;
36 default:
37 console.error('API error:', error.message);
38 }
39 throw error;
40 }
41
42 return response;
43}

Related Pages