Skip to main content

RCS capability check and SMS fallback

Every RCS send answers one question first: can this recipient’s handset receive RCS from this bot right now? Orbit answers it with a capability probe, either served from a 24-hour cache or asked live of the Dotgo RBM hub. The probe verdict drives everything downstream: a positive verdict delivers rich content; a negative verdict either short-circuits the send as RCS_NOT_SUPPORTED or — when your organization has an RCS → SMS fallback chain configured — hands the message body to SMS instead. This page owns that decision plane: what the probe returns, how the fallback chain engages, how the Dotgo bridge reports delivery, and which receipt code a fallback reports. The channel how-to (send shapes, template CRUD, rate limits) lives on RCS; this page is the concept model those endpoints follow.

What it is

The capability probe is a pair-check — bot × recipient — because RCS capability is per-handset and per-bot, not per-number. Before launch the answer influences onboarding (a tester device); after launch it gates every send:
  • isCapable: true — the RCS attempt proceeds and the message delivers as rich content (rich card, carousel, suggestion chips, commerce, or plain text with chips).
  • isCapable: false — the payload carries fallback: "sms", an explicit recommendation to route the message down the SMS path in the same decision rather than spending an RCS send that will fail closed.
The fallback recommendation is the only fallback shape the probe returns. Dotgo’s older URCS (Universal RCS) fallback — delivering a degraded RCS shape when full capability is absent — was deprecated by Dotgo in April 2026 and removed from Orbit’s capability result; the recommendation is now always SMS. Treat a false verdict as “route to SMS,” full stop.

The capability check lifecycle

Probe endpoint: GET /api/v1/rcs/capability/:botId/:phone (recipient in E.164). Response fields:
  • isCapable — boolean verdict; false adds fallback: "sms".
  • features — the raw RBM capability tokens the handset advertised.
  • universalProfileVersion — negotiated GSMA Universal Profile version. 3.0 is the floor for rich deep-links (rich_link_action) and MLS encryption.
  • featureFlags.mlsSupported / featureFlags.richLinkSupported — MLS and rich deep-link support. When richLinkSupported is false, the recipient opens the action’s fallback_url, which is why the template and send contracts both require an HTTPS fallback URL on every rich link.
Cache and inline-check behavior:
  • Positive verdicts are cached for 24 hours, so a bulk pre-send sweep is cheap; uncached misses cost one Dotgo probe each.
  • Orbit also runs the same check inline on every RCS send and short-circuits with RCS_NOT_SUPPORTED when the recipient is not capable. Calling the probe yourself is for pre-campaign planning and the reach scan, not a send-path requirement.
  • A positive UP3.0 observation is also recorded against the bot itself, so the settings dashboard can show “this bot has negotiated UP3.0” without a separate probe. One recipient on a 2.x handset never downgrades a bot that proved UP3.0 with another recipient.

Planning: reach scan and quality

