Tutorialthe whole build, step by step

10DLC registration and consent checks before your app texts leads

A consent gate that says no by default, 10DLC registration, a STOP that really stops, and a fence around test data. Not legal advice.

By Eric Snyder, founder 6 min readChecked on Oct 6, 2026
Save this guidereceiptsgroup.com/guides/ai-app-texts-calls
ForAnyone whose app, CRM or automation texts or calls leads or customers in the US
TimeAn afternoon for the audit; 10DLC registration can take a week or more of waiting
You needYour app's code or settings, your texting provider's portal, and Claude Code
Rules checked47 CFR 64.1200 and the FCC's 2024 consent order (in force since 2025-04-11)
NotLegal advice. Show this to a lawyer before you send.
In this guide
Start here
  1. The easy way: have Claude audit your app
The manual way
  1. What the rules actually say (plain English)
  2. Check 1: a consent gate that says no by default
  3. Check 2: register your texting before you send
  4. Check 3: a STOP that actually stops
  5. Check 4: a fence around test data
  6. Real use: prompts for real jobs
  7. When it breaks
  8. Sources, checked Oct 6, 2026

AI makes it easy to build an app that texts and calls people. It does not make it legal. We built our CRM and dialer with AI in twelve days, and some of the most important parts weren't features at all. They were four checks that decide who the app is allowed to contact.

This guide is those four checks, with what the federal rules actually say, links to the rules themselves, and a prompt that has Claude Code audit your app for them. It is not legal advice. Rules differ by state, and they change. Before your app sends its first message, have a lawyer who does telemarketing (TCPA) work read your consent wording and your setup.

Checked on Oct 6, 2026

Start herepart 1

The easy way: have Claude audit your app

Open Claude Code in your app's folder and paste this. It reads, reports and proposes. It doesn't change anything until you say so, and it never sends a message.

bashStart Claude in your app's folder
cd <your app's folder>
claude
PromptThe audit prompt (copy all of it)
Audit this app for the four checks in this guide, read-only:
https://receiptsgroup.com/guides/ai-app-texts-calls

Find every place the app can send a text, place a call, or hand a contact to another system. For each one, tell me:
1. Consent gate: what decides this contact may be texted or called? Does it say no by default? Can an imported or purchased list pass it? Do we store who agreed, when, where, and the exact words they agreed to?
2. 10DLC: are texts sent from a 10-digit number, and is there anything that stops sending until the numbers are registered and attached?
3. STOP: which words opt someone out, is the opt-out checked before every text AND every call, and how fast does it take effect?
4. Test data: can a test or fake contact ever reach a real CRM, a real phone number, or a real customer's account?

Answer as a table: place in the code, check, what it does now, gap, the smallest fix. Don't change any files, don't run anything that sends, calls or posts, and don't print any keys or phone numbers. Then wait for me.
The manual wayparts 2 to 8

What the rules actually say (plain English)

This is the manual way: each check, why it exists, and how to build it. Links to the rule text are under Sources. Plain-English summaries, not legal advice.

  • Marketing robocalls and robotexts need written consent. For calls and texts that advertise, made with an autodialer or an artificial or prerecorded voice, the rules require “prior express written consent”: a signed written agreement (the rule allows electronic signatures valid under federal or state law) that clearly authorizes the seller to send them, with a clear disclosure that agreeing isn't a condition of buying anything (47 CFR 64.1200(f)(9)).
  • Texts count. The FCC treats the restriction as covering both voice calls and texts; a STOP by text revokes consent for that caller's robocalls too (FCC consent order, 2024).
  • People can revoke consent any reasonable way, including replying stop, quit, end, revoke, opt out, cancel or unsubscribe, and it has to be honored within a reasonable time, no more than ten business days (47 CFR 64.1200(a)(10), in force since 2025-04-11).
  • Company-specific do-not-call requests on telemarketing calls also have to be honored within ten business days (64.1200(d)(3)).
  • Business texting from a regular 10-digit number needs 10DLC registration. Telnyx, for one: “From February 3rd 2025, any 10DLC traffic which is not registered will be blocked altogether.”

States add their own rules on top (some on calling hours, some on recording calls). Check yours.

Check 2: register your texting before you send

