Documenting SMS consent so it holds up means saving, for every contact, a record of who agreed, when, where, and the exact wording they saw, captured at the moment they opted in and never edited afterward. Keep that record attached to the contact in your own system, because when someone disputes a text, the question is "show me," and an export of phone numbers proves nothing.
Most teams collect opt-ins well enough. The gap shows up months later, when a contact claims they never signed up, a carrier asks how a number got on your list, or a demand letter arrives citing the TCPA. At that point the checkbox you designed doesn't help much. What helps is the row in your database that says this number, this form, this sentence, this timestamp. This post covers what that row should contain, where it should live, what Ready records on each send and what it leaves to you, and how all of it connects to 10DLC registration and TCPA exposure.
This is general guidance from the company that runs the sending infrastructure. It isn't legal advice. Compliance stays the sender's responsibility, so have counsel review your specific flows.
Why documenting SMS consent matters more than collecting it
Consent you can't reproduce is close to consent you never had. The TCPA lets recipients claim roughly $500 to $1,500 per unwanted text, and in a dispute the sender usually has to show the opt-in happened. "Our form has always had that checkbox" is weak evidence. "Here is the submission from March 4 at 2:17 PM Eastern, from this page, showing this disclosure text, version 3" is strong evidence.
Here is a worked example of why this matters at scale. The numbers are assumptions chosen for illustration, not statistics:
- You send one promotional text to 4,000 contacts.
- You imported 2% of them (80 numbers) from an old spreadsheet with no source recorded.
- If those 80 people dispute the text, exposure is 80 × $500 = $40,000 at the low end. At the high end it's 80 × $1,500 = $120,000.
- That figure is per text. A four-message drip campaign multiplies it.
The fix isn't expensive software. It's deciding up front what a consent record contains and refusing to send to numbers that don't have one. Cold contact belongs on phone and mail. SMS goes to people who opted in or who replied to you first.
What a consent record should hold
Picture a stranger reading the record two years from now with no context. Every field below answers a question that stranger will ask.
| Field | Example | Why it matters |
|---|---|---|
| Phone number (E.164) | +12125550199 | The record has to match the exact number you texted |
| Timestamp with timezone | 2026-03-04 14:17:09 America/New_York | Shows consent came before the first message |
| Capture source | Checkout page /checkout, form ID cart-v3 | Shows where the consent came from |
| Exact disclosure wording | "By checking this box you agree to receive recurring marketing texts from Acme Outdoor at this number. Msg frequency varies. Msg & data rates may apply. Reply STOP to opt out, HELP for help. Consent is not a condition of purchase." | The precise text the person agreed to, not a summary |
| Wording version | sms-disclosure-v3 | Lets you prove which copy was live on that date |
| Capture method | Unchecked checkbox, user checked it | Pre-checked boxes and buried terms are hard to defend |
| Scope | Marketing + order updates, Acme Outdoor only | Consent to receipts is not consent to promos |
| Technical context | IP address, user agent, session or order ID | Ties the opt-in to a real interaction |
| Confirmation sent | "Acme Outdoor: You're subscribed..." at 14:17:12 | Shows the person was told right away |
| Double opt-in reply (if used) | "YES" received 14:19:40 | Strongest evidence that the number holder agreed |
A few notes on the hard parts.
Store the wording itself. A link to your current privacy page fails as proof, because that page will change. Save the disclosure text as a versioned string, and store the version ID on each consent record. When you edit the form, create a new version. Don't overwrite the old one.
Scope matters. Someone who agreed to shipping notifications didn't agree to a Black Friday campaign. Record what the consent covers. Before you send a new type of message, check that scope.
Offline and keyword opt-ins need records too. If someone texts JOIN to your number, save the inbound message, its timestamp, the keyword, and where you advertised it (for example, "in-store sign, Austin location, sign version 2"). For paper or verbal consent at a counter, save who collected it, where, and a scan or note of the form.
Double opt-in strengthens the record. A confirming reply from the number itself is hard to dispute, and it filters out typos and mistyped numbers. We cover the carrier-side benefits in single vs double opt-in deliverability.
Keep the record with the contact, not in a folder
Consent proof usually goes missing for one of three reasons. A form tool gets cancelled and takes its submission history with it. An export lands in a shared drive nobody owns. A CRM migration drops "custom fields nobody uses." The fix is structural.
Make consent a first-class part of the contact
Give each contact a consent history, not a single yes/no flag. A simple shape:
consent_events: append-only rows (granted, revoked, re-granted), each with the fields from the table abovecurrent_sms_status: derived from the latest event, never typed by handdisclosure_versions: a separate table holding every version of your opt-in wording, keyed by version ID
Append-only is the key property. If someone opts out and later opts back in, you want both events on record, not a field that flipped twice with no trace.
Retention
Keep consent records for at least as long as you might face a claim about a text, plus margin. Many teams keep them for several years after the last message to that contact. Ask counsel for your number. Deleting a contact for privacy reasons and keeping proof of past consent can conflict, so decide your policy before a request comes in, not during one.
Opt-outs belong in the same history
A revocation is a consent event. Record when it happened, the exact inbound text ("STOP", "cancel", "please stop texting me"), and the channel. Ready handles STOP automatically and blocks further sends to that number across campaigns. Your own system should still log the revocation so your records and your sending layer agree. If you ever change providers, you need that history in a form you control.
What Ready records on each send, and what it doesn't
Responsibility splits between two layers, and it's worth being precise about where the line falls.
Ready records the sender's attestation per send. An API send can carry a consent_attested field. Setting it to true is your promise that the recipient agreed to receive texts. For each bulk send, and each API send that sets it, Ready logs who sent it, to how many recipients, and when. That gives you an audit trail of what your platform asserted at send time.
POST https://api.tryready.com/v1/messages
X-API-Key: <your key>
Idempotency-Key: 3f6c2a9e-8b1d-4c5e-9a7f-2d4b6e8c1a03
Content-Type: application/json
{
"to": "+12125550199",
"body": "Acme Outdoor: Your order #1042 has shipped. Reply STOP to opt out.",
"consent_attested": true
} The bulk endpoint (POST /v1/messages/bulk) takes the same consent_attested promise for a list of numbers. Full request details are in the messages API docs.
Ready does not store per-contact consent. It doesn't record the recipient's opt-in time, the wording they saw, or the page URL. A keyword reply to your number doesn't create a consent record in Ready either. Those details live in your system: your store, CRM or application database. That's deliberate, because only your system knows what the person saw. (A contact who signs up on a Ready-hosted opt-in page is the exception: Ready stores that sign-up, with the time, IP address and exact wording, and support@tryready.com can send you a copy.)
The practical rule follows from that. Set consent_attested: true only after your code has checked that a valid consent event exists for that number with the right scope. Don't hardcode it. The attestation is only as good as the lookup behind it.
Some safeguards apply whatever you attest. Numbers that opted out, numbers on your Ban list, and known landlines are refused before sending and aren't charged. Quiet hours are enforced by the recipient's area: campaigns wait for the window, while an API or one-to-one text is held only if the window opens within 6 hours, otherwise it is refused with 409 QUIET_HOURS_BLOCK and has to be sent again. If you want known TCPA litigators and DNC complainers removed before a send, the standalone scrub costs $0.005 per contact. These reduce risk. None of them replaces a consent record. The full case for scrubbing is in TCPA litigator scrubbing explained.
How consent ties to 10DLC registration
When you register a 10DLC campaign, you describe how people opt in and you submit sample messages. Reviewers check that description, and a vague one ("customers opt in on our website") is a common reason for rejection. Most approvals take 2 to 7 days, and a resubmission restarts that wait.
Your documented consent flow and your registration should describe the same thing:
- The opt-in description in your registration should match your live form. If you say "unchecked checkbox at checkout with disclosure text," that should be what a visitor actually sees.
- The disclosure wording should name your brand, the message type, frequency, rates, STOP and HELP. That's the same wording you version and store per contact.
- The use case should match the scope you record. If consent covers order updates only, don't send promos on a campaign registered for marketing, and don't send marketing on a campaign registered for notifications.
For the wording that tends to clear review on the first submission, see the opt-in language that passes registration.
Registration doesn't prove consent for any one contact. It shows carriers that your process exists. The per-contact records show you followed it.
Consent records and TCPA risk: layering the defenses
Think of compliance as layers. Each one covers a gap the others leave:
- Consent record: proves this person agreed. This is your main defense.
consent_attestedon each send: shows your platform checked before sending.- Opt-out handling: stops texts after revocation, across campaigns.
- Quiet hours: prevents sends at hours people complain about.
- Litigator and DNC scrub: removes numbers with a history of filing claims or complaints.
Agencies and platforms that send for their own customers have one more layer to think about: whose records are these? If a customer uploads a list and your platform sends to it, who holds the consent proof, and who is exposed if it doesn't exist? Put the answer in your contracts and in your product. Require a source field on every import, and refuse to send to numbers without one. We cover the split in detail in who gets sued when a client's bad list gets texted.
FAQ
What counts as proof of SMS consent?
Proof of SMS consent is a timestamped record tying a specific phone number to a specific opt-in action, along with the exact wording the person agreed to. The strongest records add the capture source, an IP address or session ID, and a confirming reply from the number. A phone list on its own isn't proof.
Do I need to save the exact opt-in wording or just the date?
You need the exact wording, not just the date. The wording shows what the person agreed to: which brand, which types of messages, and how to opt out. Version your disclosure text and store the version ID on each consent record so you can show what was live on that day.
Does a STOP reply delete my consent record?
No. A STOP reply should add a revocation event to the contact's history, not erase the original consent. Keeping both shows you had permission for earlier texts and stopped when asked. Ready blocks further sends after STOP automatically, but your own records should log the revocation too.
Does setting consent_attested to true protect me if I get sued?
No, not on its own. consent_attested is your promise to Ready that the recipient agreed, and Ready logs that attestation for each send as an audit trail. Your actual defense is the per-contact consent record in your own system, so set the flag only after your code confirms that record exists.
How long should I keep SMS consent records?
Keep them at least as long as someone could bring a claim about a text you sent, plus a margin. Many teams keep records for several years after the last message to a contact. Confirm the exact period with counsel, and decide in advance how deletion requests interact with that retention.
The practical takeaway
Documenting SMS consent comes down to four habits. Capture the full record when someone opts in. Store it append-only against the contact. Check it in code before you set consent_attested. Keep your registration description in line with what your form actually shows. A short audit:
- Pick ten random contacts and try to produce their full consent record in under five minutes.
- Check that your opt-in wording is versioned and that old versions still exist.
- Confirm that imports without a source field can't reach a send.
- Compare your live form with the opt-in description in your 10DLC registration.
If all four pass, you're in good shape. If you're building this into a platform and want the sending side, meaning attestation logging, opt-out handling, quiet hours and optional scrubbing, the quickstart shows the full flow. You can create an account and use the first 20 free texts to test your setup before you register.