The reach scan (POST /api/v1/rcs/reach-scan) runs the same probe against a sampled set of a segment’s contact phone numbers and returns the capable/not-capable split — the number you need to decide between an RCS-only send and an RCS-plus-SMS-fallback split before a campaign. It fans out billable capability lookups and reads contact phone numbers, so it sits behind its own scope. The quality surface (GET /api/v1/rcs/bots/:id/quality and /analytics/*) then reports per-carrier launch status, per-template delivery/read/click rates, and per-day volume — see Reach and quality for the endpoint table.

Tester devices and the verification path

Before a bot launches, it can only message registered tester devices — the capability check is how you pick them:
  • POST /api/v1/rcs/bots/:id/devices with { "phone": "+14155552671" } registers a handset directly; GET lists them, DELETE removes them.
  • POST /api/v1/rcs/bots/:id/tester-invite with { phone } delivers an on-device invite; once the recipient taps accept, the unlaunched bot can message that number.
  • The test account flow (/rcs/test-account/*) chains capability probe → tester registration → invite → OTP verification against Devotel’s shared bot, so a handset with no RCS support is rejected rather than registered. It is a demo surface; production sends need your own approved brand and launched bot.

Fallback: when the chain advances to SMS

RCS → SMS fallback is org-level, not per-request. The POST /messages/rcs request body accepts no fallback field (one is ignored); the chain lives on the organization under settings.cross_channel_fallback, configured once from Settings → Channels → Cross-Channel Fallback or over GET / PUT /api/v1/settings/channels-fallback. With a chain configured, a capability-check failure behaves exactly like a manual SMS routing decision: the RCS attempt short-circuits with RCS_NOT_SUPPORTED, and the router hands the same message body to the next channel. Without a chain, a not-capable send fails closed with an RCS_NOT_SUPPORTED delivery receipt. Two tenant-owned guards apply on the SMS hop:
  • Compliance re-check. Reaching SMS does not inherit the RCS opt-in. Orbit re-runs the SMS opt-out and DNC check against the recipient before delivering over SMS; a contact who opted out of SMS is suppressed.
  • Billing on the landed channel. The SMS hop prices and charges through the standard SMS billing path — expect fallback usage to show up as ordinary SMS spend.
Those guards are the tenant-configurable part of the chain; the trigger set (capability failure, provider exhaustion, recipient unreachable) is a closed model. The full chain model — precedence against the per-request DLR fallback plane and the campaign channels[] ladder — is on Cross-channel fallback; the ladder’s per-hop trigger/window semantics are covered there, not duplicated here.

The Dotgo bridge and the DLR plane

Dotgo is Orbit’s single RCS bridge: bot registration, template approval, carrier launch, and delivery all transit the Dotgo RBM hub. That bridge shape matters to the fallback model in two ways. Tenant resolution on receipts. Delivery receipts (DLRs) arrive at Orbit’s Dotgo webhook keyed by the bot’s provider id. Orbit resolves the owning tenant from the bot id via a reverse index, so per-tenant bots route their receipts directly. For sends through Devotel’s shared test bot — the test-account demo path — the payload carries no tenant, so Orbit falls back to resolving the tenant from the message id (cached first, then scanned across tenants). A not-capable verdict therefore does not produce a dangling or misattributed receipt: it either lands as RCS_NOT_SUPPORTED on the sending tenant, or advances to SMS where the SMS channel’s own DLR stream reports the hop. Each fallback hop is a new message attempt that surfaces in delivery reporting as its own send — not a silent rewrite. Fallback is a send-time decision, not a carrier hint. Because the Dotgo bridge carries no SMS path, falling back means leaving the RBM hub entirely and entering the SMS channel’s provider routing. The chain does this at the Orbit routing layer; Dotgo only ever sees the RCS attempt.

Message shapes the verdict gates

A positive capability verdict unlocks the full RCS send shapes; a negative one should route the same content to SMS as plain text:
  • Rich cards and carousels — titled media + copy + actions; the fallback_url on each rich link action is the degrade path for pre-UP3.0 handsets.
  • Suggestion chips — replies and actions; a fallback_sms_body-style decision keeps the text reachable when chips cannot render.
  • Commerce — product catalog + checkout rendered as RCS rich content (rcs-catalog-commerce), the RCS analogue of the WhatsApp commerce funnel.
  • Media planes — where rich media actually transits; Media planes covers the SFU-versus-carrier-plane split for voice/video, and the RCS media URL contract follows the same rule: only the advertised capability decides whether the rich plane engages.
  • RCS channel page — the how-to: send shapes, template CRUD, rate limits, onboarding gates.
  • Cross-channel fallback — the general org-level chain model and its precedence against the DLR plane.
  • Message cascade groups — sprawl control: one logical message id across every hop of a fallback chain, so RCS → SMS retries read as one message, not two.
  • Multi-channel DLR fallback — the per-request DLR plane the org chain resolves ahead of.