Do Not Call compliance is not optional. It's not a "best practice." It is the single most expensive thing you can get wrong in an outbound VICIdial operation.
A single DNC violation under the TCPA carries $500 in damages. Willful violations jump to $1,500 per call. Federal DNC registry violations can reach $53,088 per violation (2025 adjusted). Plaintiff attorneys don't file lawsuits over one call — they file class actions covering thousands. I've seen operations hit with seven-figure settlements because their DNC scrubbing process had a gap they didn't know about. A list that wasn't re-scrubbed within the 31-day window. A state DNC list they didn't realize existed. An internal DNC table that wasn't being checked during hopper loading because someone toggled the wrong setting when cloning a campaign.
The DNC landscape in 2026 involves three overlapping layers of compliance. VICIdial handles the internal layer natively. The federal and state layers require external scrubbing processes that feed into VICIdial's filtering system. All three layers must work correctly, simultaneously, on every campaign. A gap in any one of them is enough for a lawsuit.
Layer 1: The Federal DNC Registry
The FTC's National Do Not Call Registry is the baseline. Every outbound operation calling U.S. consumers must scrub against it.
Getting Access
Register at telemarketing.donotcall.gov. You'll need your company's legal name, physical address, EIN, and a responsible individual. The fee is based on area codes accessed — a single area code costs $75/year, all ~330 area codes costs approximately $21,525/year. Most operations download only the area codes they actively dial.
To figure out which area codes you need:
SELECT DISTINCT SUBSTRING(phone_number, 1, 3) as area_code,
COUNT(*) as lead_count
FROM vicidial_list
WHERE list_id IN (SELECT list_id FROM vicidial_lists WHERE active = 'Y')
GROUP BY area_code
ORDER BY lead_count DESC;
The FTC provides flat text files — one phone number per line, organized by area code. Updated daily, but you're required to download and scrub at minimum every 31 days.
The Three Import Approaches
Option A: Pre-scrub before loading into VICIdial. This is the most common approach. Scrub your lead file against the federal DNC data externally, then load only clean leads into VICIdial. Write a shell script that compares phone numbers, outputs clean leads and rejected leads, and logs the scrub for your audit trail.
Option B: Load the federal DNC into VICIdial's vicidial_dnc table. This lets VICIdial's native DNC checking handle federal filtering at hopper-loading time. But the federal registry contains 240+ million numbers — test on staging first and monitor MySQL performance. Your innodb_buffer_pool_size needs to accommodate the additional index size.
Option C: Use a third-party DNC scrubbing service. DNC.com, Gryphon Networks, Contact Center Compliance, Tele-Data Solutions. API-based scrubbing at $0.002-$0.005 per number. Easiest approach, adds per-number cost.
The 31-Day Rule
The TSR requires that you scrub calling lists against the National DNC Registry no less frequently than every 31 days. Not 32 days. Not "monthly." Every 31 days from the date of your last scrub. Track scrub dates per list.
Build a tracking table and query it weekly:
CREATE TABLE IF NOT EXISTS vicistack_dnc_scrub_log (
scrub_id INT AUTO_INCREMENT PRIMARY KEY,
list_id BIGINT NOT NULL,
scrub_type ENUM('federal', 'state', 'litigator') NOT NULL,
scrub_date DATETIME NOT NULL,
total_numbers INT NOT NULL,
numbers_removed INT NOT NULL,
scrub_source VARCHAR(100),
performed_by VARCHAR(50),
INDEX idx_list_date (list_id, scrub_date)
);
Check which lists are overdue:
SELECT
vl.list_id, vl.list_name,
ds.last_scrub,
DATEDIFF(NOW(), ds.last_scrub) as days_since_scrub,
CASE WHEN DATEDIFF(NOW(), ds.last_scrub) > 31 THEN 'OVERDUE'
WHEN DATEDIFF(NOW(), ds.last_scrub) > 25 THEN 'SCRUB SOON'
ELSE 'CURRENT'
END as scrub_status
FROM vicidial_lists vl
LEFT JOIN (
SELECT list_id, MAX(scrub_date) as last_scrub
FROM vicistack_dnc_scrub_log WHERE scrub_type = 'federal'
GROUP BY list_id
) ds ON vl.list_id = ds.list_id
WHERE vl.active = 'Y'
ORDER BY days_since_scrub DESC;
Any list showing "OVERDUE" must be re-scrubbed or deactivated immediately. Dialing from a list with a stale scrub is a per-call violation.
The Penalty Math
TCPA penalties are severe enough to be existential for small and mid-size operations:
- $500 per violation for unintentional infractions
- $1,500 per violation for willful violations
- $53,088 per violation for federal DNC registry violations (2025 adjusted)
- State-level penalties: Texas SB 140 ties TCPA-style violations to treble damages. Virginia SB 1339 requires honoring text opt-outs for ten years.
To put this in context: if your VICIdial system dials 1,000 numbers on a stale DNC list, potential exposure at $500/violation is $500,000. At the willful rate, $1.5 million. TCPA litigation hit 2,788 cases in 2024 — a 67% increase over 2023. Monthly class action filings reached 172 by January 2025, up 268% year over year. Plaintiff attorneys are actively monitoring outbound operations, and the lawsuits are getting larger.
The cost of proper DNC compliance tooling and processes — even at the enterprise level — is a rounding error compared to a single class action settlement. Operations that treat DNC as an afterthought are gambling with their existence.
Layer 2: State DNC Lists
This is the layer that trips people up. Over a dozen states maintain their own Do Not Call registries — separate from and in addition to the federal list. A number can be on Indiana's state DNC but not on the federal list. If you're calling into Indiana and haven't scrubbed against their list, you're in violation of state law.
| State | Annual Fee (approx.) | Update Frequency |
|---|---|---|
| Colorado | $200-$400 | Quarterly |
| Florida | $100 | Quarterly |
| Indiana | $75-$300 | Quarterly |
| Louisiana | Free-$200 | Quarterly |
| Massachusetts | $100-$300 | Quarterly |
| Missouri | $200 | Quarterly |
| New York | $200-$500 | Monthly |
| Pennsylvania | $100-$400 | Quarterly |
| Tennessee | Free-$100 | Quarterly |
| Texas | $100-$300 | Quarterly |
| Wyoming | Free | Quarterly |
Each state has its own registration portal, data format, and fee structure. The list changes — check each state's Attorney General website annually.
Each state has its own registration portal, data format (CSV, fixed-width text, pipe-delimited), and fee structure. The list changes — check each state's Attorney General or Public Service Commission website annually. Some states that previously maintained lists have sunset them in favor of relying solely on the federal registry.
The import process for each state follows the same pattern: register with the state agency, pay the annual fee, download the data, normalize to 10-digit phone numbers, and scrub your lists before loading into VICIdial. For large state files (Florida and Texas can have millions of entries), use MySQL's LOAD DATA LOCAL INFILE for bulk import rather than one-at-a-time inserts.
For managing multiple state DNC lists in VICIdial, you have three options:
-
Merge all into the system-wide
vicidial_dnctable. Simple but blocks those numbers across all campaigns, even where the state restriction doesn't apply. -
Create state-specific campaign DNC lists in
vicidial_campaign_dnc. More granular — assign relevant state lists to campaigns based on target geography. More work to maintain but prevents over-blocking. - Pre-scrub externally by state before loading leads into VICIdial. Only clean leads enter the system.
Layer 3: VICIdial's Internal DNC System
This is what VICIdial handles natively, and it's where compliance gaps hide most often.
The Two Tables
System-wide internal DNC (vicidial_dnc): The master DNC list. When enabled on a campaign, any number in this table will be excluded from the hopper — it will never be dialed by any campaign that has internal DNC checking turned on. Enable it: Campaign Detail > Use Internal DNC List: Y. There is no legitimate reason to set this to N on a production campaign. None.
Campaign-level DNC (vicidial_campaign_dnc): Separate DNC lists per campaign. Useful for product-specific opt-outs — a consumer says "don't call me about solar panels" but may still be a valid lead for a different product campaign. Enable it: Campaign Detail > Use Campaign DNC List: Y.
Campaign DNC entries store both the phone number and the campaign ID:
SELECT phone_number, campaign_id
FROM vicidial_campaign_dnc
WHERE phone_number = '5551234567';
This shows you every campaign-specific DNC entry for that number. A number can be on one campaign's DNC list and not another's.
System-Wide Enforcement for Multi-Campaign Operations
For organizations running multiple campaigns, a consumer who says "take me off your list" expects to stop receiving calls from your entire organization — not just the one campaign that happened to be dialing them.
Best practice:
- Internal DNC = Y on every campaign. No exceptions.
-
DNCL disposition adds to system-wide
vicidial_dnc. This ensures any agent-captured DNC request blocks the number across all campaigns. - Campaign DNC = Y where needed. Use campaign DNC for product-specific opt-outs only — situations where a consumer opts out of one product but consents to another.
How Numbers Enter the Internal DNC Table
Numbers get into vicidial_dnc through five paths:
- Manual entry via admin: Admin > DNC Numbers > Add DNC Number
- Agent disposition: When an agent dispositions with a DNC-flagged status (if configured — see below)
-
API insertion:
non_agent_api.php?function=add_dnc_phone&phone_number=5551234567 - Bulk import via admin: Admin > DNC Numbers > Load DNC Numbers from File
- Script import: Batch operations through your pre-import scrubbing pipeline
To verify a number's DNC status:
SELECT phone_number FROM vicidial_dnc WHERE phone_number = '5551234567';
If a row is returned, the number is blocked system-wide. Empty result means not on internal DNC (but it could still be on a campaign-level DNC list or on the federal/state registries that you scrub externally).
The DNCL Disposition Trap
When an agent dispositions a call with a DNC-flagged status, VICIdial should automatically add the number to the DNC table. But this only works if the disposition status has the dnc flag set to Y. This is one of the most common compliance failures I see:
SELECT status, status_name, human_answered, dnc
FROM vicidial_statuses
WHERE status IN ('DNCL', 'DNC', 'DNCC', 'OPTOUT');
If dnc = 'N' on any of those statuses, agents are using the disposition but nothing happens in the database. The number stays dialable. The disposition exists, agents select it every day, management thinks DNC is being handled — but the flag isn't set, so the internal DNC table never gets updated.
Also check campaign-level statuses:
SELECT status, status_name, dnc, campaign_id
FROM vicidial_campaign_statuses
WHERE status IN ('DNCL', 'DNC', 'DNCC', 'OPTOUT')
ORDER BY campaign_id;
The Hopper Timing Gap
DNC checking happens during hopper loading — before calls are placed. But there's a window between when a number is added to the DNC table and when the hopper excludes it. If a number is already in the hopper when the DNC entry is created, it remains dialable until the hopper refreshes.
For compliance-critical operations, flush the hopper after bulk DNC imports:
DELETE FROM vicidial_hopper WHERE campaign_id = 'YOURCAMPAIGN';
Brief pause in dialing while the hopper repopulates. Better than a violation.
Real-Time DNC via API
For DNC requests from external sources (web forms, CRM systems, email opt-outs):
curl -s "https://your-vicidial-server/vicidial/non_agent_api.php?\
source=compliance&\
function=add_dnc_phone&\
user=api_user&\
pass=api_pass&\
phone_number=5551234567"
Takes effect on the next hopper refresh — typically within seconds.
Campaign Configuration Audit
Run this query weekly to find campaigns with DNC checking disabled:
SELECT campaign_id, campaign_name,
use_internal_dnc, use_campaign_dnc
FROM vicidial_campaigns
WHERE active = 'Y'
AND (use_internal_dnc = 'N' OR use_campaign_dnc = 'N');
Every row returned is a compliance gap. Fix immediately.
For multi-campaign environments, a consumer who says "take me off your list" expects to stop receiving calls from your entire organization. Configure DNCL disposition to add to the system-wide vicidial_dnc table so it blocks across all campaigns. Use campaign DNC only for product-specific opt-outs.
Cell Phone Considerations
VICIdial's predictive dialer qualifies as an ATDS under most state definitions. Calling cell phones for telemarketing requires prior express written consent. VICIdial doesn't natively distinguish between landline and cell phone numbers — you need an external phone type append service (Neustar, Melissa Data, TeleSign) to identify wireless numbers before import.
The FCC's Reassigned Numbers Database (RND) adds another layer: phone numbers get reassigned to new consumers whose consent you never obtained. Checking the RND provides a safe harbor defense against TCPA claims from new number holders.
Wireless Numbers and Cell Phone Compliance
Cell phones add another layer. Under the TCPA, calling or texting a cell phone using an automatic telephone dialing system (ATDS) or prerecorded voice requires prior express consent — and for telemarketing, prior express written consent. VICIdial's predictive dialer qualifies as an ATDS under most definitions.
VICIdial doesn't natively distinguish between landline and cell phone numbers. You need an external phone type append service — Neustar, Melissa Data, TeleSign — to identify wireless numbers before import. Without written consent, cell phone numbers should be treated as effectively DNC even if they're not on any DNC list.
Reassigned Numbers
The FCC's Reassigned Numbers Database (RND) addresses a chronic problem: phone numbers get reassigned to new consumers, but the new consumer never consented to your calls. The previous consumer's consent doesn't transfer. Checking the RND provides a safe harbor defense — if the RND confirms the number hasn't been reassigned since consent was obtained, you have an affirmative defense against TCPA claims from the new holder.
Integrate RND checking into your scrubbing pipeline: register for access, query with phone numbers and consent dates, flag reassigned numbers, and remove them from VICIdial lists or add to internal DNC.
Daily Call Limits as a DNC Complement
DNC management works hand-in-hand with call frequency limits. A consumer receiving five calls in a single day is far more likely to file a complaint — and in states like Florida, calling the same number more than three times in 24 hours is a per-call violation regardless of DNC status.
Configure daily call limits on all campaigns as a complement to DNC filtering. The daily call limit prevents over-calling numbers that haven't opted out. The DNC list prevents any calling of numbers that have opted out. Both are necessary.
The Audit Trail VICIdial Doesn't Give You
VICIdial's vicidial_dnc table stores phone numbers but no metadata — no timestamp, no source, no who-added-it. When the FTC opens an investigation, the first thing they want is documentation: dates, records, proof of every scrub, every DNC addition, every process.
You need to augment VICIdial's native tracking with a separate scrub log that records scrub dates, sources, record counts, numbers removed, and who performed each operation. The queries and table structure shown above give you the starting point.
Building What VICIdial Doesn't Provide
VICIdial's vicidial_dnc table stores phone numbers but no metadata — no timestamp, no source, no who-added-it. For compliance documentation, build a supplemental tracking table:
CREATE TABLE IF NOT EXISTS vicistack_dnc_audit (
audit_id INT AUTO_INCREMENT PRIMARY KEY,
phone_number VARCHAR(18) NOT NULL,
dnc_type ENUM('internal', 'campaign', 'federal', 'state') NOT NULL,
campaign_id VARCHAR(8),
source ENUM('agent_dispo', 'api', 'web_optout', 'manual', 'scrub') NOT NULL,
added_by VARCHAR(50),
added_date DATETIME DEFAULT CURRENT_TIMESTAMP,
notes TEXT,
INDEX idx_phone (phone_number),
INDEX idx_date (added_date)
);
Every time a number enters your DNC table — whether from agent disposition, API call, web opt-out form, or bulk scrub — log it here with the source and timestamp. When the FTC asks for documentation, you can produce a complete audit trail showing exactly when each number was added, by whom, and through what process.
Document your scrub procedures in writing: which lists get scrubbed, how often, against which DNC sources, who performs it, where the DNC data comes from, and what happens to rejected numbers. Keep this document updated. It's your evidence of having a systematic compliance process, which matters as much as the actual scrubbing when regulators evaluate your operation.
Run the campaign DNC configuration audit weekly. Automate it with a cron job that emails you the results:
#!/bin/bash
# /opt/vicidial-reports/dnc_audit.sh — run weekly via cron
GAPS=$(mysql -u reports -p'password' asterisk -N -e "
SELECT campaign_id, campaign_name, use_internal_dnc, use_campaign_dnc
FROM vicidial_campaigns
WHERE active = 'Y'
AND (use_internal_dnc = 'N' OR use_campaign_dnc = 'N');")
if [ -n "$GAPS" ]; then
echo "DNC COMPLIANCE GAPS FOUND:" | \
mail -s "WARNING: VICIdial DNC Configuration Gaps" compliance@yourcenter.com <<EOF
The following active campaigns have DNC checking disabled:
$GAPS
Fix immediately — each call to a DNC-listed number is a potential violation.
EOF
fi
Also audit your DNCL dispositions monthly to verify numbers are actually being added to the DNC table. Compare the count of DNCL-dispositioned calls in vicidial_log against recent additions to vicidial_dnc. If agents dispositioned 50 calls as DNCL this month but only 10 numbers were added to the DNC table, something is misconfigured. The DNC flag on one of your disposition statuses is probably set to N.
If any active campaign shows use_internal_dnc = 'N', you want to know about it before a plaintiff attorney does.
The Cost of Not Getting This Right
Let's do the math. A third-party DNC scrubbing service at $0.003 per number costs $300 for a 100,000-number list. Scrubbing monthly costs $3,600/year. State DNC registrations across the 12 states listed above cost approximately $2,000-$4,000/year total. Building and maintaining the audit trail infrastructure takes a few hours of setup and minutes of ongoing maintenance.
Total annual DNC compliance cost for a typical mid-size operation: $5,000-$10,000.
A single TCPA class action settlement for DNC violations: $500,000 to $10,000,000+. The math is not close. The compliance investment is a rounding error compared to the litigation risk.
DNC compliance isn't exciting work. But one lawsuit costs more than years of proper compliance tooling. ViciStack configures DNC enforcement, scrub scheduling, and audit trail documentation for every deployment we manage — because the cost of getting it wrong dwarfs the cost of getting it right.
Originally published at https://vicistack.com/blog/vicidial-dnc-management/
Top comments (0)