The lawsuit that started with a recycled number
A company gets sued under the TCPA. They pull their suppression list, find the number on it, and assume they’re covered. Then opposing counsel asks one question: when did that number get reassigned? The company has no answer. The opt-out was recorded two years ago. The carrier recycled the number eight months later. Every message since then went to a stranger who never consented to anything.
That’s the scenario suppression lists are supposed to prevent, and that’s exactly the scenario a poorly maintained one makes worse. A list full of stale, unverified opt-outs doesn’t protect you. It just gives you false confidence.
What a defensible suppression record actually needs
At minimum, every opt-out entry needs a UTC timestamp, the raw number as submitted, a normalized E.164 version, and the channel the opt-out came through (SMS STOP reply, web form, phone IVR, etc.). That’s table stakes.
What most teams skip is the carrier snapshot at the time of opt-out. If you record that +12125550198 opted out on 2023-11-14 and you know from your lookup at that moment that dipPorted was false and the LRN was 12125550198, you have a baseline. If the number later shows a different dipLrn, that’s evidence the number has been ported, possibly reassigned, and the opt-out you’re holding may no longer apply to the person you’re about to contact.
This matters in litigation because the burden increasingly falls on the sender to show they had a reasonable, documented basis for believing the person they contacted was the same person who opted in (or that someone genuinely opted out). A timestamp alone doesn’t get you there.
Porting and reassignment are not the same problem
People conflate these. Porting is when a subscriber moves their number from one carrier to another, keeping the same number. Reassignment is when a number is deactivated and later given to a completely different person.
For suppression purposes, a ported number is usually fine. The same person still owns it, just through T-Mobile now instead of Verizon. You check dipPorted in the CheckThatPhone response and if it’s true, you also look at dipLrn. If the LRN changed but the subscriber profile you hold (name, address, account ID) still matches, you’re probably looking at the same person on a new carrier. The opt-out still applies.
Reassignment is the real danger. A deactivated number sits in a pool, gets recycled by the carrier, and goes to someone new. The deactivationDate field tells you when CheckThatPhone last observed the number as inactive. If deactivationDate is populated and falls after your opt-out timestamp, that’s a red flag. The opt-out may be from the previous subscriber, not the current one.
The blackList field is also worth checking here. A number on a known bad actor or litigation list should never be contacted regardless of opt-out status, and you should log why you suppressed it separately from a voluntary opt-out.
Building the revalidation loop
One lookup at signup, one at opt-out, and then nothing forever is how you end up in that deposition. Numbers change. Carriers recycle. People port. You need a periodic revalidation pass.
In practice, I’d break your suppression list into buckets by age. Anything opted out in the last 90 days: leave it alone, it’s fresh. 90 days to 18 months: revalidate quarterly. Older than 18 months: revalidate monthly and flag for review.
For large lists, the right tool is the bulk CSV upload via the CheckThatPhone dashboard (Dashboard → Bulk CSV). You upload your suppression list as a CSV, it deduplicates, runs carrier DIP and line type validation against every row, and returns a downloadable result file. Files and results are deleted within 24 hours of delivery, which matters for data minimization. You’re not leaving a copy of your contact list sitting on a third-party server.
For real-time checks, say during an opt-out intake flow or before a single outbound call, use the POST https://api.checkthatphone.com/v1/lookup endpoint with your Authorization: Bearer <key> header. The response gives you dipPorted, dipLrn, deactivationDate, blackList, and the deliverable flag in one shot. Build that into your opt-out handler so every new suppression entry gets a carrier snapshot baked in at creation time.
The litigator scrub layer
This is separate from opt-out hygiene but it belongs in the same workflow. Some numbers belong to serial TCPA plaintiffs who sign up specifically to manufacture lawsuits. An opt-out record does nothing for you here because the harm is the contact itself, not the failure to honor an opt-out.
Add litigatorFilter: true to your lookup request. If the response returns litigator: true, you get litigator_type and litigator_name as well. Suppress that number entirely and log it separately from your standard opt-outs. Do not commingle them. You want to be able to show in discovery that your litigator suppression is a distinct, proactive control, not something you stumbled into.
More detail on how that flag works is at /use-cases/tcpa-litigator-scrub.
What the carrier data actually costs you to skip
Validating a number through CheckThatPhone at opt-out time costs fractions of a cent. A TCPA settlement for calling a reassigned number can run $500 to $1,500 per violation, and class actions multiply that fast. The math is not close.
The less obvious cost is operational. If your suppression list contains numbers that have been deactivated and reassigned, and you’re not catching them with deactivationDate, you’re suppressing numbers you could legally contact. That’s lost revenue. I’ve seen suppression lists at mid-sized companies that were suppressing 15 to 20 percent more numbers than they needed to because nobody had ever revalidated against deactivation data. Those weren’t opt-outs. They were just dead numbers that nobody cleaned up.
See /use-cases/contact-list-hygiene for how this fits into a broader list maintenance workflow.
The minimum viable suppression schema
If you’re rebuilding or auditing your suppression table, here’s what each row should carry:
- Raw number as entered by the user
- E.164 normalized number
- UTC timestamp of opt-out
- Channel (SMS, voice, web, etc.)
dipPortedvalue at time of opt-outdipLrnvalue at time of opt-outdeactivationDatefrom most recent revalidationblackListflag from most recent revalidation- Last revalidation timestamp
- Suppression reason (voluntary opt-out, litigator flag, deactivated, etc.)
That last field is the one most schemas omit. Mixing voluntary opt-outs with litigator flags with dead numbers in a single undifferentiated list makes it much harder to explain your controls to a regulator or opposing counsel.
The /docs reference covers every field returned by the lookup endpoint if you want the full schema while you’re building this out. Pricing for bulk validation runs is at /pricing.
Where to start
Pull your current suppression list. Filter for entries older than 18 months. Run that subset through a bulk CSV validation and look specifically at deactivationDate and dipLrn changes relative to your opt-out timestamps. That one pass will tell you whether your list is a genuine compliance asset or a liability dressed up as one.