On sequencing: register first, and it’s cheaper than people expect. The scary numbers floating around are for Standard brands with secondary vetting. For a single-location business texting missed callers, you’re looking at roughly $4-5 one-time for a Low Volume Standard or Sole Proprietor brand, a $15 campaign vetting fee, and then $1.50-$10/month for the campaign depending on use case. Call it about $20 up front and a couple bucks a month. Worth confirming current numbers in the Trust Hub before you quote it to anyone, since TCR adjusts them.
The reason it has to come first is that there’s no way to test around it. Unregistered traffic gets filtered at the carrier, so Twilio returns a clean sent, your Sheet logs a success, and the message just never arrives. You’d be debugging your workflow for a week over a problem that isn’t in your workflow. Sole Proprietor caps you at one number and one campaign, which is usually fine for this use case, but it needs OTP verification on a personal mobile and takes a few days.
If you want to skip 10DLC entirely for a demo or a pilot, a toll-free number with toll-free verification is free to submit and has no monthly campaign fee. Different caller ID feel, so it’s not right for every business, but it’s a legitimate path while a 10DLC brand is pending.
On the delivery status pattern — yes, I’ve built it, and the shape that holds up is treating the send and the outcome as two separate executions.
Set statusCallback on the send (easiest at the Messaging Service level so every message inherits it) pointing at a second n8n webhook. The response to your send only tells you Twilio accepted the request; it’s queued or accepted and it means nothing about delivery. Log the row at that point with the MessageSid as your key and status queued, and stop there. No “sent” in the sheet yet.
Twilio then POSTs to your callback as the message moves: sending, sent, delivered, undelivered, failed. Second workflow receives those and upserts on MessageSid. Two things to guard:
Callbacks can arrive out of order. Rank the statuses and only write if the incoming rank is higher than what’s stored, or a late sent will overwrite a delivered.
Some messages never reach a terminal state. Landlines and dead numbers often sit at sent forever. So run a sweeper on a schedule — anything non-terminal after 15 or 20 minutes gets marked unknown and escalated the same way a failure would.
The error codes worth branching on are 30003, 30005 and 30006 for unreachable or non-mobile destinations, and 30007 for carrier filtering. 30007 climbing is your 10DLC canary. Landline hits should not retry as SMS; route those to a “call them back” queue instead, since retrying is just burning money on a number that physically can’t receive it.
One upstream option that kills a chunk of this: Twilio Lookup with line_type_intelligence before you send. Roughly half a cent per lookup, tells you mobile vs landline vs VoIP, and lets you branch before spending a message and a carrier fee on something undeliverable. Doesn’t replace the callback, but it cleans up the obvious cases.