Skip to main content

The five fallback planes

Orbit has five independent planes that move a message from one channel to the next when a send doesn’t land. Each plane resolves a different failure class, at a different stage of the send, with a different owner (org policy, per-send field, notify request, or campaign graph). This page names all five, orders them as a choice, states what every plane shares, and walks one recipient through each — so the owner pages can go deep on their own plane without re-answering “which plane do I use.” The five planes:
  1. Org capability chain — an org-configured ordered chain (e.g. RCS → SMS) the router advances through when the current channel can’t carry the recipient at all. Owner page: Cross-channel fallback.
  2. Per-request DLR fallback — an opt-in per send (fallback_channels + auto_fallback) that re-sends on the next channel only after a terminal delivery receipt arrives. Owner page: Fallback on terminal DLR.
  3. Message-level cascade policy — an org default cascade plus a typed per-send cascade field that stamps the chain for you and binds every hop under one message_group_id. Owner page: Cascade failover policy and groups.
  4. Notify waterfall cost bounds — a per-recipient mode: "waterfall" chain on POST /notify with a per-hop max_price and a cumulative max_total_price cap. Owner page: Notify cascade cost model.
  5. Campaign channels[] ladder — an ordered per-campaign channel ladder with engagement-based triggers (failed, no_delivery, no_engagement) and timed windows (fallback_after_seconds). Owner page: Cross-channel fallback (campaign-level variant) and the campaign journey builder guide.

Precedence and when each plane fires

The planes don’t fight over the same send — each resolves in a fixed order, and each fires only at its own stage: Three precedence rules matter:
  • Capability short-circuits before a DLR can exist. The chain’s trigger (the recipient can’t use this channel at all) resolves mid-send, before the carrier returns a receipt; the DLR hook’s trigger (the carrier said no) can only arise after the send was accepted. So the org chain always resolves first, and the DLR plane never fires on that attempt.
  • The DLR plane’s chain source has its own precedence. Inside Cascade failover policy and groups: raw metadata.fallback_channels beats the typed cascade field, which beats the org policy. Sources are never merged — a caller’s own chain is never silently over-filed by the org default.
  • The notify waterfall and the campaign ladder are self-contained. The waterfall is one POST /notify call that bounds its own cost; the ladder is a campaign-scoped graph evaluated per enrollment. Each owns its own escalation decisions and neither defers to the org chain.

Invariants across planes

Whatever plane owns a hop, the hop is a first-class new send on the next channel — not a silent rewrite of the failing attempt. Every hop re-enters the canonical send pipeline, so the same gates apply at every hop of every plane:
  • Sender resolution — the hop resolves its own sender for the new channel.
  • Consent and opt-out gates — the recipient’s SMS opt-out blocks an SMS hop even when the recipient accepted RCS on the primary; the TCPA re-check runs on every hop into SMS.
  • Quiet hours — send-gating rules apply per hop, not per cascade.
  • Per-segment billing — each hop prices and charges on the channel it lands on; there is no separate fallback or cascade fee class.
This is why a hop never “inherits” anything from the failing attempt beyond the recipient and the body.

The channel-closure rule

The cascade-eligible channel set is closed: sms, whatsapp, rcs, viber, telegram, messenger, instagram, line, apple_messages. Voice, fax, email, and push are never cascade-eligible — their billing and consent semantics differ too much for an automatic hop (an undelivered email turning into SMS is a compliance surface, not a convenience). Validation rejects anything outside the set with a 422 naming each invalid field. The same closure applies to the org capability chain: fallback applies to outbound messaging only, never to voice calls or email sends.

Which plane to choose

Pick by goal, not by channel:

Worked example: one recipient through each plane

Same recipient (+15551234567), same body (“Your appointment is tomorrow at 10:30.”), traced through all five planes:
  • Org capability chain. You configured RCS → SMS once on the org. The RCS capability check returns not_capable, so the router advances immediately — before any receipt exists — and the SMS hop re-enters the pipeline (sender resolution, TCPA re-check, quiet hours) then bills as a normal SMS. The DLR plane never sees this send.
  • Per-request DLR fallback. You sent RCS with fallback_channels: ["sms"]. The send was accepted; twenty seconds later the carrier returns undelivered. The fallback hook stamps fallback_attempted_at atomically and dispatches one new SMS send carrying fallback_of: <your rcs message id>. Carrier replays of the DLR can’t re-send — the stamp is already set.
  • Message cascade policy. An org default (channels: ["whatsapp", "sms"]) arms every send; a per-send cascade: { "channels": ["sms"], "fallback_window_seconds": 3600 } overrides it for one send; either stamps one message_group_id. Read the finished run back at GET /api/v1/messages/cascade/groups/<group_id> — one logical message, N legs, fallback_of and fallback_reason on every hop.
  • Notify waterfall. POST /notify with mode: "waterfall" and rcs → whatsapp → sms, a per-hop max_price: 0.02, and a cumulative max_total_price: 0.05. RCS prices at 0.03 over its per-hop bound, so it’s skipped; the cumulative cap trims the tail before arming; the SMS hop fires and bills under both caps. The response’s dropped_for_cost_cap names what never fired.
  • Campaign ladder. An omnichannel campaign runs channels: ["whatsapp", "sms"] with fallback_on: "no_engagement" and fallback_after_seconds: 86400. WhatsApp delivers; after 24 hours with no engagement event, the ladder advances and SMS fires on a timed window — an engagement-based trigger the org chain’s capability triggers can’t express.
Each plane owned the send at a different moment: the org chain before any DLR existed, the DLR hook after the carrier answered, the cascade policy at send-stamp time, the notify waterfall at request time, the campaign ladder at the engagement-window boundary.