Unified Messaging
When you integrate messaging into your application, you typically face a fragmented landscape: one API for SMS, another for WhatsApp, a third for RCS. Each has its own authentication flow, payload format, webhook structure, and delivery logic. Maintaining three parallel integrations means three codebases, three webhook handlers, and three sets of delivery-tracking logic.
EnableX Unified Messaging solves this by providing a single API endpoint that routes your message across SMS, WhatsApp, and RCS. You send one request. EnableX handles channel selection, payload adaptation, fallback orchestration, and unified delivery reporting — all through one integration.
Instead of building and maintaining three separate integrations, you write one API call. EnableX takes care of channel selection, message formatting, fallback logic, and delivery tracking across all channels.
Problems It Solves
| Challenge | Without Unified Messaging | With Unified Messaging |
|---|---|---|
| Channel coverage | Integrate SMS, WhatsApp, RCS separately — three codebases | One integration covers all channels |
| Fallback logic | Build and maintain your own retry/failover code | Automatic cascade handled by EnableX |
| Delivery reach | Limited by single channel coverage and availability | Maximise delivery by cascading across channels |
| Webhook handling | Three webhook handlers, three payload formats | Single unified webhook for all delivery events |
| Cost optimisation | Manual routing decisions per message | Budget-based routing selects cheapest channel first |
Channel Comparison
Each messaging channel has different strengths. Unified Messaging lets you leverage the best of all three without separate integrations:
| Capability | SMS | RCS | |
|---|---|---|---|
| Reach | Universal — every phone | 2B+ users globally | Android (Google Messages) |
| Rich content | Text only | Images, video, documents, buttons | Rich cards, carousels, suggested actions |
| Templates required | DLT (India), 10DLC (USA) | Yes — Meta approval required | No |
| Read receipts | Delivery only | Delivered + read | Delivered + read |
| Best for | OTPs, alerts, broadest reach | Rich transactional + marketing | Rich Android-native experiences |
How It Works
Unified Messaging acts as an intelligent routing layer between your application and the individual messaging channels. Here is the end-to-end flow:
Message Flow
- You send one API request — POST to
/messaging/v1/messageswith the recipient number, channel preferences, and channel-specific payloads. - EnableX evaluates channels — Based on your
preferencemode (order,budget, orpriority), EnableX determines which channel to attempt first. - Message is routed — EnableX adapts your payload to the selected channel's format and dispatches the message.
- Delivery is attempted — If the first channel succeeds, the cascade stops. If it fails (recipient unreachable on that channel), EnableX automatically falls back to the next channel in the list.
- Webhook notifications fire — You receive real-time delivery events (queued, sent, delivered, failed, channel-fallback) at your webhook URL.
Preference Modes
The preference field controls how EnableX orders the channels you provide:
| Mode | Behaviour | When to Use |
|---|---|---|
order | Channels are tried in the exact order you specify in the channels array | When you want explicit control over channel priority |
budget | Channels are re-ordered by cost — cheapest first | When minimising cost is the primary goal |
priority | Channels are re-ordered by availability and historical delivery performance | When fastest, most reliable delivery matters most |
Unified Messaging API v1.0 (released February 2026) supports the order delivery mode. The budget and priority modes will be introduced in subsequent releases.
Cascade Fallback Logic
When you list multiple channels, EnableX orchestrates delivery as a cascade:
- The first channel in the resolved order is attempted.
- If delivery is confirmed (recipient reachable, message accepted by the channel), the cascade stops.
- If the channel fails (recipient not reachable, channel unavailable, or delivery error), EnableX moves to the next channel automatically.
- This repeats until the message is delivered or all channels are exhausted.
The cascade decision is based on real-time channel capability detection — not just a timed retry. RCS capability is checked against Google's RCS lookup; WhatsApp reachability is checked via Meta's infrastructure. SMS is universally available and typically serves as the final fallback.
When sending RCS, you can include a fallback_text field in the RCS payload. If the recipient's device is not RCS-capable, EnableX automatically sends this text as an SMS — without needing a separate SMS entry in the channels array. This covers the most common RCS degradation case efficiently.
Quick Start
Get a unified message sent in three steps.
Step 1 — Get Your Credentials
In the EnableX Portal, navigate to My Projects → [Your Project] → Overview and note your App ID and App Key. These are the same credentials used across all EnableX messaging APIs.
Your project must have the messaging channels you intend to use provisioned through the EnableX operations team. SMS, WhatsApp, and RCS each require their own setup (sender IDs, WABA connection, RCS agent registration). Only provisioned channels can be included in the channels array.
Step 2 — Send Your First Unified Message
Send a message that tries WhatsApp first, then falls back to SMS:
curl -X POST https://api.enablex.io/messaging/v1/messages \
-H "Authorization: Basic BASE64(APP_ID:APP_KEY)" \
-H "Content-Type: application/json" \
-d '{
"to": "+919876543210",
"channels": ["whatsapp", "sms"],
"preference": "order",
"whatsapp": {
"type": "text",
"recipient_type": "individual",
"text": {
"body": "Your order #7821 has shipped. Track at: https://yourapp.com/track/7821"
}
},
"sms": {
"from": "ENABLEX",
"data_coding": "plain"
}
}'
Step 3 — Handle the Response
{
"code": 200,
"message": "Message accepted",
"message_id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
The response confirms acceptance. message_id is your unique identifier — use it to correlate delivery webhooks and poll for status. The actual delivery outcome arrives asynchronously via your webhook URL.
Authentication
The Unified Messaging API uses HTTP Basic Authentication. Every API request must include an Authorization header with your project credentials.
Credentials
Your credentials are available in the EnableX Portal under your project settings:
| Credential | Role |
|---|---|
APP_ID | Username in HTTP Basic authentication |
APP_KEY | Password in HTTP Basic authentication |
Authorization Header
Encode APP_ID:APP_KEY as a Base64 string and include it in the header:
POST https://api.enablex.io/messaging/v1/messages
Authorization: Basic BASE64_ENCODED_APP_ID:APP_KEY
Content-Type: application/json
The same APP_ID and APP_KEY are used across all EnableX messaging APIs — SMS, WhatsApp, RCS, and Unified Messaging. You do not need separate credentials for each channel.
API Host & Base URL
API Host
https://api.enablex.io/messaging/
Version Base URL
https://api.enablex.io/messaging/v1/
The version number (v1) isolates your integration from breaking changes in future releases. All endpoints documented below are relative to this base URL.
Primary Endpoint
https://api.enablex.io/messaging/v1/messages
This single endpoint handles both sending messages and retrieving delivery status (with GET by appending the message_id).
Send Message API
The Send Message API accepts a single POST request that combines channel preferences, delivery mode, and channel-specific payloads. EnableX routes the message across your chosen channels with automatic failover.
Endpoint
| Method | URL |
|---|---|
POST | https://api.enablex.io/messaging/v1/messages |
Headers
| Header | Value |
|---|---|
Authorization | Basic BASE64(APP_ID:APP_KEY) |
Content-Type | application/json |
Understanding the Payload Structure
Before looking at the JSON, here is what each part of the payload does:
The Unified Messaging payload has two layers: common fields that apply to every message, and channel-specific objects that define the content for each channel.
| Field | Purpose |
|---|---|
to | Recipient phone number (E.164 format). Only one number per request. |
channels | Array of channels in preferred order — determines routing sequence |
preference | Routing mode: order, budget, or priority |
whatsapp | WhatsApp-specific payload (message type, template, text, media) |
sms | SMS-specific payload (sender ID, encoding, template ID) |
rcs | RCS-specific payload (agent, message type, rich cards, suggestions) |
The Unified Messaging API accepts exactly one phone number in to. For bulk messaging, call the API once per recipient or use the individual channel APIs which support batch sends.
Basic Payload
{
"to": "+919876543210",
"channels": [
"whatsapp",
"sms",
"rcs"
],
"preference": "order",
"whatsapp": {
...
},
"sms": {
...
},
"rcs": {
...
}
}
Complete Payload Reference
| Parameter | Type | Required | Description |
|---|---|---|---|
to | String | Yes | Country-code-qualified phone number (E.164). Single recipient only. |
channels | Array | Yes | Channel order: "whatsapp", "sms", "rcs". Minimum 1, maximum 3. |
preference | String | No | order (default), budget, or priority |
whatsapp | Object | Conditional | Required if whatsapp is in channels. Uses the same payload structure as the WhatsApp Messaging API, except to is omitted (uses top-level to). |
sms | Object | Conditional | Required if sms is in channels. Uses the same payload as the SMS API, except to, recipient, type, type_details, scheduled_dt, and created_dt are excluded. |
rcs | Object | Conditional | Required if rcs is in channels. Uses the same payload as the RCS Messaging API, except phone is omitted (uses top-level to). |
country_channels | Object | No | Country-specific channel overrides. Keys are ISO2 country codes (e.g., IN, US). |
multi_channel_delivery | Boolean | No | Default: false. Set true to send across all channels simultaneously (no cascade). |
Channel-Specific Payload Details
Each channel object follows the same structure as its individual channel API, with a few exclusions to avoid duplication with the top-level fields:
SMS Object
Follows the SMS API payload. Excluded fields: to, recipient, type, type_details, scheduled_dt, created_dt. Scheduling is not available through Unified Messaging.
{
"sms": {
"from": "ENABLEX",
"data_coding": "plain",
"template_id": "12345"
}
}
WhatsApp Object
Follows the WhatsApp Messaging API payload. Excluded fields: to (uses top-level to). Supports template messages, session text, media, and interactive messages.
{
"whatsapp": {
"type": "template",
"template": {
"name": "order_shipped",
"language": "en",
"components": [
{
"type": "body",
"parameters": [
{
"type": "text",
"text": "7821"
}
]
}
]
}
}
}
RCS Object
Follows the RCS Messaging API payload. Excluded fields: phone (uses top-level to). Supports text, rich cards, carousels, and suggested actions.
{
"rcs": {
"type": "text",
"agent": "MY_RCS_AGENT",
"text": "Your order #7821 has shipped.",
"fallback_text": "Your order #7821 has shipped. Track: https://yourapp.com/track/7821",
"ttl": 60
}
}
Send Variations
The Unified Messaging API supports several send modes beyond the basic cascade.
Unified Text Message
When you want to send the same plain text content across all channels (no rich media, no templates), use the unified object instead of providing separate payloads for each channel. This is the simplest possible unified send.
Unified text works for WhatsApp and RCS session messaging (plain text, no templates or rich content). For SMS, it works only if the destination country does not require a registered template or if the text matches an approved template.
{
"to": "+919876543210",
"channels": ["whatsapp", "sms", "rcs"],
"preference": "order",
"unified": {
"body": "Your appointment is confirmed for Monday at 10:30 AM."
},
"rcs": {
"agent": "MY_RCS_AGENT"
},
"sms": {
"from": "CLINICX"
}
}
The unified.body field sets the text content for all channels. Channel-specific objects (rcs, sms) are still needed for required fields like agent name and sender ID, but you do not need to repeat the message body.
Country-Specific Channel Preferences
Different countries have different channel availability and regulatory requirements. The country_channels object lets you define per-country channel preferences that override the global channels array.
{
"to": "+919876543210",
"channels": ["whatsapp", "sms", "rcs"],
"country_channels": {
"IN": ["sms", "whatsapp"],
"US": ["rcs", "sms"]
},
"preference": "order",
"whatsapp": { ... },
"sms": { ... },
"rcs": { ... }
}
How it works: EnableX detects the country from the to phone number. If the number matches a country in country_channels, that country's channel array is used. Otherwise, the global channels array applies. The preference mode applies to both global and country-specific arrays.
Parallel Delivery (All Channels Simultaneously)
By default, Unified Messaging uses cascade delivery — try one channel, fall back to the next. If you want the message delivered across all channels at the same time (no failover, just broadcast), set multi_channel_delivery to true.
{
"to": "+919876543210",
"channels": ["whatsapp", "sms", "rcs"],
"multi_channel_delivery": true,
"whatsapp": { ... },
"sms": { ... },
"rcs": { ... }
}
When multi_channel_delivery is true, the preference mode and channel order have no effect — the message is dispatched to all listed channels simultaneously. You will receive separate delivery webhooks for each channel.
Complete Request Example
This example sends a message that tries WhatsApp first (with a template), then SMS (with sender ID), then RCS (with a rich text and fallback). The preference is order, so channels are tried in the sequence listed:
POST https://api.enablex.io/messaging/v1/messages
Authorization: Basic BASE64(APP_ID:APP_KEY)
Content-Type: application/json
{
"to": "+919876543210",
"channels": [
"whatsapp",
"sms",
"rcs"
],
"preference": "order",
"whatsapp": {
"type": "text",
"recipient_type": "individual",
"text": {
"body": "Hi there! Your verification code is 847291."
}
},
"sms": {
"from": "ENABLX",
"data_coding": "plain",
"template_id": "99999"
},
"rcs": {
"type": "text",
"agent": "MY_AGENT",
"text": "Hi there! Your verification code is 847291.",
"fallback_text": "Hi there! Your verification code is 847291.",
"ttl": 60
}
}
Success Response
{
"code": 200,
"message": "Message accepted",
"message_id": "65f1a2b3c4d5e6f7a8b9c0d1"
}
| Field | Type | Description |
|---|---|---|
code | Number | 200 indicates the message was accepted for processing |
message | String | Human-readable status — "Message accepted" |
message_id | String | Unique identifier. Use this to poll delivery status and correlate webhook events. |
A 200 response means EnableX has accepted the message for processing. Actual delivery status is reported asynchronously through webhooks or the delivery status API. Always implement webhook handling for reliable delivery tracking.
Channel Routing
Understanding how EnableX selects and routes channels is critical for designing your messaging strategy.
How Channel Selection Works
- Channel list resolved — EnableX checks if the
tonumber matches any country incountry_channels. If yes, that country's channel array is used. Otherwise, the globalchannelsarray applies. - Preference mode applied — If
preferenceisorder, the array order is preserved. Ifbudgetorpriority, EnableX re-orders channels by cost or performance. - Capability check — For the first channel in the resolved order, EnableX performs a real-time capability check:
- RCS: Checks Google's RCS capability lookup for the recipient's device
- WhatsApp: Checks recipient reachability via Meta's infrastructure
- SMS: Universally available — no capability check needed
- Dispatch or fallback — If the recipient is reachable on the selected channel, the message is dispatched. If not, EnableX moves to the next channel in the list.
Routing Examples
| Scenario | Channels | Outcome |
|---|---|---|
| Recipient has WhatsApp | ["whatsapp", "sms"] | Delivered via WhatsApp; SMS not attempted |
| Recipient does not have WhatsApp | ["whatsapp", "sms"] | WhatsApp fails → SMS fallback delivers |
| Recipient has RCS-capable device | ["rcs", "whatsapp", "sms"] | Delivered via RCS; others not attempted |
| Indian number, country override | channels: ["rcs", "sms"], country_channels.IN: ["sms"] | Only SMS attempted (country override takes effect) |
| Parallel mode | ["whatsapp", "sms"], multi_channel_delivery: true | Both WhatsApp and SMS sent simultaneously |
Delivery Status API
Poll for the current delivery status of any message using its message_id.
Endpoint
| Method | URL |
|---|---|
GET | https://api.enablex.io/messaging/v1/messages/{message_id} |
Request
GET https://api.enablex.io/messaging/v1/messages/65f1a2b3c4d5e6f7a8b9c0d1
Authorization: Basic BASE64(APP_ID:APP_KEY)
Content-Type: application/json
Response
The response includes the overall delivery status and per-channel status objects for every channel that was attempted:
{
"code": 200,
"message_id": "65f1a2b3c4d5e6f7a8b9c0d1",
"to": "+919876543210",
"channels": ["whatsapp", "sms", "rcs"],
"preference": "order",
"delivery": {
"status": "DELIVERED",
"channel": "whatsapp",
"whatsapp": {
"message_id": "wamid_abc123",
"status": "DELIVERED",
"queued": "2026-04-09T10:00:00Z",
"sent": "2026-04-09T10:00:01Z",
"delivered": "2026-04-09T10:00:03Z",
"business_phone": "+6531234567"
}
}
}
Delivery Status Values
| Status | Description |
|---|---|
PENDING | Message accepted, not yet queued on any channel |
QUEUED | Message queued for delivery on a channel |
SENT | Message sent to the channel provider |
DELIVERED | Message confirmed delivered to the recipient |
FAILED | Delivery failed on the current channel (may cascade to next) |
While the delivery status API is useful for on-demand checks, webhooks provide real-time notifications as delivery events occur. Configure a webhook URL in your project settings for production use. See Unified Messaging Webhooks for setup and payload details.
Per-Channel Status Objects
The delivery object contains a sub-object for each channel that was attempted. Each sub-object includes channel-specific fields:
| Channel | Key Fields |
|---|---|
| SMS | message_id, status, queued, sent, delivered, sender, failure_reason |
message_id, recipient_id, status, queued, sent, delivered, business_phone, conversation | |
| RCS | event_type, message_id, message_status, queued, sent, delivered, agent, failure_reason |
Error Codes
| Code | HTTP | Description |
|---|---|---|
INVALID_NUMBER | 400 | to is not a valid E.164 phone number |
SENDER_NOT_APPROVED | 403 | Sender ID not approved for the target country |
TEMPLATE_NOT_APPROVED | 403 | WhatsApp template not yet approved by Meta |
WABA_NOT_CONNECTED | 403 | WhatsApp Business Account not connected to this project |
RCS_AGENT_NOT_REGISTERED | 403 | RCS business agent not registered with Google |
INSUFFICIENT_BALANCE | 402 | Account balance too low for the requested send |
RATE_LIMIT_EXCEEDED | 429 | Request rate limit exceeded — retry with exponential backoff |
CHANNEL_UNAVAILABLE | 503 | Requested channel temporarily unavailable |
ALL_CHANNELS_FAILED | — | Webhook event — all channels in the cascade exhausted without delivery |
API Quick Reference
| Operation | Method | Endpoint |
|---|---|---|
| Send Unified Message | POST | /messaging/v1/messages |
| Get Delivery Status | GET | /messaging/v1/messages/{message_id} |
| Send SMS (direct) | POST | /sms/v1/messages |
| Send WhatsApp (direct) | POST | /whatsapp/v1/messages |
| Send RCS (direct) | POST | /rcs/v1/messages |
Best Practices
Design Your Channel Order Thoughtfully
Place the richest channel first (RCS or WhatsApp) and SMS last. Rich channels provide better user experience (read receipts, interactive elements), while SMS serves as the universal safety net. A common cascade is: ["rcs", "whatsapp", "sms"].
Always Include Fallback Text for RCS
When sending RCS rich content, include the fallback_text field. This ensures non-RCS devices receive an SMS equivalent automatically, without needing a separate SMS entry in the cascade.
Implement Webhooks for Production
The delivery status API is useful for testing and ad-hoc checks, but always configure a webhook URL for production. Webhooks provide real-time delivery updates without polling overhead.
Store the message_id
Map the message_id from the API response to your internal transaction or order ID. This is your primary key for correlating all delivery events back to the original send.
Use Country-Specific Routing for Regulated Markets
Markets like India (DLT requirements) and the US (10DLC) have channel-specific regulations. Use country_channels to route regulated markets through compliant channels while keeping the richer cascade for other regions.
Use Parallel Mode Sparingly
Parallel delivery (multi_channel_delivery: true) sends across all channels simultaneously. This maximises reach but also maximises cost. Use it only for critical alerts where delivery speed is paramount.
Release Notes
v1.0 — February 24, 2026
Initial release of the Unified Messaging API with support for SMS, WhatsApp, and RCS channels. Delivery mode: order (channels tried in the sequence provided). The budget and priority delivery modes will be introduced in subsequent releases.
What's Next
- Unified Messaging Webhooks — Webhook setup, delivery notification payloads, and handler examples
- SMS Guide — Sender IDs, DLT registration, campaign setup, delivery receipts
- WhatsApp Guide — Template management, interactive messages, media, session messaging
- RCS Guide — Rich cards, carousels, suggested actions, capability check
- Messaging Prerequisites — WABA setup, RCS agent registration, sender ID provisioning