Order dispatch notifications workflow
A dispatch pipeline ships one transactional message per fulfillment stage — order confirmation, shipped, out for delivery, delivered, plus the exception branch. This guide builds that pipeline as one loop: emit the stage event, send a templated message with the stage tagged on it, and you can then read the whole lineage per order in the order-notifications ledger instead of joining delivery logs yourself. The ledger page is the operator’s reading surface; this page is the developer’s build recipe. The pairing below is the tested shape — your commerce system, a per-stage templated send, a delivery trail, and the alert rules that watch the series.1. Model the fulfillment stages
Fix the stage vocabulary first, because every later join (ledger groups, alert rule filters) reads the same strings:
Put every event exact names in one place (a constants module your emitters import) — the ledger groups the series by whatever string you stamp, and a
order.shiping typo becomes a silent second series you cannot merge back.
Two design rules on the stage list:
order.exceptionis one bucket. A delayed delivery and a failed attempt are both expected traffic. Stamp them all onorder.exceptionand carry the sub-reason (delayed,failed_attempt,refunded) as your ownmetadatakey — one stage to alert on, sub-reasons still recoverable per order.- Stages are event names, not message text. The body copy for each stage is a template you maintain separately; the stage tag is the join key.
2. Emit each stage event
Two emitters feed the same ledger — pick whichever owns the stage transition:- The commerce spine. If your storefront runs on the commerce checkout spine, its state machine already emits the cart/checkout transitions (
paid,fulfilled), and your flow listens for the transition and fires the message below. The stage tag rides on the send either way. - Direct fulfillment hooks. Your own order-management system POSTs
POST /api/v1/messages/sms(or the matching per-channel route) on each stage change. The rest of this guide assumes this shape; the tag/ledger/DLR steps are identical for spine emitters.
3. Send a templated message with the stage tagged
Branch the stage event into a templated send and stamp the stage plus your own correlation key onmetadata. The ledger groups by the stage; your DLR consumer (step 5) joins on the order id. Both travel on the message body’s metadata map and echo back on the delivery webhooks:
202 Accepted queues the send; the terminal delivered / failed state arrives on the webhook.
4. Choose the channel with SMS↔WhatsApp fallback
Order notifications are reachability traffic, not engagement traffic — a delivered confirmation matters more than the richer channel. The per-messagecascade_policy on smart-send arms a fallback chain the terminal-DLR hook consumes, so an undelivered WhatsApp hop falls to SMS instead of dying:
sms first where that is the recipient’s known channel, whatsapp first where you hold a WhatsApp opt-in — the resolver stamps the executable chain onto the message metadata either way, and the stage tag rides through every hop. The full rule set (channel eligibility, ordering, the auto_fallback: false opt-out) is on the fallback chains page.
5. Subscribe to delivery webhooks, join onto the stage badge
Subscribe to the message-event webhooks (message.sent, message.delivered, message.read where the channel returns it, message.failed) and verify signatures — the per-channel vocabulary and HMAC checks are on the delivery webhooks guide. On each event, your consumer:
- Reads the echoed
metadata.stage+metadata.order_id. - Marks that stage’s send as
sent/delivered/read/failedon your order record. - Accepts a correcting event after a terminal one — a WhatsApp
undeliveredthat later delivers re-firesmessage.delivered.
6. Read anomalies: missing stage series and failure spikes
Open Insights → Order notifications ledger with the per-stage grouping. Two anomaly shapes matter:- Missing stage series. A stage that silently stopped firing (confirmation volume drops to zero) renders as a missing row on its series, not a dip — a volume dip still shows the stage. Route your emitter health this way: a broken webhook subscription kills
order.shippedwhileorder.confirmationkeeps flowing. - Failure spikes. Filter on
status=failed(dispatch/configuration faults) versusstatus=undelivered(recipient-side hygiene) — the rejection-code breakdown tells you which one spiked. A suddenfailedbump on one stage usually marks a template edit the channel rejected.
7. Attach usage-anomaly alert rules
Guard the series itself, not just the aggregate. Wire org-scoped rules on the usage & delivery anomaly alert rules surface:- A delivery-rate rule (
sms_delivery_rate, guards a drop) catches the carrier-side failure spike — with the stage tag on the ledger you can confirm the drop localizes to one stage before you dig. - A volume rule (
outbound_message_volume, guards a surge) catches a duplicate-emitter regression — step 2’s “do not wire both” bug lands here.
8. Keep transactional classification clean
A notification is transactional because its content is strictly about the order. The moment a stage send carries promotional copy (“while you’re here — 20% off accessories”), the carrier and content-moderation layers reclassify the flow as marketing, and it stops reading as transactional traffic in the ledger. Three rules keep the class clean:- Template bodies reference only the order and its fulfillment state — no upsell, no cross-sell, no review requests.
- Keep each stage’s template scoped to that stage’s event — the exception branch alerts on the problem, it does not pitch a replacement product.
- Marketing goes on the campaign rails with their own quiet hours and unsubscribe handling — never appended to a stage send.
See also
- Order notifications ledger — the reading surface this pipeline feeds
- Fallback chains — all three fallback surfaces and when to use each
- Smart-send cascade policy — the per-message chain the recipe above arms
- Wire delivery webhooks per channel — the event vocabulary, signatures, and sandbox tester
- Usage & delivery anomaly alert rules — the org-scoped rules you attach in step 7
- Commerce checkout spine — the alternative emitter for the same ledger