Skip to main content

Message envelope model

The message envelope is the channel-agnostic declaration a single send carries through the router. Where Pricing and rate resolution embeds the envelope inside the pricing narrative, this page defines it on its own: read it when you meet channel_chain or costAware on the omnichannel send surfaces and need the model they belong to.

The envelope

One envelope declares everything the router needs for a single send attempt:
  • One recipientto, the destination the envelope delivers.
  • One content bagcontent, a universal text body plus optional per-channel rich variants (a WhatsApp template, an RCS rich body, MMS media, and so on).
  • An ordered channel_chain — your fallback preference for this send, in the order you declared it.
The router walks that chain top-down. The first channel with both a registered provider and a renderable content variant wins the walk. Two edge rules fall out of that:
  • Most-specific-wins on content. A channel-specific variant beats the universal text body on its channel’s hop; absent a variant, the universal body renders. A channel that can render neither is skipped silently and the walk continues rather than failing the send.
  • Transient failure falls through. A provider-level transient failure (a retryable error, a 5xx, a timeout) advances the walk to the next declared channel. The channel you lose on is recorded in the attempt audit; the chain only ends when every declared channel is exhausted.
The envelope’s declared channel is also what pricing keys on — whichever channel wins the walk determines which rate-card ladder and which per-operator rules resolve its price (see the final section).

Cost-aware re-sequencing

Declaring costAware: true on the envelope re-ranks your chain cheapest-first before the walk starts. The preference set is yours; the rate card only re-sequences it — channels are never added, removed, or trimmed, only re-ordered. Per channel, the resolver reads the per-send cost override you supplied with the envelope when one exists, and the platform rate card otherwise. A channel with no published price is never assumed cheapest; equal-price channels keep your declared order, so the re-sequenced chain is always a stable re-ordering of what you declared. Re-sequencing happens once, at declaration time: after sorting, the walk follows the same first-provider-and-renderable-variant rule as an unsorted chain.

How the envelope differs from cascade and notify fallback

Orbit has three fallback planes, and all of them are escalation-by-failure — a brand-new send dispatched after the prior one failed:
  • The org-level cross-channel fallback chain advances on reachability and capability failures.
  • The cascade policy (org default or per-send cascade field) escalates on a terminal delivery receipt and binds the hops under one message_group_id.
  • The notify waterfall chases one recipient through bindings with per-hop and cumulative cost bounds.
The envelope is routing-by-choice on one attempt: the whole preference chain is declared up front and the router routes within it on the single send, rather than reacting to a failure signal from a previous send. No DLR-driven escalation ever fires, no group id is stamped, and no organization-level configuration participates. Choose between them by what drives the move: declare an envelope when you want the channel picked by preference (or price) inside one send; arm a cascade or the org chain when you want a failed send to re-try on the next channel; compose a notify waterfall when you want per-recipient escalation with explicit cost bounds.

The per-hop price-resolution contract

Every hop on the walk funnels through the same resolver pipeline a direct send on that channel uses — the precedence from Pricing and rate resolution runs identically per hop: per-operator override verbatim, then your organization’s markup, then the platform-default markup, and Contact sales when no published rate exists. One consequence: a fall-through hop is priced on the channel it lands on, so a chain declared RCS → SMS attributes an SMS hop as an SMS charge, never an RCS one. The quantity multiplier is channel-shaped and fixed:
  • SMS and MMS price per segment — the per-segment rate multiplied by the segment count of the rendered body.
  • Every other channel prices one unit per message.
The winning hop’s declaration is what the wallet debits, and the ledger row carries that attribution back, so the re-sequencing costAware performed is fully traceable per hop.

What an envelope is NOT

  • Not a cascade group. A cascade stamps one message_group_id on the primary and every fallback hop so the run reads back as one logical message. An envelope is a single declaration on one attempt — it groups to nothing.
  • Not a notify waterfall. A waterfall hoists the chain per recipient in one notify call and screens with max_price / max_total_price bounds. An envelope declares the chain on the send itself; the cost bounds do not apply to it, and costAware merely re-orders rather than bounds.
  • Not the org-fallback chain. The organization-level settings.cross_channel_fallback configuration arms every send uniformly. An envelope carries no organization-level configuration — the chain is declared per send and applies to that send only.