Skip to main content
Transactional SMS is every message triggered by a user action: booking confirmations, shipping updates, ride ETAs, appointment reminders, payment receipts. Unlike marketing SMS, users expect them — and get mad when they don’t arrive.

The mindset

Timely or worthless

A “your ride arrives in 3 min” SMS 10 minutes late is worse than no message at all. Send fast or don’t send.

One segment, every time

Keep bodies ≤ 160 GSM-7 chars. Two segments is 2x the cost for zero added value.

Include the action

“Ride arriving” ❌ · “Chidi arrives at Gate 2 in 3 min in an Hiace (ABC 123 XY)” ✅

Never rely on SMS alone

Pair with push notification + in-app state. SMS is a fallback + confirmation, not the primary UI.

Patterns

Booking confirmation

Template body:

Status change

Fire on every state transition: assigned → en-route → arriving → completed. Dedupe with an idempotency key so a webhook retry doesn’t double-send:

Appointment reminder

Scheduled sends are perfect for reminders:

Delivery receipt

Things to avoid

Short URLs get flagged as spam. Use a branded redirect domain (shut.ng/t/…) and keep the path tight.
Batch updates (“your status changed 3 times in the last minute”) into one message if the transitions happen fast. Users read the most recent anyway.
“From: 1234” looks like spam. From: SHUTTLERS is recognizable.
Webhooks have a lag. Drive the UI from your own order state + push notifications. Treat sms.delivered as confirmation that the SMS got through, not that the user acted.

Deliverability hygiene

For transactional SMS at scale (>100k/month), do these quarterly:
  1. Review bounces. Run GET /v1/sms?status=failed&limit=200 — look for clusters by carrier, by time window, by number format.
  2. Clean stale numbers. If you’ve failed to deliver to a number 5 times in a row, take it off your list.
  3. Monitor carrier breakdown. GET /v1/sms/analytics/carriers — if one MNO suddenly drops delivery rate, escalate to us — we can re-route via Termii or file a trouble ticket.