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.
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.
cd <your app's folder>
claudeAudit 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.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 1: a consent gate that says no by default
In ours, the rule is written right into the code: a contact that arrived by import is not consent. Otherwise a spreadsheet with a column called “consent” launders a bought list straight into your texting. The gate starts at no and only one thing turns it to yes: a real person agreeing on your form, recorded.
Store this for every yes
- The phone number, and the person's name.
- The exact words they agreed to (the version, not “the checkbox”).
- Where: the page or form, and that they checked an unchecked box themselves.
- When, to the second.
- Which business they agreed to hear from.
[ ] By checking this box, I agree that <Your Business Name> may call and text me at the
number above about <what you'll contact them about>, including marketing messages sent
using automated technology. Agreeing is not a condition of any purchase. Message
frequency varies. Message and data rates may apply. Reply STOP to opt out, HELP for help.
<link to your privacy policy> <link to your terms>def may_contact(contact, channel, suppressed):
"""True only when this contact has a recorded, form-given yes and hasn't opted out. Default: no."""
c = contact.get("consent") or {}
if contact.get("phone") in suppressed: # Check 3: STOP wins, on every channel
return False
if contact.get("is_test"): # Check 4: test data never contacts anyone
return False
if c.get("source") != "web_form": # imports, purchases and CSV columns are not consent
return False
return bool(c.get("agreed_at") and c.get("wording_version") and c.get("page")
and channel in (c.get("channels") or []))Then make every send path call it: the app, the automations, the dialer, any script. One gate, no side doors. Ask Claude to find the side doors; that's what the audit prompt is for.
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.
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.
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.
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.
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.
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.
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.
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
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.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.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.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
The campaign was rejected
Someone texted STOP and got another message
A purchased list is “already opted in”
You're not sure the wording is enough
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.
- 47 CFR 64.1200 (Cornell LII)(f)(9) prior express written consent and its required disclosures; (a)(10) revocation by any reasonable means, including stop, quit, end, revoke, opt out, cancel, unsubscribe, within ten business days; (d)(3) do-not-call requests within ten business days.
- Federal Register: Strengthening the Ability of Consumers To Stop Robocalls (2024-04587)The FCC's 2024 consent order: reasonable means of revocation, ten business days, a text STOP revokes robocalls too; compliance required from 2025-04-11.
- Telnyx: Frequently asked questions about 10DLCRegister a brand and a campaign, assign numbers, manual review; unregistered 10DLC traffic blocked from 2025-02-03.
- FTC: National Do Not Call Registry for telemarketersWhere sellers and telemarketers access the national registry.
