> ## 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.

# RCS

> Send rich messaging experiences with RCS Business Messaging through Orbit

# RCS

Deliver app-like messaging experiences natively in users' default messaging apps with RCS Business Messaging. Orbit provides RCS via DotGo's RBM Hub (the same RCS aggregator powering bot registration, template approval, and carrier delivery throughout Orbit), supporting rich cards, carousels, suggested actions, and branded sender profiles.

## Send an RCS Message

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/messages/rcs \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155552671",
    "body": "Your order #12345 has shipped!",
    "suggested_replies": [
      { "action": { "text": "Track Order", "open_url": { "url": "https://example.com/track/12345" } } },
      { "reply": { "text": "Contact Support", "postback_data": "contact_support" } }
    ]
  }'
```

A send is either plain text (`body`), a standalone `rich_card`, or a
`rich_card_carousel` — they are mutually exclusive. For text and media sends,
attach chips under the top-level `suggested_replies` array; rich cards and
carousels carry their own chips under `rich_card.suggestions` and
`rich_card_carousel.suggestions`. Each suggestion chip is either a `reply`
(`{ text, postback_data }`) or an `action`
(`{ text, open_url | dial_action | view_location_action }`).

## Send a Rich Card

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/messages/rcs \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155552671",
    "rich_card": {
      "card_content": {
        "title": "Nike Air Max 90",
        "description": "$129.99 — Free shipping on orders over $50",
        "media": {
          "height": "MEDIUM",
          "content_info": { "file_url": "https://example.com/images/shoe.jpg" }
        }
      },
      "suggestions": [
        { "action": { "text": "Buy Now", "open_url": { "url": "https://example.com/buy/shoe" } } },
        { "reply": { "text": "More Details", "postback_data": "details_air_max_90" } }
      ]
    }
  }'
```

## Send a Carousel

Carousels render 2–10 cards via `rich_card_carousel.card_contents`. A
single-card carousel renders as malformed on Android — use `rich_card` for one
card.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/messages/rcs \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155552671",
    "rich_card_carousel": {
      "card_width": "MEDIUM",
      "card_contents": [
        {
          "title": "Nike Air Max 90",
          "description": "$129.99 — Free shipping",
          "media": {
            "height": "MEDIUM",
            "content_info": { "file_url": "https://example.com/images/air-max-90.jpg" }
          },
          "suggestions": [
            { "action": { "text": "Buy Now", "open_url": { "url": "https://example.com/buy/air-max-90" } } }
          ]
        },
        {
          "title": "Nike Pegasus 41",
          "description": "$139.99 — Free shipping",
          "media": {
            "height": "MEDIUM",
            "content_info": { "file_url": "https://example.com/images/pegasus-41.jpg" }
          },
          "suggestions": [
            { "action": { "text": "Buy Now", "open_url": { "url": "https://example.com/buy/pegasus-41" } } }
          ]
        }
      ]
    }
  }'
```

## Features

* **Rich cards** — image, title, description, and action buttons in a single message
* **Carousels** — horizontally scrollable card collections (up to 10 cards)
* **Suggested replies & actions** — tap-to-reply buttons and deep links
* **Branded sender** — verified business name, logo, and color in the chat thread
* **Typing indicators** — real-time composing indicators
* **Read receipts** — delivery and read confirmation
* **SMS fallback** — automatic fallback to SMS when RCS is unavailable

## RCS Availability

RCS is supported on Android devices with Google Messages. When the recipient's
device cannot receive RCS (Apple device, older Android, RBM not enrolled, or
the carrier does not bridge to the RBM hub), Orbit can automatically retry the
send over SMS without changing your request.

The fallback chain is **configured per organization**, not per request. Once
configured, every RCS send transparently retries the next channel in the chain
when delivery fails for an RCS-specific reason (capability check returns
`not_capable`, all RCS providers exhaust their attempts, or the recipient has
not opted in to RCS in their messaging app).

### Configure RCS → SMS fallback

The cross-channel fallback chain lives on the organization, under
`settings.cross_channel_fallback`. Enable it once from the dashboard:

1. Open **Settings → Channels → Cross-Channel Fallback**.
2. Add a rule with **Primary: RCS** and **Fallback: SMS** (you can chain more
   channels — e.g. `RCS → WhatsApp → SMS` — and they will be tried in order).
3. Save. The change takes effect on the next send; no redeploy or send-path
   change is required.

### What triggers the fallback

* **Capability check fails** — Orbit's capability cache (or a live Dotgo
  probe) reports `not_capable` for the recipient's number. The RCS attempt
  short-circuits with `RCS_NOT_SUPPORTED` and the router advances to the
  next channel in the chain.
* **All RCS providers fail** — every registered RCS provider returns a
  non-retryable error within the configured retry budget.
* **TCPA opt-out re-check** — when the chain falls through to SMS, Orbit
  re-runs the SMS opt-out + DNC check against the recipient. If they have
  opted out of SMS (even though they accepted RCS), the message is
  suppressed rather than delivered over SMS.

The request body for `/messages/rcs` does **not** accept a `fallback` field
— passing one is ignored. Fallback behavior is entirely driven by the
organization-level configuration so it stays consistent across every send
path (API, campaigns, journeys, inbox replies) without requiring callers to
remember to set a flag.

## Rate limits

Orbit throttles outbound calls to Dotgo's RBM Hub with a Redis-backed
sliding-window limiter so you stay within Dotgo's agreed throughput and avoid
upstream 429s. The limit is scoped **per tenant**: each account gets its own
ceiling of `DEVOTEL_RCS_RATE_LIMIT` sends per `DEVOTEL_RCS_RATE_WINDOW_MS`
window, so one tenant's send volume never eats into another's. Size your
capacity planning against this per-tenant ceiling, not a shared global pool.

Both knobs are operator-tunable **without a redeploy** — set the env var
(Secret Manager / cluster env) and restart the pod:

| Env var                      | Default | Description                                                                                                                          |
| ---------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `DEVOTEL_RCS_RATE_LIMIT`     | `50`    | Maximum outbound RCS sends permitted **per tenant** within each window. Raise it to match a higher contracted Dotgo throughput tier. |
| `DEVOTEL_RCS_RATE_WINDOW_MS` | `60000` | Length of the rate-limit window, in milliseconds (default 60s).                                                                      |

Raise `DEVOTEL_RCS_RATE_LIMIT` and `DEVOTEL_RCS_RATE_WINDOW_MS` together so the
effective per-tenant rate (sends ÷ window) matches your Dotgo TPS tier — bumping
one without the other changes the burst shape, not just the throughput.

## Agent Registration

RCS requires a verified business agent. Register yours in **Channels > RCS > Agent Settings** on the Orbit dashboard. Verification typically takes 3–5 business days.
