> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Build rich RCS cards in the visual builder

> Design RCS rich cards and carousels in Messages → RCS → Builder — pick the bot, add media and suggestion chips, validate against carrier limits, preview on a device mock, save to the template library, and reference the template from a campaign or the API.

# Build Rich RCS Cards in the Visual Builder

The **Rich Card Studio** on **Messages → RCS → Builder** is the visual authoring surface for RCS templates. You compose a rich card or carousel, watch it render on a live device preview, save it into the same template library the [RCS Templates tab](/guides/rcs-templates-tab) manages, and send a test to a real handset — without writing the JSON by hand. This guide walks that flow end to end: where the builder sits, what each control does, what limits it enforces, and how the saved definition reaches a campaign.

Prerequisites: a **launched RCS agent** on your tenant. If you have not enrolled a brand and launched an agent yet, work through the [RCS onboarding guide](/guides/rcs-onboarding) first — enrollment itself is covered in the [RCS brands console guide](/guides/rcs-brands-console). The builder needs an agent before it can save or send.

## 1. Open the builder: Messages → RCS → Builder

Open **Messages → RCS → Builder**. The page splits into two columns: the authoring form on the left, a live device preview and the save/send actions pinned on the right. Every keystroke re-renders the preview, so what you see is what the handset renders.

The **Setup** card asks for two things:

* **RCS Bot** — the agent the design belongs to. Templates are scoped per agent, so pick the bot first; anything you author from here lands under that agent's template roster.
* **Template name** — the key the design is stored under. It becomes the identifier a campaign or API send references later, so name it for the use (`order_update_card`, `back_in_stock_carousel`), not for the experiment (`test_v2`).

With no bot selected the save and send controls stay disabled, and the page tells you to create and verify an RCS bot first.

## 2. Compose the card

The second card is the composer. Two tabs pick the shape the carrier delivers:

* **Rich Card** — a single card: one title, one description, one media item, up to four suggestion chips. Use this for a single offer, update, or call to action.
* **Carousel** — two to ten cards the recipient swipes through. Use this for a product set, a pick-list, or a menu. Each card carries its own title, description, media, and chips; drag a card to reorder the swipe order.

Inside a card you fill:

* **Title** — the heading the recipient reads first. Required.
* **Description** — supporting copy under the title.
* **Media** — an image or video. Paste an HTTPS URL or upload a file; the upload lands in your media library and the URL fills in for you. Pick a **Height** (Short, Medium, Tall) that matches the crop — media with a different aspect renders letter-boxed on the device.
* **Suggestions** — the chips at the card's foot. Each chip has a type: **Reply** (a tap-to-reply postback), **Open URL** (a web link), **Dial** (a phone number), or **Calendar** (an event with start and end times). A chip with an incomplete payload — an Open URL with no link, a Dial with no number — is dropped at save, so the recipient never sees a dead button.

Two helpers keep personalization out of hard-coded copy:

* **Insert variable** (in the title and description headers) drops a `{{1}}`, `{{2}}`, … token at the caret. The tokens are the placeholders a campaign's per-recipient variables fill at send time; the preview highlights them as pills so you can see where dynamic values land.
* Switching between **Rich Card** and **Carousel** keeps your cards — you can author one card, flip the tab, and add a second card without retyping.

## 3. Per-carrier preview and fallback degradation

The right-hand column renders the design inside a device mock as you type — title, description, media crop, and chips included. Treat it as the high-fidelity path: it shows what a capable RCS handset gets.

RCS delivery is capability-gated per recipient. When a handset does not advertise RCS, the send short-circuits and the channel chain steps in — the recipient gets an **SMS with the card's text instead of the card**, and the media and chips do not downgrade into MMS automatically. Design with that in mind:

