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

# Troubleshooting: RCS undelivered or never reaching an RCS-capable device

> Tell a recipient-capability failure (RCS_NOT_SUPPORTED) from a carrier-side lifecycle failure, read the RCS-specific classified error code, and map every cause — unlaunched agent, incapable handset, malformed card, rejected agent, throughput cap — to its fix.

# Troubleshooting: RCS undelivered or never reaching an RCS-capable device

RCS fails at two distinct layers, and the fix is different for each. This
page separates them first, then decodes each cause and its resolution.

* **RCS not supported (capability failure, pre-submit)** — the recipient's
  handset cannot receive RCS from your agent, so Orbit short-circuits the
  send before it reaches a carrier. The row fails closed with an
  `RCS_NOT_SUPPORTED` receipt. This is a **reachability** problem, not a
  delivery problem — fix it before the send.
* **RCS undelivered (carrier-side lifecycle failure)** — the agent and the
  recipient both passed the capability check, but the carrier rejected the
  message, the agent was not launched, the template schema was refused, or
  the per-tenant throughput cap turned the send back with a 429. The row
  lands at `undelivered`, `failed`, or `rejected` with an RCS-specific
  `classified_error_code`.

Work the symptom map below, then match the cause to its fix. If the row is
stuck pre-queue (`queued`, `pending`), work the
[queue-side troubleshooting page](/reference/troubleshooting) instead; if it
holds at `sent` with no terminal outcome, see
[Troubleshooting: message sent but no delivery receipt](/troubleshooting/submitted-no-receipt).
This page assumes those queues are clear.

## Symptom map

Read the status and the classified error code together — the same status
word means something different on RCS than it does on SMS. Three places
read the same RCS row state: the Delivery Log channel filter
(`/messages/delivery-log?channel=rcs`, with the same `status=` and
`direction=` vocabulary as every channel), the authoritative row on
`GET /api/v1/messages/:id`, and the `message.failed` webhook payload
with `channel: "rcs"` for event-driven handling — branch on the payload's
`status` and `error` fields, not the event type alone.

