Disclosure: I run NxFlowAI, an automation agency serving US businesses remotely from Mumbai. Not legal advice; check consent rules with your own adviser.

In US small-business automations, texting consent tends to live in the texting tool and nowhere else. Then a second tool (a CRM sequence, a review-request app, a reminder service) texts someone who replied STOP last month. The fix is boring and effective: one consent ledger that every automation checks before sending. It is a pattern I use as an AI automation agency building US texting workflows.

The table

CREATE TABLE consent_events ( id BIGSERIAL PRIMARY KEY, phone_e164 TEXT NOT NULL, -- +1XXXXXXXXXX channel TEXT NOT NULL, -- sms, whatsapp, email purpose TEXT NOT NULL, -- transactional, marketing event TEXT NOT NULL, -- opt_in, opt_out source TEXT NOT NULL, -- web_form, keyword_reply, staff_entry evidence TEXT, -- form id, message id, staff note occurred_at TIMESTAMPTZ NOT NULL DEFAULT now() ); 

Append-only. Never update a row; add a new event.

The check

def may_send(phone, channel, purpose): last = db.latest_event(phone, channel, purpose) if last is None: return purpose == "transactional" and has_active_request(phone) return last.event == "opt_in" 

Every automation calls may_send right before sending, not when the job is queued.

Capturing opt-outs

  • Inbound texts matching the standard opt-out words (the FCC's list is stop, quit, end, revoke, opt out, cancel and unsubscribe; carriers and providers may recognise more) write an opt_out event for all purposes on that channel. Plain-language requests such as "please stop texting me" should be caught too, by a person if not by code.
  • Staff can record an opt-out by hand ("customer asked on the phone").
  • Opt-ins come from forms with clear wording, and the form id goes in evidence.

Why append-only

When someone asks "why did we text this person?", you can answer with dates and sources. That is worth more than a boolean flag.

Test cases

  • Opt-out on Monday, reminder scheduled Sunday: blocked.
  • Opt-in for reminders only, marketing job runs: blocked.
  • Number formatted three ways: same person (normalize to E.164).

We design ledgers like this during a 72-hour audit before building any texting flow. For the non-technical overview of that audit, see our guide to auditing a business workflow before AI.