Skip to main content
The Messages API lets you send a single message to one recipient on any channel supported by Zexa — SMS, WhatsApp, Telegram, email, or Slack. Each successful request returns a unique message ID and an initial delivery status. Use the message ID to poll for status updates, or set up a webhook to receive delivery events pushed to your server in real time.

Send a Message

POST https://api.zexa.ao/v1/messages

Request Parameters

channel
string
required
The messaging channel to use. Must be one of: sms, whatsapp, telegram, email, slack.
to
string
required
The recipient identifier. Use an E.164-formatted phone number (e.g. +244912345678) for sms, whatsapp, and telegram. Use an email address for email. Use a Slack channel ID or user ID for slack.
from
string
required
Your registered Sender ID or verified email address. Sender IDs are configured in your Zexa dashboard under Settings → Senders. Use GET /sender-ids to retrieve your registered Sender IDs programmatically.
body
string
The plain-text message content. Required unless template is provided.
subject
string
The email subject line. Applies to the email channel only.
html
string
An HTML body for email messages. When provided alongside body, the body field serves as the plain-text fallback for email clients that do not render HTML.
template
object
A WhatsApp-approved message template. Use this instead of body for WhatsApp messages that require a pre-approved template.
scheduled_at
string
An ISO 8601 UTC datetime string specifying when to send the message (e.g. 2026-07-01T09:00:00Z). Omit this field to send the message immediately.

Request Examples

curl -X POST https://api.zexa.ao/v1/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "channel": "sms",
    "to": "+244912345678",
    "from": "ZEXA",
    "body": "Your verification code is 482910. It expires in 10 minutes."
  }'

Response Fields

id
string
The unique message identifier, prefixed with msg_ (e.g. msg_a1b2c3d4). Use this ID to retrieve the message status later.
status
string
The initial delivery status of the message. See the Delivery Statuses table below.
channel
string
The channel the message was sent on.
to
string
The recipient identifier as provided in the request.
created_at
string
ISO 8601 UTC timestamp of when the message was created.
Example response (201 Created):
{
  "id": "msg_a1b2c3d4",
  "status": "queued",
  "channel": "sms",
  "to": "+244912345678",
  "created_at": "2026-06-24T10:00:00Z"
}

Error Scenarios

StatusErrorDescription
400invalid_requestMissing required fields or malformed JSON body
401unauthorizedAPI key is missing or invalid
422validation_errorto is not in E.164 format, or from is not a registered Sender ID
422insufficient_creditsAccount does not have enough credits to send the message
429rate_limit_exceededToo many requests — retry after the time indicated in Retry-After

Delivery Statuses

StatusDescription
queuedMessage has been accepted and is waiting to be dispatched to the carrier or channel
sentMessage has been dispatched to the downstream carrier or channel provider
deliveredThe carrier or channel confirmed successful delivery to the recipient’s device
failedDelivery failed after all retry attempts; check the error field for the reason
undeliverableThe destination is permanently unreachable (e.g. invalid number, deactivated account)

Get Message Status

Retrieve the current status of a message by its ID. For production workloads, prefer webhooks over polling to reduce latency and API usage.
GET https://api.zexa.ao/v1/messages/{id}
curl https://api.zexa.ao/v1/messages/msg_a1b2c3d4 \
  -H "Authorization: Bearer YOUR_API_KEY"
Example response:
{
  "id": "msg_a1b2c3d4",
  "status": "delivered",
  "channel": "sms",
  "to": "+244912345678",
  "created_at": "2026-06-24T10:00:00Z",
  "delivered_at": "2026-06-24T10:00:05Z"
}
For production applications, use webhooks to receive delivery status updates in real time rather than polling this endpoint. Polling introduces latency and counts against your rate limit.

List Sender IDs

Retrieve all Sender IDs registered on your account. The from field in a send request must match one of these values for SMS, WhatsApp, and Telegram messages.
GET https://api.zexa.ao/v1/sender-ids
curl https://api.zexa.ao/v1/sender-ids \
  -H "Authorization: Bearer YOUR_API_KEY"

Response Fields

data
array
An array of Sender ID objects registered to your account.
meta
object
Pagination metadata.
Example response:
{
  "data": [
    {
      "id": "sid_abc123",
      "name": "MYBRAND",
      "channel": "sms",
      "status": "active",
      "created_at": "2026-01-15T08:00:00Z"
    },
    {
      "id": "sid_def456",
      "name": "+244900000001",
      "channel": "whatsapp",
      "status": "active",
      "created_at": "2026-02-10T12:30:00Z"
    }
  ],
  "meta": {
    "total": 2,
    "page": 1,
    "per_page": 50
  }
}
To register a new Sender ID or manage existing ones in the dashboard, visit Sender IDs. Sender ID registration may require carrier approval and can take up to 72 hours depending on the channel and country.