Register your interest: Tag @Cody, get an agent
BlogEngineering

Twilio and CodeWords: messaging that stays compliant

Consent, opt-out handling, and delivery reporting. Why the regulatory layer is the hard part of SMS automation rather than sending, and what to build before you send anything.

Osman RamadanOsman Ramadan11 min read

Summarize with AI

Twilio and CodeWords: messaging that stays compliant
On this page

Sending a message through Twilio is one API call. That simplicity is misleading, because the difficulty in automated messaging is not sending. It is everything around sending: whether this person agreed to receive it, whether they have since asked you to stop, whether the number is registered for the kind of traffic you are putting through it, and whether anyone would know if messages silently stopped arriving.

Getting those wrong carries consequences beyond an unhappy recipient. Carriers filter traffic, regulators impose penalties, and a number with a poor reputation stops delivering for everybody using it.

What we'll cover

Every other decision here depends on getting this right, and it is the part most likely to be treated as a detail.

Record consent with its evidence. Not just that somebody agreed, but when, through what, and to what. "They gave us their number" is not consent to send marketing.

Transactional and marketing are different. A delivery notification for an order somebody placed rests on a different basis from a promotional message. Conflating them in one automation means the stricter rules apply to everything, or you breach them.

Opt-out must work everywhere, immediately. Twilio handles standard opt-out keywords on its own for many configurations, and your systems still need to know, because an opt-out that stops SMS while your CRM keeps the person on a list will be violated by the next automation somebody builds.

Check consent at send time, not at list-build time. The gap between assembling a list and sending it is a gap in which people opt out.

Keep the record. If somebody complains, the answer to "why did you message them" should be retrievable rather than reconstructed. That record is also what protects you.

What the Twilio API reaches

Messages can be sent and their status read, including the delivery states that matter for monitoring.

Status callbacks report what happened to each message — queued, sent, delivered, undelivered, failed — asynchronously, which is how you find out delivery is failing.

Incoming messages arrive by webhook, which is how opt-outs, replies, and conversations reach your systems.

Phone numbers can be listed and configured, including which webhook handles their incoming traffic.

Messaging services group numbers and handle sender selection, sticky sender behaviour, and opt-out management centrally, which is worth using rather than managing numbers individually.

Verify handles one-time passcodes as a managed service, which is safer than building the same thing yourself.

Lookup validates numbers and reports line type, which prevents sending SMS to landlines and catches typos before they cost you.

Connecting it to CodeWords

CodeWords connects to more than 3,000 integrations, and the connection is made once and reused.

  1. Open CodeWords and start a new automation.
  2. Describe what should happen in plain language to Cody, the automation builder: the trigger, the message, and explicitly what consent basis it relies on.
  3. Authorize the connection with your Twilio credentials, using a scoped API key rather than the account token.
  4. Describe the exceptions: a number that fails lookup, a recipient who has opted out, a message that fails delivery.
  5. Test against numbers you control, in a test messaging service, before anything reaches a customer.

You describe the outcome; Cody builds it, connects it, and deploys it. The free plan covers light use, with Pro at $39 per month and Business at $100 per month as usage grows; details are on the pricing page.

Seven automations worth building

Opt-out propagation. An inbound stop message reflected immediately in your CRM, your email platform, and anywhere else holding that contact. Build this first, before anything that sends.

Transactional notifications. Order confirmations, appointment reminders, delivery updates. Clear consent basis, genuinely useful, and the category where SMS earns its cost.

Number validation at capture. Check numbers when they are collected rather than when you send, so the customer can correct a typo while they are still there.

Delivery monitoring. Track status callbacks, alert when the undelivered rate for a number or a route rises, because silent delivery failure is the characteristic way SMS breaks.

Two-way conversation routing. Inbound replies classified and routed to whoever should answer, rather than arriving somewhere nobody watches.

Consent audit reporting. Contacts you hold numbers for with no recorded consent basis, reported for cleanup. Most lists of any age have these.

Spend and volume reporting. Messages sent by type and destination with cost, since international SMS pricing varies enough to produce genuine surprises.

Delivery, which fails silently

The failure mode worth designing for, because nothing tells you.

Sent is not delivered. The API accepting your message means Twilio has it, not that a phone received it. The delivery status arrives later, by callback, and only if you listen.

Carriers filter. Traffic that looks promotional, unregistered, or high-volume from a new number can be filtered without any error reaching you. The message reports as sent and nobody receives it.

Registration matters. Depending on country and number type, sending without the appropriate registration results in filtering. This is an administrative task rather than a technical one, and it is the most common cause of a working integration that delivers nothing.

Monitor the rate, not individual messages. One undelivered message is noise. An undelivered rate that has doubled since Tuesday is a problem, and it is visible only if something is watching.

Alert on the drop. A sudden fall in delivered messages is more informative than a rise in errors, because filtering produces the former without the latter.

