DEV Community

Ujjwal Dubey
Ujjwal Dubey

Posted on

A Consent Ledger for Customer Texts: Storing Opt-Ins and STOPs So Every Automation Can Check Them

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()
);
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)