---
title: "RCS Business Messaging API"
description: "Send RCS text, media, rich cards, carousels and suggested replies, check device capability first, and plan SMS fallback for users without RCS."
canonical: "https://omnichannels.ai/developers/rcs/"
language: "en"
updated: "2026-10-10"
publisher: "BroadNet Technologies"
brand: "OmniChannels.ai"
section: "Messaging channels"
---

# RCS Business Messaging API

Canonical: https://omnichannels.ai/developers/rcs/
Language: en
Publisher: OmniChannels.ai by BroadNet Technologies

RCS Business Messaging delivers branded, verified messages with rich cards, carousels and suggested actions to the phone's native messaging app. You send every RCS message type through `POST /rcs/message/sendbulk`, a multipart endpoint where `messageType` selects the payload.

## Before you send

- **A launched RCS agent.** Your brand's verified sender (the agent) is registered with Google and the carriers by our team as part of onboarding. While the agent is in test, it only delivers to registered test numbers.
- **Recipients in E.164 with a leading `+`**, for example `+447700900123`. RCS rejects numbers without the `+` at validation time, unlike the SMS API.
- **A fallback plan** for users whose device or carrier does not support RCS (see below).

## Message types

| `messageType` | Required fields | Rules |
| --- | --- | --- |
| `TEXT` | `content` | Up to 3,072 characters. |
| `MEDIA` | `mediaUrl` | HTTPS URL to an image, video, audio file or PDF. Optional `caption`, `fileName`. |
| `CARD` | `cardsJson` | One rich card. Title up to 200 characters, description up to 2,000, media over HTTPS, up to 10 suggestions. |
| `CAROUSEL` | `cardsJson` | 2 to 10 cards, same per-card rules as `CARD`. |
| `CHOICE` | `content`, `choicesJson` | Up to 10 suggested replies or actions; each needs non-empty `text`. |
| `LOCATION` | `latitude`, `longitude` | Latitude between -90 and 90, longitude between -180 and 180. Optional `locationName`, `locationAddress`. |
| `TEMPLATE` | `templateId` | Template ID in ULID format (26 characters), plus `templateVersion`, `templateLanguage`, `parametersJson`. |

Invalid requests are rejected up front with `400`, rather than failing silently per recipient.

## Common fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `messageType` | string | Yes | One of the types above. |
| `destinationNo` | string | One of these two | One or more E.164 numbers with `+`, comma-separated. |
| `destinationFiles` | file | One of these two | File of recipients for bulk sends. |
| `recipientType` | string | No | `PHONE`. |
| `batchId` | string | No | `0` starts a new batch. |
| `campaignName` | string | No | Your label for reporting. |
| `allowDuplicate` | string | No | `false` removes duplicates. |
| `delay` | string | No | Throttle between messages. |
| `scheduled` | string | No | `true` to schedule. |
| `scheduleTime` | string | When scheduled | For example `2026-11-01 10:00:00.000`. |
| `gmt` | string | When scheduled | GMT offset, for example `+04:00`. |
| `recurrence`, `repeatCount` | string | No | `NONE`, `DAILY` and so on, and how many times to repeat. |

## Send a rich card

A card has a title, a description, an image and up to 10 suggestions. A suggestion with a `url` opens a link, one with a `phoneNumber` starts a call, and one with only `postbackData` is a suggested reply that comes back to you when tapped.

```bash title="cURL"
curl -X POST https://api.broadnet.me/rcs/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F campaignName=autumn-launch \
  -F destinationNo=+447700900123 \
  -F messageType=CARD \
  -F 'cardsJson={"title":"Autumn collection is here","description":"New arrivals with launch-week prices.","mediaUrl":"https://cdn.example.com/omnidemo/autumn.jpg","height":"MEDIUM","choices":[{"text":"Shop now","url":"https://example.com/autumn","postbackData":"SHOP"},{"text":"Call us","phoneNumber":"+447700900100","postbackData":"CALL"},{"text":"Not now","postbackData":"LATER"}]}'
```

```js title="Node.js"
const card = {
  title: "Autumn collection is here",
  description: "New arrivals with launch-week prices.",
  mediaUrl: "https://cdn.example.com/omnidemo/autumn.jpg",
  height: "MEDIUM",
  choices: [
    { text: "Shop now", url: "https://example.com/autumn", postbackData: "SHOP" },
    { text: "Call us", phoneNumber: "+447700900100", postbackData: "CALL" },
    { text: "Not now", postbackData: "LATER" },
  ],
};

const form = new FormData();
form.append("batchId", "0");
form.append("campaignName", "autumn-launch");
form.append("destinationNo", "+447700900123");
form.append("messageType", "CARD");
form.append("cardsJson", JSON.stringify(card));

const res = await fetch("https://api.broadnet.me/rcs/message/sendbulk", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.BROADNET_TOKEN}` },
  body: form,
});
console.log(res.status, await res.text());
```

```python title="Python"
import json
import os
import requests