What not to automate

Anything without a clear consent basis. If you cannot say what the recipient agreed to and when, do not send.

Bulk promotional messaging to acquired lists. Regardless of what the list vendor claimed, this is where penalties and carrier blocks come from.

Anything with a legal character. Debt collection, contract termination, or anything with consequences should be sent by a person who decided to send it.

High-frequency messaging. Several messages to the same person in a day will produce opt-outs faster than any content problem, and each opt-out is permanent.

Anything at an inconsiderate hour. Quiet hours are regulated in some jurisdictions and are simply good practice everywhere. An automation triggered at three in the morning should queue rather than send.

Building it so it survives

Check consent immediately before sending, not when the list was built.

Make it safe to run twice. Webhooks retry, and a duplicate SMS is worse than a duplicate email because it is intrusive and it costs you.

Log every message with its consent basis. This is the record that answers a complaint.

Handle the opt-out webhook as a priority path. It should not be queued behind other work, since the window between the request and it taking effect is your exposure.

Report daily. Messages sent, delivered, failed, and opted out. The opt-out count is the one to watch, because a rising rate means your content or frequency is wrong.

Limits worth knowing about

Rate limits and throughput vary by number type, and sending faster than a number supports queues rather than fails, which delays messages without an obvious error.

International pricing varies substantially by destination, and an automation with global reach can produce a surprising bill.

Message segments mean a long message is billed as several, and non-standard characters reduce the characters per segment considerably, which catches anyone using emoji or accented text.

Number registration requirements differ by country and change, and unregistered traffic is filtered rather than rejected.

Inbound webhooks need to respond quickly, so an automation doing heavy work on receipt should acknowledge first and process afterwards.

What to build first

Opt-out propagation, before anything that sends. An inbound stop message reflected immediately everywhere you hold that contact. It is small, it is the one piece with genuine legal consequence, and building it first means every later automation inherits a consent state it can trust.

Two habits make the difference. Test the opt-out path deliberately with a number you control and confirm it propagated everywhere, since assuming it works is exactly how people find out it does not. And report the opt-out rate daily, because it is the earliest signal that your messaging is wrong.

Frequently asked questions

Do I need to handle opt-outs if Twilio does it?

Twilio can handle standard keywords for the messages it sends, and your own systems still need to know. Otherwise the person remains on lists elsewhere and the next automation somebody builds will message them. The propagation is the part you own.

Why are my messages sending but not arriving?

Most often carrier filtering, frequently due to missing registration for the number and traffic type. The API reports success because Twilio accepted the message; the delivery status callback is what tells you what actually happened, and if nothing is listening for it you will not know.

Can I send marketing messages?

With explicit consent for marketing specifically, appropriate registration, respect for quiet hours, and a working opt-out. What you cannot do is send promotional messages to numbers collected for another purpose, which is the most common way businesses get into trouble here.

How do I validate numbers?

Use Lookup at the point of capture rather than at send time, so a typo can be corrected while the customer is still in front of you. It also reports line type, which prevents sending SMS to a landline and paying for nothing.

What should I monitor?

The delivery rate by number and route, the opt-out rate, and total spend. A falling delivery rate is the characteristic symptom of filtering and produces no errors, so it is invisible unless something specifically watches for it.

How do I stop duplicate messages?

Use an idempotency key derived from the triggering event and check it before sending. Webhook retries are the usual cause, and a duplicate SMS is more intrusive than a duplicate email and costs you each time.

Should the automation reply to inbound messages?

Route them to a person for anything conversational. Automated replies are reasonable for acknowledgement and for genuinely simple factual queries, and a customer who replies to an SMS is usually expecting a person, so silence or a bot reply both disappoint.

How do I handle international recipients?

Check the destination before sending, because pricing, regulation, and registration requirements all vary by country. An automation with global reach and no per-country handling will produce both a surprising bill and messages filtered in markets you did not think about.

Should acknowledgements be sent by SMS?

Only where the original interaction was by SMS. Sending a text to confirm a web form submission is intrusive for something the person is already looking at, and it consumes goodwill you will want later for something that matters.

What is the single biggest cause of messages not arriving?

Missing or incorrect registration for the number and traffic type, which varies by country and changes. It produces filtering rather than errors, so the integration looks healthy and nothing arrives. Confirm registration before assuming anything is wrong with your code.

Should transactional and marketing use the same number?

Separate them where you can, using different numbers or messaging services. Marketing traffic carries filtering risk, and a number whose reputation degrades takes your delivery notifications down with it, which is a much worse outcome than a campaign underperforming.

How do I handle replies to an automated message?

Route them to a person, always. Somebody replying to an SMS expects a human, and an automated response to a genuine reply is the interaction people remember badly. At minimum, acknowledge and tell them when a person will respond.

Get started today

Your first workflow is free to build.

Describe what you need. Cody handles the build, the connections, and the deployment.