* Keep the **title plus description** readable on their own — they are the text the SMS fallback carries. If the card makes no sense without the image, a downgraded recipient gets a broken message.
* Put the essential call to action in the text, not only on a chip. Chips fall away on SMS; the URL they pointed at should also live in the description for the fallback recipient.
* The chain is configured per organization, not per send — see **Configure RCS → SMS fallback** on the [RCS channel page](/channels/rcs#fallback-chain) for where it lives and how the ladder advances.

To see the real thing before a campaign does, use **Send a test to** next to Save: enter an E.164 address, hit send, and the design goes out over the bot to a live handset. A test to a non-RCS handset shows you the fallback path the campaign would take.

## 4. Save to the template library and wire it into a campaign

**Save template** submits the design into the selected bot's template roster — the same roster the [RCS Templates tab](/guides/rcs-templates-tab) lists with approval badges and per-template deliverability. A save starts life as **Pending review**: the carrier reviews the definition, and only an **Approved** template can be sent by a campaign.

The **Saved templates** list below the composer shows the bot's existing templates with two row actions:

* **Edit** — rehydrates the builder from the stored definition and locks the name. Saving an edit is an in-place update: it resets carrier approval to **Pending review** under the same name, so a campaign that references the template goes back to waiting until the carrier re-approves. Never open a live template in edit mode mid-campaign as an exploratory session — an accidental save re-triggers the review window.
* **Delete** — removes the template after a confirmation. Any campaign or flow still sending it starts failing, so check references first.

Once approved, the template is referenceable two ways. In the **campaign create wizard** the RCS channel step lists the agent's approved templates by name — pick one and the wizard stamps the template's definition onto the campaign instead of composing inline.

Via the API a campaign wires the same template by creating the campaign with `channel: "rcs"` and the template's body text as `message_template` — the SMS-fallback string the non-RCS recipients degrade to:

```bash cURL theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/campaigns \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Back in stock — Q3",
    "channel": "rcs",
    "message_template": "Your saved item is back: grab it before it sells out. Reply STOP to opt out.",
    "channels": [
      { "channel": "rcs", "order": 0, "fallback_on": "failed", "fallback_after_seconds": 300 },
      { "channel": "sms", "order": 1 }
    ]
  }'
```

The `{{1}}`-style tokens you dropped during authoring resolve against the campaign's per-recipient variables before the call goes out. The ordered `channels` ladder (`RCS → SMS`) rides the same org-level chain — declare it on the campaign so the down-for-SMS hop is explicit.

Two pre-launch checks gate the send: the template's badge must read **Approved**, and the organization must have its RCS → SMS fallback chain configured. Read the badge on the Templates tab or `GET /api/v1/rcs/bots/:id/templates/:name` before launching.

## 5. The full saved-template shape

Saving a rich card through the builder is the API's template create — the builder runs the same call under the hood. A single rich card lands as:

```bash cURL theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/rcs/bots/bot_abc/templates \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "rich_template_data": {
      "name": "back_in_stock_card",
      "msg_type": "rich_card",
      "body": "Your saved item is available again: grab it before it sells out.",
      "card_title": "{{1}} is back in stock",
      "card_description": "Reply STOP to opt out. Offer expires Sunday.",
      "card_media_url": "https://cdn.example.com/products/air-max-90.jpg"
    }
  }'
```

`body` doubles as the plain-text SMS-fallback string; `card_title` / `card_description` / `card_media_url` carry the rich content. A carousel save swaps to `msg_type: "carousel"` and moves the card set into `carousel_json` — a JSON-encoded array of 2–10 `{ title, description, media }` card shells, the envelope the RCS provider renders per-card suggestions from at send time. Read the full per-field contract on the [RCS channel page Templates section](/channels/rcs#templates).

`GET /api/v1/rcs/bots/:id/templates/:name` returns the stored definition plus its current approval status — use it to diff what a campaign will send against the edit you are about to publish.

## 6. Limits and validation

The builder validates inline and blocks save/send until the design is clean. The limits are the carrier's, not arbitrary — a template that breaks them comes back rejected, so the builder catches them up front:

| Limit                | Rule                                                                                                           |
| -------------------- | -------------------------------------------------------------------------------------------------------------- |
| Title                | Required on every card.                                                                                        |
| Media URL            | HTTPS only — RBM rejects `http://` or unprefixed URLs. Upload fills a hosted HTTPS URL for you.                |
| Suggestions per card | At most 4 chips per card.                                                                                      |
| Reply chip text      | 25 characters.                                                                                                 |
| Carousel size        | 2–10 cards. A single card belongs on the **Rich Card** tab — a one-card carousel renders malformed on Android. |
| Open URL value       | Must be an `http(s)://` link.                                                                                  |
| Dial value           | Must include a phone number.                                                                                   |
| Calendar value       | Must include a start and end time.                                                                             |

Each violation surfaces in the composer as an inline warning naming the card and the missing field — fix the list top to bottom before saving. The save call re-validates server-side and returns a `422` naming the invalid field, so a race past the client-side check still fails closed.

## Related

* [RCS onboarding](/guides/rcs-onboarding) — brand, agent, verification, and launch: the path to the bot the builder saves under.
* [RCS brands console](/guides/rcs-brands-console) — enroll and resubmit brands from the dashboard before an agent exists.
* [RCS Templates tab](/guides/rcs-templates-tab) — the approval lifecycle, deliverability counters, and sequencing discipline for the templates the builder saves.
* [RCS channel page](/channels/rcs) — the full send contract, the fallback chain, and the template REST surface.