card = {
    "title": "Autumn collection is here",
    "description": "New arrivals with launch-week prices.",
    "mediaUrl": "https://cdn.example.com/omnidemo/autumn.jpg",
    "height": "MEDIUM",
    "choices": [
        {"text": "Shop now", "url": "https://example.com/autumn", "postbackData": "SHOP"},
        {"text": "Call us", "phoneNumber": "+447700900100", "postbackData": "CALL"},
        {"text": "Not now", "postbackData": "LATER"},
    ],
}
fields = {
    "batchId": "0",
    "campaignName": "autumn-launch",
    "destinationNo": "+447700900123",
    "messageType": "CARD",
    "cardsJson": json.dumps(card),
}
r = requests.post(
    "https://api.broadnet.me/rcs/message/sendbulk",
    headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
    files={k: (None, v) for k, v in fields.items()},
    timeout=30,
)
print(r.status_code, r.text)
```

## Send a carousel

A carousel is a JSON array of 2 to 10 cards in `cardsJson`:

```bash title="cURL"
curl -X POST https://api.broadnet.me/rcs/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=+447700900123 \
  -F messageType=CAROUSEL \
  -F 'cardsJson=[{"title":"Classic","description":"Best seller","mediaUrl":"https://cdn.example.com/omnidemo/a.jpg","height":"MEDIUM","choices":[{"text":"Buy","url":"https://example.com/a","postbackData":"BUY_A"}]},{"title":"Premium","description":"New arrival","mediaUrl":"https://cdn.example.com/omnidemo/b.jpg","height":"MEDIUM","choices":[{"text":"Buy","url":"https://example.com/b","postbackData":"BUY_B"}]}]'
```

## Send suggested replies

`CHOICE` sends a text with tappable suggestions:

```bash title="cURL"
curl -X POST https://api.broadnet.me/rcs/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=+447700900123 \
  -F messageType=CHOICE \
  -F "content=How was your delivery today?" \
  -F 'choicesJson=[{"text":"Great","postbackData":"CSAT_5"},{"text":"OK","postbackData":"CSAT_3"},{"text":"Poor","postbackData":"CSAT_1"}]'
```

Suggestions can also carry a `url` (open a link, or add an event to a calendar) or `latitude` and `longitude` (share a location).

## Send a template

RCS templates are created with `POST /rcs/template/create` and sent by ID with their parameters:

```bash title="cURL"
curl -X POST https://api.broadnet.me/rcs/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=+447700900123 \
  -F recipientType=PHONE \
  -F messageType=TEMPLATE \
  -F templateId=01ARZ3NDEKTSV4RRFFQ69G5FAV \
  -F templateVersion=1 \
  -F templateLanguage=en \
  -F 'parametersJson={"name":"Sara","otp":"482913"}' \
  -F campaignName=login-otp
```

Related endpoints: `POST /rcs/template/list`, `GET /rcs/template/name`, `GET /rcs/template/grouped`, `PUT /rcs/template/{RCS_TEMPLATE_ID}` and `DELETE /rcs/template/{RCS_TEMPLATE_ID}`.

## Check capability and plan fallback

Not every device or carrier supports RCS. Plan what happens for those users.

- **Platform fallback.** Channel fallback (for example WhatsApp, then RCS, then SMS) is configured per use case with our team, and delivery statuses come back in one webhook format.
- **Your own fallback.** If you orchestrate channels yourself, check capability first and send SMS through `POST /sms/sendSms` when RCS is not available. You can also fall back when a webhook reports `FAILED` for an RCS message.

`POST /rcs/capability/query` submits a capability lookup for a number and returns a request ID for tracking:

```bash title="cURL"
curl -X POST "https://api.broadnet.me/rcs/capability/query?recipient=%2B447700900123" \
  -H "Authorization: Bearer $BROADNET_TOKEN"
```

URL-encode the `+` as `%2B` in query strings.

## Test, track and control batches

| Method | Path | Description |
| --- | --- | --- |
| POST | `/rcs/message/test?to=…&text=…` | Single text smoke test. While your agent is in test, it only reaches test numbers. |
| POST | `/rcs/message/batches` | List batches (JSON body with `page`, `size`, `status` and date filters). |
| GET | `/rcs/message/about?batchId=…` | Batch details. |
| GET | `/rcs/message/pause?batchId=…` | Pause a `PENDING` or `INPROGRESS` batch. |
| GET | `/rcs/message/resume?batchId=…` | Resume a paused batch. |
| DELETE | `/rcs/message/abort?batchId=…` | Abort a batch. |
| POST | `/rcs/message/typing` | Show a typing indicator. |

Note that RCS batch endpoints take `batchId`, while SMS, WhatsApp, Messenger, Instagram, Telegram and Email take `batch_Id`.

Batch statuses are `PENDING`, `INPROGRESS`, `PAUSED`, `DONE`, `ABORTED` and `FAILED`. Per-recipient delivery statuses arrive on your webhook.

## Next steps

- [Webhooks](/developers/webhooks/): receive RCS statuses and postback replies.
- [SMS API](/developers/sms/): the fallback channel for non-RCS devices.
- [WhatsApp API](/developers/whatsapp/): rich messaging on WhatsApp.
- [Errors and limits](/developers/errors-and-limits/): handle validation errors and retries.