10DLC is the system US carriers use to know who's texting from a regular 10-digit number and why. You register a brand (your business) and a campaign (what you text about), then attach your numbers to the campaign. People review it by hand, and nobody tells you how long that takes. Ours: brand approved fast, campaign created the same day, numbers still waiting on the carriers over a week later.

  1. Register the brand

    WhereYour texting provider's portal (Telnyx, Twilio and the rest all have a 10DLC section)

    Your legal business name, tax ID, address and website, exactly as they appear on your registration. Mismatches are the usual reason for a rejection.

  2. Register the campaign

    Pick the use case that matches what you actually send. Write sample messages that look like your real ones, describe how people opt in (link to the form with the consent wording above), and list your opt-out and help keywords. Vague campaigns get rejected.

  3. Attach your numbers, then wait

    Assign the numbers you'll text from to the campaign. Until the provider shows them as attached and active, don't send.

  4. Make the app wait too

    Put a switch in the app that keeps the texting lane off until the numbers are attached, and check it on every send. “It'll probably go through” is how you get blocked numbers.

    pythonThe switch (example)
    TEXTING_LIVE = False   # flip to True only after the provider shows every number attached to the campaign
    
    def send_text(contact, body, suppressed):
        if not TEXTING_LIVE:
            return "held: 10DLC not attached"
        if not may_contact(contact, "sms", suppressed):
            return "blocked: no consent or opted out"
        ...  # your provider's send call

Check 3: a STOP that actually stops

The rules give you up to ten business days to honor an opt-out. Your code can do it in ten seconds, so do. One suppression list, checked before every text and every call, because a STOP by text revokes calls too.

pythonInbound handler (example)
OPT_OUT = {"stop", "quit", "end", "revoke", "opt out", "optout", "cancel", "unsubscribe", "stopall"}

def on_inbound_text(phone, body, suppressed):
    words = body.strip().lower()
    first = words.split()[0] if words else ""
    if words in OPT_OUT or first in OPT_OUT:
        suppressed.add(phone)            # save it to your database, not just memory
        return "You're unsubscribed and won't get more messages from <Your Business Name>."
    if words == "help":
        return "<Your Business Name>: <how to reach you>. Reply STOP to opt out."
    return None
  • Opt-outs that come in any other way count too: a reply like “please stop texting me”, an email, a call to your office. Have one place a person on your team can add a number.
  • Sync the list to every tool that can contact people: your CRM, your dialer, your email tool.
  • Keep it forever. Don't “clean” it.

Check 4: a fence around test data

AI-built apps get tested a lot, and fast. We once had our test runner push a fake lead into a live CRM after delivery went live. We caught it and removed it by hand, which is luck, not design. Now there's a fence: test contacts are marked, and every path that touches a real system refuses them.

pythonThe fence (example)
def is_test(contact):
    return bool(contact.get("is_test")) or contact.get("email", "").endswith("@example.com")

def deliver(contact, destination):
    if is_test(contact) and destination.get("production"):
        raise RuntimeError("refused: test contact to a live system")
    ...
  • Use your providers' test or sandbox modes and separate keys for testing.
  • Use phone numbers you own for tests, never a real lead's.
  • Make “test” the default for anything a script creates.

Real use: prompts for real jobs

Prompt1. Find the side doors
Search this codebase for every function, webhook, cron job or script that can send a text, place a call, send an email, or create a contact in another system. List each with its file and line, and whether it calls our consent gate first. Read-only.
Prompt2. Add the gate where it's missing
For each send path you listed without the consent gate, show me the smallest change that calls may_contact() first and refuses on False. One path at a time, show me the diff, wait for my yes.
Prompt3. Prove STOP works
Write a test (no real sends; mock the provider) that: texts a test contact, receives "Stop" from that number, then tries to text AND call it again, and asserts both are refused. Run it and show me the result.
Prompt4. Check the consent record
Show me what we store when someone checks the consent box: every field, an example row with fake data, and anything missing compared with the list in this guide's Check 1. Read-only.

When it breaks

Texts “send” but nobody gets them
Check the numbers are attached to an approved 10DLC campaign in your provider's portal. Unregistered 10DLC traffic is blocked.
The campaign was rejected
Read the reason. Usually: sample messages that don't match the use case, an opt-in description without the consent wording, or business details that don't match your registration.
Someone texted STOP and got another message
A send path skips the suppression list. Run real-use prompt 1, then prompt 3 until it passes.
A purchased list is “already opted in”
Not by your form, so not by your gate. Talk to your lawyer before using it at all.
You're not sure the wording is enough
That's a lawyer question, not a code question. Bring them the exact wording and a screenshot of the form.

That's the four

No by default, registered before you send, STOP in seconds, and test data that can't get out. None of it is a feature anyone asks for, and all of it is what keeps the app you built in a weekend from becoming a problem you deal with for a year.

Not legal advice: have a lawyer read your consent wording and setup before your first message.

Checked on Oct 6, 2026 against

Every claim about a third-party tool in this guide (plans, prices, menu paths, commands, limits) was checked against these official pages on Oct 6, 2026. These screens change often: if something looks different, trust the page over this guide.

Rather skip the setup?

Want help setting this up?

Receipts Group builds these systems. Thirty minutes with Eric tells you which piece is worth building first, or that none of them are. The guides stay free either way.

Keep going

more free guides