SendComms
API Reference

Error Handling

SendComms uses conventional HTTP response codes to indicate the success or failure of an API request. Codes in the 2xx range indicate success, codes in the 4xx range indicate client errors, and codes in the 5xx range indicate server errors.

Error Response Structure

All error responses follow a consistent structure:

ERROR RESPONSE FORMAT
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",       // Machine-readable error code
    "message": "Human-readable description",
    "details": { ... },        // Optional: additional context
    "transaction_id": "txn_..." // Optional: for tracking
  }
}

HTTP Status Codes

CodeStatusDescription
200OKRequest succeeded
201CreatedResource created successfully
400Bad RequestInvalid parameters or request format
401UnauthorizedInvalid or missing API key
402Payment RequiredInsufficient account balance
403ForbiddenAccount suspended or permission denied
404Not FoundResource not found
409ConflictRequest already in progress (idempotency)
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected server error
503Service UnavailableService temporarily unavailable

Client Error Codes

These errors indicate an issue with your request. Check the error message for how to fix it.

401UNAUTHORIZED
Invalid or missing API key
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or missing API key"
  }
}
403ACCOUNT_SUSPENDED
Your account has been suspended
{
  "success": false,
  "error": {
    "code": "ACCOUNT_SUSPENDED",
    "message": "Your account has been suspended. Please contact support."
  }
}
402INSUFFICIENT_BALANCE
Not enough balance to complete the request
{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Insufficient balance. Required: $0.0350, Available: $0.0100",
    "details": {
      "required": 0.035,
      "available": 0.01
    }
  }
}
429RATE_LIMIT_EXCEEDED
Too many requests, please slow down
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please try again in 39 seconds.",
    "limit": 5,
    "remaining": 0,
    "reset": 1766452500,
    "retryAfter": 39
  }
}
400INVALID_PHONE_NUMBER
Phone number format is invalid
{
  "success": false,
  "error": {
    "code": "INVALID_PHONE_NUMBER",
    "message": "Invalid phone number. Use E.164 format (e.g., +233540800994)"
  }
}
400INVALID_EMAIL
Email address format is invalid
{
  "success": false,
  "error": {
    "code": "INVALID_EMAIL",
    "message": "Invalid email address: notanemail"
  }
}
400MESSAGE_TOO_LONG
SMS message exceeds maximum length
{
  "success": false,
  "error": {
    "code": "MESSAGE_TOO_LONG",
    "message": "Message too long. Maximum 1600 characters allowed, got 1750",
    "details": {
      "length": 1750,
      "maxLength": 1600
    }
  }
}
400MISSING_FIELD
A required field is missing from the request
{
  "success": false,
  "error": {
    "code": "MISSING_FIELD",
    "message": "Missing required field: to"
  }
}

Service Error Codes

These errors indicate a temporary issue with the service. Most are retryable after a short delay.

StatusCodeServiceDescriptionRetryable
503SMS_SEND_FAILEDSMSFailed to send SMS messageYes
503EMAIL_SEND_FAILEDEmailFailed to send email messageYes
503DATA_PURCHASE_FAILEDDataFailed to process data bundle purchaseYes
503AIRTIME_PURCHASE_FAILEDAirtimeFailed to process airtime purchaseYes

503 Service Unavailable

When you receive a 503 error, this typically indicates a temporary issue. Wait a few seconds and retry your request. Use the idempotency_key parameter to safely retry without risk of duplicate processing.

Best Practices

1

Check the Error Code

Use the error.code field for programmatic handling rather than parsing error messages.

2

Use Idempotency Keys for Retries

Always include an idempotency_key when retrying failed requests to prevent duplicate processing.

3

Implement Exponential Backoff

For rate limit (429) and service unavailable (503) errors, implement exponential backoff starting with a 1-second delay and doubling each retry.

4

Log Transaction IDs

Always log the transaction_id from error responses. This helps support quickly identify and resolve issues.

Retry Example

Here's how to implement safe retries with idempotency:

JAVASCRIPT
async function sendSMSWithRetry(to, message, maxRetries = 3) {
  const idempotencyKey = crypto.randomUUID();
  
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch('https://api.sendcomms.com/api/v1/sms/send', {
        method: 'POST',
        headers: {
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          to,
          message,
          idempotency_key: idempotencyKey
        })
      });
      
      const data = await response.json();
      
      if (response.ok) {
        return data; // Success!
      }
      
      // Don't retry client errors (4xx except 429)
      if (response.status >= 400 && response.status < 500 && response.status !== 429) {
        throw new Error(data.error?.message || 'Request failed');
      }
      
      // Retry on 429 (rate limit) or 5xx (server errors)
      if (attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      
    } catch (error) {
      if (attempt === maxRetries) throw error;
    }
  }
}