Skip to main content

Multi-channel Notify

The Messages → Multi-channel notify page is the one-shot, mixed-channel send surface: it composes a recipient list where every entry picks its own channel, writes one shared message, and dispatches everything in a single POST /api/v1/notify call. It mirrors Twilio Notify — a heterogeneous binding list of (channel, address) pairs plus one shared payload, with delivery resolved per binding. Eight channels are offered in the composer: RCS, WhatsApp, SMS, email, push, Viber, Telegram, and Messenger. The address is whatever the channel routes on — E.164 phone for SMS/WhatsApp/RCS/Viber, an email address, a device token for push, or a handle for Telegram/Messenger. Every recipient runs through the same delivery pipeline as a single send on that channel: opt-out lists, quota, sender resolution, and compliance checks all apply.

When to use Notify vs a flow vs a campaign

Notify is the “one message, mixed list, right now” tool. A campaign is the governed blast with analytics; a flow is the conversation. If every recipient is on SMS, the simpler surface is Batch SMS. If the same recipient should be chased across channels only when the first one fails, that is also Notify — in cascade mode, covered below.

Role requirements

The page is gated to owner, admin, and developer roles. Members and viewers do not see the page and cannot open the composer — the same role guard that protects other dispatch surfaces. If the page is missing from your dashboard, ask an owner or admin for one of those roles.

Composing a send

  1. Open Messages → Multi-channel notify and click Multi-channel notify to open the composer.
  2. Pick a Delivery strategyFan-out (the default, Twilio Notify parity) or Cascade (failover). The next section explains the difference.
  3. Write the Message body. It is applied to every recipient. An optional Sender overrides the default sender resolution; leave it blank and the router resolves a per-channel sender for you.
  4. Build the recipient list: one row per recipient, each with a channel select and an address. Use Add recipient for more rows; the composer accepts up to 10,000 bindings (the same cap Twilio Notify enforces per call).
  5. Send and read the per-row result — every recipient gets its own queued/failed chip.
“Twilio Notify parity” means the call semantics match Twilio’s Notify API: a single request carries a mixed binding list and one shared payload, each binding is delivered on its own channel, and per-binding failures never abort the rest of the batch. Orbit adds the cascade strategy and cost bounds on top of that baseline. All page-level checks are advisory: a row with an empty address is dropped before dispatch, and a body left blank blocks the send with a toast. Address-shape validation happens in the delivery pipeline per channel — a bad address comes back as that row’s per-binding error, not as a form error.

Channel selection and the fallback cascade

The delivery strategy picker maps onto the mode field of POST /api/v1/notify:
  • Fan-out (default). Every row fires immediately, in parallel — one delivery attempt per row, no retry across channels. Use it for announcements where one channel per recipient is the intent.
  • Cascade (failover). Rows that share an address merge into one per-recipient fallback chain, in row order (richest → cheapest, e.g. RCS → WhatsApp → SMS). Only the first hop fires; the next hop fires only if the active one comes back undelivered inside the escalation window (30 seconds to 24 hours — blank uses the 24-hour default).
Cascade mode enforces at least two channels per recipient; a single-hop recipient gets an amber “Add another channel for failover” callout and blocks the send until fixed. The full mechanism — chain grouping, the escalation window, cost bounds per hop and per cascade — is covered in Cascade (waterfall) fallback chains in the notify composer, and the pricing model behind the caps in Notify cascade cost model.

Delivery tracking and retries

After dispatch the dialog renders the per-row result:
  • 200 / all queued — every row carries a green Queued chip. In cascade mode that means the first hop per recipient is armed; the rest escalate only on undelivered receipts.
  • 207 Multi-Status — some rows failed. Each failed row shows a Failed chip with a human-readable reason (opt-out, quota, bad address); hover the row for the machine-readable error code. Branch per row — never re-send the whole batch, or the queued rows go out twice.
  • 422 / nothing queued — no row was accepted. Fix the body or addresses and resend; nothing went out, so a full retry is safe.
The composer result is the synchronous queue verdict only. A queued row is not delivered yet — terminal delivery arrives through the usual per-channel delivery events (delivery receipts for SMS/WhatsApp/RCS, provider callbacks for email and push). For a cascade, resolve the hop chain, per-hop cost, and escalation flag by notify id with Track a cascade; the page hosts that lookup panel below the composer. A retry that makes sense is rebuilding the failed rows as a new send — dispatch itself has no automatic cross-channel retry outside cascade mode.

Worked example — a 3-channel notify send

A clinic reminds tomorrow’s patients about their appointments. The patient list is mixed: some patients prefer WhatsApp, one only has email, and one high-priority patient should be cascaded across three channels until one delivers.
  1. Open the composer. Messages → Multi-channel notifyMulti-channel notify. Keep the strategy on Fan-out first.
  2. Write the body: “Reminder: your appointment at CareClinic is 10:30 AM tomorrow. Reply to reschedule.” Leave Sender blank — WhatsApp and email resolve their own senders.
  3. Add three rows: WhatsApp → +14155552671, SMS → +14155559876, Email → patient@example.com. Click Send notification.
  4. Read the result. Two rows show Queued, email shows Failed with the reason “Recipient opted out of email sends.” The total/queued/failed strip reads 3 / 2 / 1.
  5. Recover the failed row. Re-open the composer, switch the strategy to Cascade, and give the high-priority patient a chain: three rows with the same address +14155550001 on RCS, WhatsApp, and SMS, plus an Escalation window of 300 seconds. The chain preview under the list reads RCS → WHATSAPP → SMS; click Start cascade.
  6. Track it. Only the RCS hop fires now. Copy the notify id from the result into the Track a cascade panel on the page: it shows the active hop, the armed tail, and the escalation flag once a DLR moves the chain forward.
The mixed fan-out handled the bulk; the cascade handled the one patient where delivery matters more than channel cost — both from the same composer.

See also