RCS Campaign API
Launch RCS campaigns and manage message templates directly from your own application. Two REST endpoints cover the full lifecycle: one creates reusable templates, the other sends a template to a contact list. Delivery and interaction events are posted back to your webhook as they occur.
| Document ID | Version | Status | Protocol | Authentication | Last updated |
|---|---|---|---|---|---|
| FON-API-RCS-001 | 1.0 | Released | REST over HTTPS, JSON | Bearer API key | 07 September 2026 |
1. Overview
A working integration has three moving parts. A template defines what the message looks like and which variables it accepts. A campaign pairs that template with a contact list and submits it for delivery. A webhook receives the delivery and click events that follow. Build them in that order — a campaign cannot reference a template that does not yet exist.
BASE URL — https://app.fonada.ai/functions/v1
| Endpoint | Method | Purpose |
|---|---|---|
/rcs_template_manager | POST | Create a text, standalone, or carousel template. |
/rcs_campaign_launcher | POST | Send an existing template to a list of contacts. |
1.1 Conventions used in this document
| Notation | Meaning |
|---|---|
| Required | The request is rejected if the field is absent. |
| Conditional | Required only when a related field takes a specific value — the condition is stated in the description. |
| Optional | May be omitted. Any default is stated in the description. |
{{variable}} | A placeholder in template content, replaced at send time by the matching key in a contact's params object. |
fsk_… | Placeholder for your workspace API key. Replace it with your own value in every example. |
2. Authentication
Every request carries an API key in the Authorization header as a bearer token. Keys are issued per workspace from the Fonada console and are prefixed with fsk_. Requests and responses are JSON, and Content-Type must be set on every call.
Authorization: Bearer fsk_your_api_key_here Content-Type: application/json
3. Send a campaign message
POST /rcs_campaign_launcher
Pairs an existing template with a list of contacts and submits the campaign for delivery. Each contact may carry its own params object, which fills the {{variable}} placeholders defined in the template.
curl --location 'https://app.fonada.ai/functions/v1/rcs_campaign_launcher' \
--header 'Authorization: Bearer fsk_your_api_key_here' \
--header 'Content-Type: application/json' \
--data '{
"template_name": "MY_Template2",
"campaign_name": "March_Bulk_Promo",
"contacts": [
{ "mobile": "98xxxxxxxx", "params": { "name": "John", "city": "Mumbai" } },
{ "mobile": "76xxxxxxxx", "params": { "name": "Priya", "city": "Delhi" } }
]
}'3.1 Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
template_name | string | Required | Name of an existing RCS template. Case-sensitive; must match the stored template exactly. |
campaign_name | string | Required | Identifier for this campaign run. Appears in the campaign dashboard and in report exports. |
contacts | array | Required | Array of contact objects. One message is queued per entry. |
contacts[].mobile | string | Required | Recipient mobile number, 10 digits. |
contacts[].params | object | Optional | Key-value pairs used for variable substitution. Keys must match the {{variable}} names declared in the template. |
3.2 Response
{
"status": "success",
"campaign_id": "camp-20260330-xyz",
"messages_queued": 2
}| Field | Type | Description |
|---|---|---|
status | string | Result of the submission. |
campaign_id | string | Unique campaign reference. Persist this — it links your records to the campaign dashboard and to every per-recipient row in the report export. |
messages_queued | integer | Number of messages accepted for delivery after validation. |
4. Template management
POST /rcs_template_manager
Templates are reusable message designs. Create one, then reference it by name from any campaign. All three types use this endpoint; the template_type field selects the layout.
| Type | Renders as | Recommended for |
|---|---|---|
text | Formatted text with optional buttons | OTPs, reminders, and transactional alerts. Degrades to SMS most gracefully on non-RCS devices. |
standalone | A single rich card with hero media | Promotions, onboarding, and single-offer announcements. |
carousel | Two to ten horizontally scrollable cards | Product catalogues, multi-offer sends, and comparison sets. |
4.1 Plain text template
A text message with optional quick-reply and URL suggestions.
curl --location 'https://app.fonada.ai/functions/v1/rcs_template_manager' \
--header 'Authorization: Bearer fsk_your_api_key_here' \
--header 'Content-Type: application/json' \
--data '{
"action": "create_template",
"template_name": "welcome_text_v1",
"template_type": "text",
"bot_name": "Fonada AI",
"text": "Hello {{name}}, welcome to {{brand}}!",
"suggestions": [
{ "type": "reply", "label": "Know More", "postback": "know_more" },
{ "type": "url", "label": "Visit Website", "url": "https://fonada.com" }
]
}'| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Required | Must be create_template. |
template_name | string | Required | Unique template name. Short, without spaces. |
template_type | string | Required | Set to text. |
bot_name | string | Required | Display name of the verified RCS bot that sends the message. |
text | string | Required | Message body. Use {{variable}} for dynamic values. |
suggestions | array | Optional | Buttons shown beneath the message. |
suggestions[].type | string | Required | One of reply, url, or phone. |
suggestions[].label | string | Required | Button label shown to the recipient. Keep it short and verb-led. |
suggestions[].postback | string | Conditional | Required when type is reply. Returned to your webhook when the button is tapped. |
suggestions[].url | string | Conditional | Required when type is url. Opened in the device browser. |
4.2 Standalone rich card
A single card with a title, description, hero media, and action buttons.
curl --location 'https://app.fonada.ai/functions/v1/rcs_template_manager' \
--header 'Authorization: Bearer fsk_your_api_key_here' \
--header 'Content-Type: application/json' \
--data '{
"action": "create_template",
"template_name": "diwali_offer_v1",
"template_type": "standalone",
"bot_name": "Fonada AI",
"title": "Special Offer for {{name}}",
"description": "Get 20% off today!",
"media_url": "https://cdn.example.com/offer-hero.jpg",
"orientation": "VERTICAL",
"media_height": "MEDIUM_HEIGHT",
"suggestions": [
{ "type": "url", "label": "Claim Offer", "url": "https://www.fonada.com/" },
{ "type": "phone", "label": "Call Us", "phone": "+919876543210" }
]
}'| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Required | Must be create_template. |
template_name | string | Required | Unique template name. |
template_type | string | Required | Set to standalone. |
bot_name | string | Required | Display name of the RCS bot. |
title | string | Required | Card headline. Supports {{variable}} substitution. |
description | string | Optional | Card subtitle or body text. |
media_url | string | Optional | Publicly reachable image URL used as the card hero. |
orientation | string | Optional | VERTICAL (default) or HORIZONTAL. Use vertical for portrait artwork, horizontal for landscape. |
media_height | string | Optional | SHORT_HEIGHT, MEDIUM_HEIGHT, or TALL_HEIGHT. |
suggestions | array | Optional | Action buttons. Supports url and phone types. |
suggestions[].label | string | Required | Button label shown to the recipient. |
suggestions[].url | string | Conditional | Required when type is url. |
suggestions[].phone | string | Conditional | Required when type is phone. Use E.164 format, for example +919876543210. |
4.3 Carousel
A horizontally scrollable set of rich cards, used when one message needs to present several products or offers.
curl --location 'https://app.fonada.ai/functions/v1/rcs_template_manager' \
--header 'Authorization: Bearer fsk_your_api_key_here' \
--header 'Content-Type: application/json' \
--data '{
"action": "create_template",
"template_name": "Cars_Carousel",
"template_type": "carousel",
"bot_name": "Fonada AI",
"card_width": "MEDIUM",
"cards": [
{
"title": "Car A",
"description": "Best sedan",
"media_url": "https://example.com/a.jpg",
"suggestions": [{ "type": "url", "label": "View", "url": "https://car-a.com" }]
},
{
"title": "Car B",
"description": "Best SUV",
"media_url": "https://example.com/b.jpg",
"suggestions": [{ "type": "url", "label": "View", "url": "https://car-b.com" }]
}
]
}'| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Required | Must be create_template. |
template_name | string | Required | Unique template name. |
template_type | string | Required | Set to carousel. |
bot_name | string | Required | Display name of the RCS bot. |
card_width | string | Optional | SMALL or MEDIUM (default). |
cards | array | Required | Card objects. Minimum 2, maximum 10. |
cards[].title | string | Required | Title text for the card. |
cards[].description | string | Optional | Subtitle or body text for the card. |
cards[].media_url | string | Optional | Hero image URL for the card. |
cards[].suggestions | array | Optional | Per-card action buttons. |
4.4 Suggestion types
| Type | Description | Behaviour on tap |
|---|---|---|
reply | Quick-reply chip | Posts postback_data to your webhook. The recipient stays in the conversation. |
url | Link button | Opens the target page in the device browser. |
phone | Call button | Opens the dialler pre-filled with the given number. |
5. Webhooks
Fonada posts a JSON payload to your configured webhook URL whenever a message changes state or a recipient taps a button. Acknowledge with 200 OK as soon as the payload is received and process it asynchronously; long-running work inside the request handler risks timeouts.
5.1 Delivery status events
{
"event_type": "delivery_status",
"timestamp": "2026-02-11T20:05:00Z",
"message_id": "msg-123",
"bot_id": "fonada-bot-12345",
"recipient": "910000000000",
"status": "delivered",
"status_details": {
"sent_at": "2026-02-11T20:00:00Z",
"delivered_at": "2026-02-11T20:00:02Z"
}
}5.2 Status values
| Status | Meaning | Trigger |
|---|---|---|
sent | Message accepted by the carrier | Immediately after submission |
delivered | Message reached the handset | On device receipt |
read | Message opened by the recipient | When the conversation is opened |
failed | Delivery could not complete | On error, accompanied by an error object |
The statuses are independent of one another. A message may be delivered and never read, so treat delivery rate as a health metric and read rate as an engagement metric.
5.3 Failure payload
{
"event_type": "delivery_status",
"message_id": "msg-124",
"status": "failed",
"error": {
"code": "INVALID_NUMBER",
"message": "Phone number is invalid or not reachable"
}
}5.4 Button click events
When a recipient taps a suggestion, a button_click event is posted to the same webhook URL. Key your application logic on postback_data rather than button_text — the postback stays stable when the visible label changes.
{
"event_type": "button_click",
"timestamp": "2026-02-11T20:10:00Z",
"message_id": "msg-123",
"bot_id": "fonada-bot-12345",
"user_phone": "910000000000",
"interaction": {
"type": "action",
"button_text": "Buy Now",
"postback_data": "buy_product_123",
"url": "https://shop.com/buy?product=123"
}
}| Interaction type | Description | Typical use |
|---|---|---|
action | Call-to-action button | Buy, Subscribe, Learn More |
url | URL button | Opening a website |
phone | Call button | Contacting support |
6. Response codes and errors
API responses
| Code | Meaning | Recommended action |
|---|---|---|
| 200 | Request accepted; messages queued or template created. | Record campaign_id and continue. |
| 400 | Malformed body, unknown template_name, or invalid field value. | Validate the JSON payload and confirm the template exists with the exact name. |
| 401 | Missing or invalid bearer token. | Check the fsk_ key and the header spelling, then retry. |
Webhook error codes
| Code | Meaning | Recommended action |
|---|---|---|
INVALID_NUMBER | The number is invalid or not reachable. | Remove or correct the entry and clean the audience list before the next run. |
7. Operational guidance
- Validate before you send. Confirm every contact supplies each variable the template declares, and normalise numbers to a consistent format.
- Test on a small list first. Run one campaign per template type against a handful of internal numbers before a production send.
- Make webhook handlers idempotent. Key on message_id plus status so a repeated event does not double-count a delivery.
- Reconcile regularly. Compare submitted counts against your own records; discrepancies usually indicate duplicates or malformed rows in the audience list.
- Use stable postback codes. Short machine-readable values such as BOOK_DEMO survive copy changes and keep downstream analytics consistent.
8. Support
For integration support, quote the campaign_id and the affected message_id when raising a ticket — these identify the exact send in platform logs.
| Technical support | 1800 120 0081 |
| info@fonada.com | |
| Console | app.fonada.ai |
| Related documentation | RCS Campaign Management, Media Manager, KPI Analytics |
Appendix A — Revision history
| Version | Date | Summary of change | Author |
|---|---|---|---|
| 1.0 | 07 Sep 2026 | First released edition. Campaign launcher, three template types, delivery and click webhooks, response codes. | Platform Engineering |