RCS Business Messaging API
The EnableX RCS Business Messaging (RBM) API lets you send rich, interactive messages to users through their native Android messaging app. Unlike SMS — which is limited to plain text — RCS supports rich cards with images and video, carousels for product browsing, and interactive suggestions that let users tap to reply, open a URL, dial a phone number, share a location, or create a calendar event.
RCS messages are delivered through the user's default messaging app on Android devices. There is no separate app to install — the experience is native and seamless. Your business appears as a verified RBM Agent with a branded identity (name, logo, description) that the user sees in the conversation thread.
Authorization header. See the Authentication section below before making any API calls.
▶ Run in Postman Collection last updated Aug 12, 2024
When to Use RCS vs. SMS vs. WhatsApp
RCS, SMS, and WhatsApp each serve different messaging scenarios. Understanding when to use each channel helps you design the right communication strategy.
| Capability | SMS | RCS | |
|---|---|---|---|
| Rich media (images, video) | No | Yes | Yes |
| Interactive buttons / suggestions | No | Yes (6 types) | Yes (buttons, lists) |
| Carousels | No | Yes (2–10 cards) | No |
| Requires separate app install | No | No (native Android) | Yes |
| Delivery receipts | Limited | Yes (SENT → DELIVERED → READ) | Yes |
| Template approval required | DLT (India) | RBM (India only) | Meta (global) |
| Fallback mechanism | Native | SMS fallback text | N/A |
fallback_text parameter in every RCS API call to ensure users on non-RCS devices still receive your message as SMS.
The RBM Agent Concept
In RCS, your business communicates through an RBM Agent — a verified identity registered with Google's RCS Business Messaging platform. The agent has a name, logo, description, and contact information that appear in the user's messaging app.
Every API call you make includes an agent parameter — this is the name of your registered RBM Agent. EnableX provisions and manages the agent registration on your behalf. You reference the agent name when sending messages, creating templates, and processing webhooks.
Base URL
All RCS API endpoints use the following base URL:
https://api.enablex.io/rcs/v1/
All API routes documented on this page are relative to this base URL. For example, the messaging endpoint is https://api.enablex.io/rcs/v1/messages.
Authentication
EnableX supports two authentication mechanisms for the RCS API. You can use either one — choose based on your architecture.
HTTP Basic Authentication
Each EnableX RCS project is assigned an APP ID and APP Key. These credentials are used for HTTP Basic Authentication:
How it works: Create a base64-encoded string of APP_ID:APP_KEY (note the colon separator) and pass it in the Authorization header.
POST https://api.enablex.io/rcs/v1/messages
Authorization: Basic base64(APP_ID:APP_KEY)
Content-Type: application/json
Bearer Token Authentication
If you prefer token-based auth, you can generate a Bearer Token that is valid for 60 minutes. During this window, use the token for any number of API calls. When it expires, generate a new one.
Step 1 — Request a token by calling the Token API with your project credentials:
POST https://api.enablex.io/rcs/v1/token
Content-Type: application/json
{
"app_id": "your-app-id",
"app_key": "your-app-key"
}
Step 2 — Receive the token with its expiry timestamp:
{
"code": 200,
"token": "eyJhbGciOiJIUz...",
"expiry": 1719212536
}
| Key | Type | Description |
|---|---|---|
token | String | Bearer token for subsequent API calls |
expiry | Number | Unix timestamp (UTC) when the token expires |
Step 3 — Use the token in the Authorization header:
POST https://api.enablex.io/rcs/v1/messages
Authorization: Bearer eyJhbGciOiJIUz...
Content-Type: application/json
expiry value and regenerate a new token before it expires. If you call any API with an expired token, you will receive error code 1002 — "Invalid/Expired Token used."
Authentication Error Responses
If authentication fails — whether due to invalid credentials or an expired token — the API returns:
{
"message": "Authentication failed",
"status": "Unauthorized",
"reason": "Invalid credentials or the account has been deactivated"
}
Core Messaging Flow
The RCS messaging lifecycle follows this pattern:
1. Business sends a message → The API accepts the request and returns a message_id.
2. RBM delivers the message → Delivery status updates (SENT, DELIVERED, READ, FAILED) are posted to your webhook.
3. User interacts → If the message includes suggestions, user taps are posted to your webhook as incoming events.
4. User replies → Free-form text, files, or location shares arrive on your webhook as incoming messages.
200 response. See RCS Webhooks for complete payload details.
Template System (India Requirement)
The RCS platform mandates that businesses in India must use a pre-approved message template to initiate conversations. Once a user responds, a 24-hour session window opens, and the business can send any message type without a template.
Outside India, there is no template requirement — you can send any message type at any time.
Template Messages vs. Session Messages
| Scenario | Message Type | API Endpoint |
|---|---|---|
| Initiating conversation (India) | Template Message | POST /rcs/v1/messages/templates |
| Initiating conversation (outside India) | Any message type | POST /rcs/v1/messages |
| Within 24-hour session window | Any message type | POST /rcs/v1/messages |
POST /rcs/v1/templates. You send a message using a template via POST /rcs/v1/messages/templates.
Template Types
Templates can be created for three content types:
| Type | Description |
|---|---|
text | Plain text message with optional suggestions |
card | Rich card with media, title, description, and suggestions |
carousel | Carousel of 2–10 rich cards |
Placeholders in Templates
Text templates can include dynamic placeholders that are replaced with actual values when the message is sent. Placeholders use square bracket syntax — for example:
Hi [name], your order [order_id] has been shipped to [location].
Variable naming rules: must start with a letter, can contain alphanumeric characters and underscores, are case-sensitive, and cannot contain spaces or special characters.
[variable] square bracket placeholders — not the {{variable}} curly brace syntax used by WhatsApp. Ensure your integration uses the correct format.
Creating a Template
Submit a template for RBM approval. Templates are typically reviewed and approved within minutes to 24 hours.
POST https://api.enablex.io/rcs/v1/templates
Authorization: Bearer {token}
Content-Type: application/json
Text Template with Placeholders
This example creates a text template named order_update with two placeholder variables:
{
"name": "order_update",
"type": "text",
"text": "Hi [name], your order [order_id] is out for delivery.",
"suggestions": [
{
"type": "reply",
"text": "Track Order",
"postback": "track_order"
}
],
"templateDetails": {
"username": "your-account-username",
"agent": "your-agent-name",
"variables": [
"name",
"order_id"
],
"category": "text"
}
}
The templateDetails object provides metadata required by RBM for the approval process:
| Key | Type | Required | Description |
|---|---|---|---|
username | String | Yes | Your account username |
agent | String | Yes | RBM Agent name |
variables | Array | Conditional | List of placeholder variable names used in the text. Required if the text contains [variable] placeholders |
category | String | Yes | Must match the type field: text, card, or carousel |
Success Response:
{
"code": 200,
"message": "Template request has been created",
"data": { }
}
Rich Card Template
To create a template with a rich card (image/video + text + suggestions):
{
"name": "product_promo",
"type": "card",
"card": {
"title": "Summer Sale",
"description": "Up to 50% off on selected items",
"url": "https://example.com/promo-banner.jpg",
"suggestions": [
{
"type": "open_url",
"text": "Shop Now",
"url": "https://example.com/sale",
"postback": "shop_summer_sale"
}
]
},
"templateDetails": {
"username": "your-account-username",
"agent": "your-agent-name",
"category": "card"
}
}
Carousel Template
To create a template with a carousel of multiple rich cards:
{
"name": "product_catalog",
"type": "carousel",
"carousel": [
{
"title": "Product A",
"description": "Premium quality widget",
"url": "https://example.com/product-a.jpg",
"suggestions": [
{
"type": "open_url",
"text": "View Details",
"url": "https://example.com/product-a",
"postback": "view_product_a"
}
]
},
{
"title": "Product B",
"description": "Best-selling gadget",
"url": "https://example.com/product-b.jpg",
"suggestions": [
{
"type": "open_url",
"text": "View Details",
"url": "https://example.com/product-b",
"postback": "view_product_b"
}
]
}
],
"templateDetails": {
"username": "your-account-username",
"agent": "your-agent-name",
"category": "carousel"
}
}
Managing Templates
List Templates
Retrieve your templates with optional filters:
GET https://api.enablex.io/rcs/v1/templates?status=approved&type=text&page_no=1&page_length=10
Authorization: Bearer {token}
| Query Parameter | Type | Description |
|---|---|---|
name | String | Filter by template name (returns single template) |
type | String | text, card, or carousel |
status | String | pending, approved, or rejected |
page_no | Number | Page number (default: 1) |
page_length | Number | Results per page (default: 10) |
Response:
{
"code": 200,
"message": "Success",
"page_no": 1,
"page_length": 10,
"total": 25,
"data": [
{ }
]
}
Update a Template
PATCH https://api.enablex.io/rcs/v1/templates/:template_name
Authorization: Bearer {token}
Content-Type: application/json
Send the complete updated template definition in the request body. The payload format is the same as the create template request.
Delete a Template
DELETE https://api.enablex.io/rcs/v1/templates/:template_name
Authorization: Bearer {token}
{
"code": 200,
"message": "Template is deleted"
}
Sending a Template Message
Once a template is approved, send it to a user with the template messaging endpoint. If the template contains placeholders, provide the variable values in the variables object.
POST https://api.enablex.io/rcs/v1/messages/templates
Authorization: Bearer {token}
Content-Type: application/json
{
"type": "template",
"phone": "+919876543210",
"agent": "your-agent-name",
"template": {
"name": "order_update",
"variables": {
"name": "Rahul",
"order_id": "ORD-78432"
}
},
"fallback_text": "Hi Rahul, your order ORD-78432 is out for delivery.",
"ttl": 3600
}
The top-level fields used in every template message:
| Key | Type | Required | Description |
|---|---|---|---|
type | String | Yes | Must be "template" |
phone | String | Yes | Recipient phone with country code (e.g., +919876543210) |
agent | String | Yes | Your RBM Agent name |
template | Object | Yes | Contains name (template name) and optional variables object |
fallback_text | String | Optional | SMS fallback if RCS is unavailable |
ttl | Number | Optional | Time-to-live in seconds. Cannot be used with expire_time |
expire_time | String | Optional | Expiry timestamp (YYYY-MM-DD HH:MM:SS UTC). Cannot be used with ttl |
Success Response:
{
"code": 200,
"message": "Message request has been created",
"message_id": "msg_abc123def456"
}
The message_id is used to track delivery status updates received on your webhook.
Session Messages (Without Template)
When you are within a 24-hour session window (user has responded), or when operating outside India where templates are not mandatory, you can send messages directly without a template. All session messages use a single endpoint with different type values.
POST https://api.enablex.io/rcs/v1/messages
Authorization: Bearer {token}
Content-Type: application/json
The type field determines the content type:
| Type Value | Description | Key Content Fields |
|---|---|---|
text | Plain text message | text, suggestions |
card | Rich card with media | card object |
carousel | Carousel of 2–10 rich cards | carousel array |
Sending a Text Message
A text message can contain up to 2,500 characters and optionally include interactive suggestions.
{
"type": "text",
"phone": "+919876543210",
"agent": "your-agent-name",
"text": "Hi Rahul! Your appointment is confirmed for tomorrow at 10:00 AM.",
"suggestions": [
{
"type": "reply",
"text": "Confirm",
"postback": "appointment_confirmed"
},
{
"type": "reply",
"text": "Reschedule",
"postback": "appointment_reschedule"
}
],
"fallback_text": "Your appointment is confirmed for tomorrow at 10:00 AM."
}
| Key | Type | Required | Description |
|---|---|---|---|
type | String | Yes | Use "text" |
text | String | Yes | Message text (max 2,500 characters) |
suggestions | Array | No | Array of suggestion objects (max 4 per message) |
Sending a Rich Card
A rich card combines media (image or video), text, and interactive suggestions into a single visually rich message. This is ideal for product showcases, promotional content, or any message that benefits from visual context.
{
"type": "card",
"phone": "+919876543210",
"agent": "your-agent-name",
"card": {
"title": "Premium Wireless Headphones",
"description": "Noise-cancelling, 30-hour battery life. Now $79.99",
"url": "https://example.com/headphones.jpg",
"thumbnail_url": "https://example.com/headphones-thumb.jpg",
"suggestions": [
{
"type": "open_url",
"text": "Buy Now",
"url": "https://example.com/headphones",
"postback": "buy_headphones"
},
{
"type": "reply",
"text": "More Info",
"postback": "info_headphones"
}
]
},
"fallback_text": "Premium Wireless Headphones - $79.99. Visit https://example.com/headphones"
}
The card object fields:
| Key | Type | Required | Description |
|---|---|---|---|
title | String | Yes | Card title text |
description | String | No | Card description text |
url | String | Conditional | Public HTTPS URL for the media file. Cannot be used with id |
id | String | Conditional | Pre-uploaded file ID. Cannot be used with url |
thumbnail_url | String | No | HTTPS URL for thumbnail image. Cannot be used with thumbnail_id |
thumbnail_id | String | No | Pre-uploaded thumbnail file ID. Cannot be used with thumbnail_url |
suggestions | Array | No | Up to 4 suggestion objects per card |
thumbnail_url for video content. This gives users a preview image before the video loads. See RCS Rich Media for full media specifications, card heights, and orientation details.
Sending a Carousel
A carousel lets you present multiple options as a horizontally scrollable set of rich cards. Users can swipe through the cards and interact with each one individually. Carousels are ideal for product catalogs, plan comparisons, or multi-option menus.
{
"type": "carousel",
"phone": "+919876543210",
"agent": "your-agent-name",
"carousel": [
{
"title": "Basic Plan",
"description": "$9.99/mo — 10 GB storage",
"url": "https://example.com/plan-basic.jpg",
"suggestions": [
{
"type": "open_url",
"text": "Select Plan",
"url": "https://example.com/plans/basic",
"postback": "select_basic"
}
]
},
{
"title": "Pro Plan",
"description": "$19.99/mo — 100 GB storage",
"url": "https://example.com/plan-pro.jpg",
"suggestions": [
{
"type": "open_url",
"text": "Select Plan",
"url": "https://example.com/plans/pro",
"postback": "select_pro"
}
]
},
{
"title": "Enterprise Plan",
"description": "Custom pricing — Unlimited storage",
"url": "https://example.com/plan-enterprise.jpg",
"suggestions": [
{
"type": "reply",
"text": "Contact Sales",
"postback": "contact_sales"
}
]
}
],
"fallback_text": "Check out our plans at https://example.com/plans"
}
| Key | Type | Required | Description |
|---|---|---|---|
type | String | Yes | Use "carousel" |
carousel | Array | Yes | Array of 2–10 rich card objects (same structure as the card object above) |
Interactive Suggestions
Suggestions are interactive buttons that appear below a message or within a rich card. They allow users to respond with a single tap rather than typing a free-form reply. Each message or card can have up to 4 suggestions.
There are two categories of suggestions, and they cannot be mixed on a single card:
| Category | What It Does | Types |
|---|---|---|
| Suggested Replies | Sends a predefined text/postback value back to the business | reply |
| Suggested Actions | Triggers a native device action (open URL, dial, view map, etc.) | open_url, dial, view_location, share_location, create_calendar_event |
Suggested Reply
When a user taps a suggested reply, the app sends the postback data back to your webhook. Use this for quick response options like "Yes/No", "Confirm/Cancel", or menu selections.
{
"type": "reply",
"text": "Confirm Booking",
"postback": "booking_confirmed_12345"
}
Open URL
Opens the specified URL in the user's browser or the default app registered for that URL scheme.
{
"type": "open_url",
"text": "View Invoice",
"url": "https://example.com/invoices/INV-789",
"postback": "view_invoice_789"
}
Dial a Phone Number
Opens the phone dialer with the specified number pre-filled. The phone number must include a leading +, country code, and area code with no separators.
{
"type": "dial",
"text": "Call Support",
"phone": "+18005551234",
"postback": "call_support"
}
View a Location
Opens the default map application with a pin at the specified coordinates.
{
"type": "view_location",
"text": "See on Map",
"latitude": "28.4595",
"longitude": "77.0266",
"label": "EnableX Office, Gurugram",
"fallback": "https://maps.google.com/?q=28.4595,77.0266",
"postback": "view_office_location"
}
Share Location
Prompts the user to share a location (not necessarily their current location). The shared coordinates are posted to your webhook.
{
"type": "share_location",
"text": "Share Delivery Address",
"postback": "share_delivery_location"
}
Create Calendar Event
Opens the user's calendar app with a pre-filled event.
{
"type": "create_calendar_event",
"text": "Add to Calendar",
"title": "Doctor Appointment",
"description": "Annual health checkup at City Hospital",
"start_time": "2025-03-15T10:00:00Z",
"end_time": "2025-03-15T11:00:00Z",
"fallback": "https://calendar.google.com/calendar/event?action=TEMPLATE",
"postback": "calendar_appointment_added"
}
For the complete field reference for each suggestion type, see RCS Rich Media — Suggestions Reference.
Utility APIs
Revoke a Sent Message
If a message is still queued (not yet delivered), you can revoke it. RBM keeps undelivered messages in queue for up to 30 days unless you specified a ttl or expire_time.
DELETE https://api.enablex.io/rcs/v1/messages/revoke/{message_id}
Authorization: Bearer {token}
200 OK response confirms the revocation request was received — it does not guarantee the message was revoked. If revocation succeeds, the message is deleted from the user's queue. If it was already delivered, the revocation has no effect.
Mark an Incoming Message as Read
Notify the end user that your business has read their incoming message. This displays a "read" indicator in their messaging app.
POST https://api.enablex.io/rcs/v1/messages/read
Authorization: Bearer {token}
Content-Type: application/json
{
"request_id": "incoming-message-request-id",
"phone": "+919876543210",
"agent": "your-agent-name"
}
| Key | Type | Required | Description |
|---|---|---|---|
request_id | String | Yes | The request_id of the incoming message to mark as read |
phone | String | Yes | User's phone number with country code |
agent | String | Yes | RBM Agent name |
Send a Typing Indicator
Show the user that your business is composing a response. This displays a typing animation in the user's messaging app.
POST https://api.enablex.io/rcs/v1/indicators/typing
Authorization: Bearer {token}
Content-Type: application/json
{
"request_id": "incoming-message-request-id",
"phone": "+919876543210",
"agent": "your-agent-name"
}
Error Handling
All RCS API errors follow a consistent JSON format:
{
"code": 1003,
"message": "Authentication failed",
"description": "Invalid credentials or the account has been deactivated"
}
| Error Code | Meaning | Action |
|---|---|---|
1002 | Invalid/Expired Token | Regenerate a Bearer Token using the Token API |
1003 | Authentication Failed | Verify your APP ID and APP Key credentials |