| UI hint                                                                 | Most likely cause                                                                                                                                           | Where to confirm                                                                                                                                                          |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Status `failed`, `classified_error_code` = `RCS_NOT_SUPPORTED`**      | Recipient handset has no RCS capability (Apple device, older Android, RBM not enrolled)                                                                     | `GET /api/v1/messages/:id` `metadata.classified_error_code`; the pre-send probe `GET /api/v1/rcs/capability/:botId/:recipient` returns `isCapable: false`                 |
| **Status `rejected`, agent never launched or rejected at onboarding**   | Brand or agent refused by carriers — `rcs_business` trust check unverified                                                                                  | `GET /api/v1/rcs/bots/:id/quality` — `verification_status` / `carrier_statuses` map; [Brand Identity trust score](/concepts/brand-identity-trust-score)                   |
| **Status `rejected`, agent verified then refused again**                | Agent rejected after onboarding — policy takedown or quality downgrade                                                                                      | Bot's `carrier_statuses` map `GET /api/v1/rcs/bots/:id/quality` — a `rejected` or `suspended` carrier entry                                                               |
| **Status `rejected` or `failed` on rich sends only, plain text passes** | Template missing a required card/button schema field (rich card with no `fallback_url` on a `rich_link_action`, single-card carousel, unpaired suggestions) | `POST /api/v1/messages/rcs` schema — the rich-payload rules in [RCS channel page](/channels/rcs); `message.failed` webhook payload `error_message` names the schema error |
| **Status `failed` across the whole tenant, every recipient**            | Per-tenant throughput cap — sends queue behind the ceiling and land back as `429` carry-overs                                                               | The [RCS channel page rate limits](/channels/rcs#rate-limits) — the cap is per tenant, not global                                                                         |
| **Status `undelivered`, recipient is RCS-capable**                      | Carrier-side routing gap or spam filter on the destination                                                                                                  | `message.failed` webhook payload raw `error_code` / `error_message` — carrier's own wording                                                                               |

## Causes and resolutions

Work each cause once, in this order — they are sequential gates, and a
higher gate masks the lower ones.

### 1. Unregistered RCS agent — `rcs_business` not verified

RCS is a verified-sender channel. The agent must clear four gates —
brand submitted, agent created, carrier-verified, launched — before a
live send reaches a subscriber. If the agent is in draft or pending
verification, the send fails closed.

**Resolution:** work the
[RCS onboarding gates](/guides/rcs-onboarding) in order — the
[RCS channel page checklist](/channels/rcs#onboarding-brand--agent--verify--launch)
compresses them to the four decisions. A brand that was refused or
suspended blocks agent creation; fix the brand record first. Verify the
`rcs_business` surface is `verified` on the
[Brand Identity trust score](/concepts/brand-identity-trust-score) before
re-sending.

### 2. Recipient device lacks RCS support

RCS reaches Android devices with Google Messages only. An Apple device,
an older Android with no RBM enrollment, or a carrier that does not
bridge to the RBM hub short-circuits the send with `RCS_NOT_SUPPORTED`.

**Resolution:** the pre-send capability check
`GET /api/v1/rcs/capability/:botId/:recipient` tells you whether a number
is reachable before you spend the send. When it returns `isCapable: false`
with `fallback: "sms"`, route the message down the SMS path in the same
decision. To make this automatic, enable the org-level
[cross-channel fallback chain](/channels/rcs#configure-rcs--sms-fallback)
**Primary: RCS → Fallback: SMS** — the router advances on the
`RCS_NOT_SUPPORTED` receipt without you branching per send. A reach scan
on a segment (`POST /api/v1/rcs/reach-scan`) tells you the share of a
contact pool that is RCS-capable before a campaign.

### 3. Template missing a required card/button schema field

Rich sends fail when the payload violates the RCS schema — most often a
`rich_link_action` missing its required `fallback_url`, a single-card
carousel (which renders malformed on Android — use `rich_card` for one
card), or a suggestion chip that is neither a `reply` nor an `action`.
Plain-text sends on the same agent pass while rich sends fail.

**Resolution:** fix the payload against the schema rules on the
[RCS channel page](/channels/rcs#send-an-rcs-message) — the mutually
exclusive shapes (`body` / `rich_card` / `rich_card_carousel`) and the
per-chip `reply` | `action` contract. When the
[Brand Identity trust score](/concepts/brand-identity-trust-score)
verifies the agent but rich sends still fail, re-read the send body's
schema before escalating — a schema error is deterministic, not a carrier
gate.

### 4. Agent rejected after onboarding

A launched agent can come back `rejected` or `suspended` on a carrier —
typically a policy takedown, a quality downgrade, or a carrier-side
re-review. The send fails with an RCS-specific classified error; plain
and rich sends fail alike.

**Resolution:** read the per-carrier map on
`GET /api/v1/rcs/bots/:id/quality`. A `rejected` or `suspended` entry
means the carrier revoked the agent — fix the brand/agent record and
resubmit through the
[RCS onboarding guide](/guides/rcs-onboarding) rather than resending
against the same carrier. For a staged launch across a subset of carriers
(`carrier_mccmnc`), a subscriber on a not-yet-launched carrier fails even
when the agent is fine elsewhere — check the `carrier_statuses` map before
you blame the content.

### 5. Quota / throughput — per-tenant cap turned the send back

RCS throttles outbound calls per tenant against the contracted Dotgo RBM
Hub throughput. Exceeding the cap turns the send back with a `429` and a
`retry_after` window; retries inside the window hit the same cap.

**Resolution:** the cap is a per-tenant ceiling, not a global pool.
If every send on the tenant comes back at once, queue and retry after
the `retry_after` interval rather than hammering the window — the
[RCS channel page rate limits](/channels/rcs#rate-limits) covers the
window mechanics. The operator raises the ceiling (env knobs,
`DEVOTEL_RCS_RATE_LIMIT` per `DEVOTEL_RCS_RATE_WINDOW_MS` window) to
match the contracted Dotgo throughput tier — a per-tenant adjustment,
not a code change. A higher contracted Dotgo TPS tier is the durable
fix when the ceiling is routinely reached.

## What not to do

* **Do not spam retry on a capability failure.** `RCS_NOT_SUPPORTED` is
  deterministic — the same handset fails the same way every time. Enable
  the org-level fallback chain or drop the recipient to SMS; do not
  `POST /api/v1/messages/:id/retry` against an incapable device.
* **Do not assume RCS ≈ SMS.** The verified-sender chain (brand → agent →
  verify → launch) and the per-recipient capability probe are RCS's own
  gates, absent from SMS. Treating RCS as "SMS with a logo" skips both.
* **Do not treat a rate-limit 429 as a carrier failure.** The per-tenant
  cap is your own contracted ceiling — queue and retry after
  `retry_after`, and raise it with the operator when the ceiling is
  routinely reached. Opening a carrier ticket on a self-inflicted cap
  wastes the trace.

## When to escalate

Open a support ticket when one of these holds:

* The agent shows `verified` and `launched` on the target carrier, the
  recipient's capability probe returns `isCapable: true`, the payload
  matches the schema, and the row still terminates with an unexpected
  `classified_error_code` the cause table does not explain.
* A fleet of carrier-side failures on one destination that persists after
  a launched agent and a clean capability probe — the delivery log
  `channel=rcs` filter plus the
  [deliverability analytics](/api-reference/endpoints/analytics) top-N
  failure-reason breakdown is the aggregate view to quote.
* You need the provider-side trace against the RBM aggregator.

Include all three so support can pull the RBM pipeline trace without a
back-and-forth:

* Your **tenant ID** (dashboard under Settings → Organization, or
  `organizationId` on `GET /api/v1/me`).
* One **message ID** (`msg_…`) of a representative failed RCS row.
* The **RCS-specific `classified_error_code`** off that row — read it
  from `metadata.classified_error_code` on `GET /api/v1/messages/:id`,
  not the display label.

## See also

* [RCS channel page](/channels/rcs) — the concept-and-reference surface
  (capability check, fallback chain, rate limits, onboarding gates)
* [RCS onboarding guide](/guides/rcs-onboarding) — the four-gate
  walkthrough with every endpoint and the status tables
* [Cross-channel fallback](/concepts/cross-channel-fallback) — the
  org-level chain that turns a `RCS_NOT_SUPPORTED` receipt into an SMS
* [Multi-channel DLR fallback](/concepts/multi-channel-dlr-fallback) —
  the terminal-DLR plane vs. the capability plane where RCS fails
* [Troubleshooting: message undelivered or failed](/troubleshooting/message-undelivered-failed)
  — the generic decoder (all channels); this page covers the RCS slice
* [Brand Identity trust score](/concepts/brand-identity-trust-score) —
  the `rcs_business` verified-sender check an RCS agent must clear
