SendAfrica logoSendAfricaDocs

Errors & Response Format

Every SendAfrica response uses one envelope. Learn the shape, pagination meta, and the full error-code reference.


#Response envelope

Every response — success or failure — follows the same envelope. All requests and responses use application/json unless noted otherwise (CSV import/export and provider webhooks are the exceptions).

success
json
{
  "success": true,
  "data": { "...": "..." },
  "error": null,
  "meta": null,
  "request_id": "dfffa252-4781-43ff-8e1a-bf01a754d66a",
  "timestamp": "2026-06-11T16:24:05Z"
}
error
json
{
  "success": false,
  "data": null,
  "error": {
    "code": "invalid_credentials",
    "message": "Invalid credentials"
  },
  "request_id": "abc123",
  "timestamp": "2026-06-11T16:24:05Z"
}

Always branch on success (or the HTTP status), then read error.code — codes are stable strings designed for programmatic handling.

#Pagination

Paginated endpoints return a meta object with everything needed for page controls:

json
json
{
  "success": true,
  "data": {
    "items": ["..."],
    "total": 150,
    "page": 1,
    "per_page": 25,
    "total_pages": 6
  }
}

#Error codes

HTTPCodeMeaning
400validation_errorMissing or invalid field
400invalid_requestMalformed request body
400weak_passwordPassword outside 12–128 characters (register)
400invalid_otpOTP expired or incorrect
400invalid_phoneNot a valid Tanzania mobile number
400phone_not_setPhone OTP requested but no phone on the account
400too_many_recipientsBulk SMS exceeds 100 recipients
400unknown_providerUnrecognized OAuth provider name
401invalid_credentialsWrong email or password
401unauthorized / invalid_tokenMissing, malformed, or expired JWT
401invalid_api_key / missing_api_keyMissing or invalid API key
401invalid_refresh_tokenRefresh expired, revoked, or already rotated
401invalid_exchange_codeOAuth exchange code expired or already used
401token_revokedToken blacklisted (logged out elsewhere)
402insufficient_creditsNot enough credits to send
403email_not_verifiedEmail must be verified before this action
403account_inactiveAccount suspended or inactive
403feature_disabledFeature flag off (phone OTP, OAuth, mobile money)
404not_foundResource not found
409email_existsEmail already registered
409duplicate_contactPhone already exists in that contact list
409phone_not_verifiedMobile-money payment with unverified phone
409request_in_progressSame Idempotency-Key still being processed
429rate_limit_exceededToo many requests
500server_errorInternal server error

#Handling errors in practice

errors.py
python
from sendafrica.exceptions import (
    SendAfricaError,
    InsufficientCreditsError,
    RateLimitError,
    InvalidPhoneError,
)

try:
    client.sms.send(to="0712345678", message="Hello")
except InsufficientCreditsError:
    print("Not enough credits -- top up first")
except RateLimitError as e:
    print(f"Rate limited -- retry after {e.retry_after}s")
except InvalidPhoneError as e:
    print(f"Bad phone number: {e.message}")
except SendAfricaError as e:
    print(f"API error: {e} (status={e.status_code}, request_id={e.request_id})")

Include request_id in bug reports

Every response carries a request_id that correlates with server logs. Quote it when contacting support and it makes tracing instant.