Remove, reset, or purge unwanted contacts from ViciDial lists without corrupting call logs or orphaning agent records.
List management in ViciDial requires direct database access combined with understanding how leads link to call logs, agent activity, and callbacks. Deactivating a lead preserves history; resetting a lead clears its attempt count and status; deleting a lead removes it entirely but risks breaking referential integrity if done carelessly. This guide shows the exact SQL, CLI commands, and web interface steps to manage each operation safely.
Tested on ViciDial 2.14 (SVN 3555+) and 2.13, Asterisk 16/18, MariaDB 10.5+, PHP 7.4+.
Prerequisites
- SSH access to the ViciDial server or a machine with remote MySQL client installed.
- MySQL or MariaDB command-line client (mysql) or a GUI tool like DBeaver or phpMyAdmin.
- Database credentials with SELECT, UPDATE, DELETE on the asterisk database.
- Understanding of ViciDial list IDs (numeric identifiers for campaigns/lists).
- A backup of the asterisk database taken within the last 24 hours.
- Agent or admin access to the web interface at /vicidial/admin.php.
- Knowledge of which leads are tied to active callbacks or scheduled follow-ups.
Understanding ViciDial lead status codes
Before modifying leads, know what each status means in the vicidial_list table.
The status field controls whether an agent can dial a lead:
- NEW: Untouched, ready to dial.
- ACTIVE: Currently being worked.
- DEAD: Permanently removed from dialing queue (do not call, duplicate, bad number).
- INBOUND: Reserved for inbound transfers.
- QUEUE: Waiting for agent availability.
- PAUSE: Temporarily held.
Related flags in the same table:
- Called: 0 = never called, 1 = called at least once. Resetting this is what "resetting" a lead means.
- Phone: The phone number string (E.164 format preferred: +1-555-0101).
- Lead_id: Auto-incremented primary key, unique per list.
- List_id: Foreign key linking to vicidial_lists.
The vicidial_log table records every call attempt. Deleting a lead does not automatically delete its logs, so historical call data remains for reporting and compliance.
Deactivating leads through the web interface
The simplest method for small volumes (10-100 leads) is the ViciDial admin panel.
- Navigate to Admin Leads (e.g., http://your-vicidial-server/vicidial/admin.php).
- Select your List from the dropdown.
- Use the Search form to find the lead by phone, name, or ID.
- Click the lead row to open its detail page.
- Change Status to DEAD.
- Set "Do Not Call" flag if you want to block it from future list reloads.
- Save.
This marks the lead as DEAD in vicidial_list.status, preventing agents from dialing it. The lead remains in the database for audit purposes. Call logs stay intact.
Use this method when:
- You are removing a single lead or a handful.
- You need a timestamp audit trail (ViciDial logs admin actions).
- You want agent feedback recorded (notes field).
For bulk operations, use the database directly (see below).
Deactivating leads in bulk with SQL
To deactivate 100+ leads at once, use direct SQL. This is 100 times faster than the web interface.
Step 1: Identify the list ID and lead range.
SELECT list_id, list_name, active FROM vicidial_lists
WHERE list_name LIKE 'Campaign_Q4%';
Note the list_id (e.g., 101).
Step 2: Deactivate leads by phone number pattern.
UPDATE vicidial_list
SET status = 'DEAD', called = 1
WHERE list_id = 101
AND phone LIKE '555%';
This marks all leads in list 101 with phone numbers starting in 555 as DEAD. The called = 1 ensures they appear in reporting as "attempted".
Step 3: Verify the change.
SELECT count(*), status FROM vicidial_list
WHERE list_id = 101
GROUP BY status;
Example output:
count(*) status
------- -------
4521 NEW
512 DEAD
189 PAUSE
Common deactivation scenarios:
Deactivate all leads in a list:
UPDATE vicidial_list SET status = 'DEAD' WHERE list_id = 101;
Deactivate leads with invalid phone numbers:
UPDATE vicidial_list SET status = 'DEAD'
WHERE list_id = 101 AND (phone IS NULL OR phone = '' OR length(phone) < 10);
Deactivate leads marked as duplicate in notes:
UPDATE vicidial_list SET status = 'DEAD'
WHERE list_id = 101 AND comments LIKE '%duplicate%';
Deactivate leads not called in 30 days:
UPDATE vicidial_list SET status = 'DEAD'
WHERE list_id = 101
AND last_local_call_time < DATE_SUB(NOW(), INTERVAL 30 DAY);
After any bulk update, always run the verification query to confirm the count.
Resetting leads (clearing attempts and status)
Resetting a lead removes its call history and attempt counter, returning it to NEW status. This re-queues it for dialing without losing the contact record itself.
Use reset when:
- An agent dialed a number by mistake (robocall or wrong extension).
- A lead was marked DEAD but is actually reachable (bad skip trace).
- You want to retry a lead that failed several times.
Reset a single lead by ID:
UPDATE vicidial_list SET status = 'NEW', called = 0
WHERE lead_id = 4521;
Reset all leads in a list that are currently PAUSE or DEAD:
UPDATE vicidial_list SET status = 'NEW', called = 0
WHERE list_id = 101 AND status IN ('PAUSE', 'DEAD');
Reset leads that have not been called in the last 60 days:
UPDATE vicidial_list SET status = 'NEW', called = 0
WHERE list_id = 101
AND (last_call_time IS NULL OR last_call_time < DATE_SUB(NOW(), INTERVAL 60 DAY));
Do not reset the entire active_in_list or priority fields; those control dialing order and should remain intact.
Resetting does not delete call logs. The lead's history in vicidial_log remains for compliance. You are only clearing the queuing state.
Deleting leads permanently
Permanent deletion removes a lead entirely from the vicidial_list table. Use this only when you are certain the lead should never appear in reports or callbacks.
Risks of deleting:
- Orphaned call logs: A vicidial_log record pointing to a deleted lead_id cannot be joined back.
- Broken callbacks: If a callback is scheduled for a deleted lead_id, it will fail.
- Compliance issues: You lose the record that a contact was in your system.
For these reasons, deactivation (DEAD status) is safer than deletion in most cases.
Delete a single lead (verify first):
-- Check for callbacks
SELECT callback_id, lead_id, callback_date FROM vicidial_callbacks
WHERE lead_id = 4521;
-- If none, delete
DELETE FROM vicidial_list WHERE lead_id = 4521;
Delete leads that were never called:
DELETE FROM vicidial_list
WHERE list_id = 101
AND called = 0
AND status = 'NEW';
Delete duplicate phone numbers (keep the first occurrence):
DELETE FROM vicidial_list
WHERE lead_id NOT IN (
SELECT MIN(lead_id) FROM vicidial_list
WHERE list_id = 101
GROUP BY phone
) AND list_id = 101;
Before running any DELETE, always take a backup:
mysqldump -u asterisk -p asterisk vicidial_list > /tmp/vicidial_list_backup_$(date +%s).sql
Then run the DELETE in a transaction so you can roll back if needed:
START TRANSACTION;
DELETE FROM vicidial_list
WHERE list_id = 101 AND called = 0 AND status = 'NEW';
-- Check affected rows
SELECT ROW_COUNT();
-- If correct, commit
COMMIT;
-- If wrong, ROLLBACK;
Purging call logs for deleted leads
If you delete leads, their call logs remain in vicidial_log. To clean them up:
DELETE FROM vicidial_log
WHERE lead_id NOT IN (SELECT lead_id FROM vicidial_list);
This removes any orphaned log entries. Run this once per month if you delete leads regularly.
Check how many rows will be affected first:
SELECT count(*) FROM vicidial_log
WHERE lead_id NOT IN (SELECT lead_id FROM vicidial_list);
On a large system (millions of logs), this query can take minutes. Use it during low-traffic windows (2-4 AM).
Resetting call attempt counters
ViciDial tracks call attempts per lead in the vicidial_log table. Some lists use custom attempt limits (e.g., dial 5 times, then move to DEAD). If you want to allow more attempts without fully resetting the lead, clear the attempt count.
The vicidial_log.lead_id and vicidial_log.list_id combination forms the basis for attempt counting. To allow a lead to be dialed again without losing history:
UPDATE vicidial_list
SET called = 0
WHERE list_id = 101 AND lead_id IN (
SELECT DISTINCT lead_id FROM vicidial_log
WHERE list_id = 101 AND call_date > DATE_SUB(NOW(), INTERVAL 7 DAY)
);
This resets the called flag for leads called in the last 7 days, letting them dial again. The call logs remain for reporting.
Bulk importing and list resets
When you import a new lead list via the web interface (Admin Leads, Upload), ViciDial assigns new lead_ids and calculates the next_state. If you want to reload the same list (e.g., after adding new fields), you must first reset or delete the old list.
To reload a list:
- Note the list_id.
- Delete all leads in that list:
DELETE FROM vicidial_list WHERE list_id = 101; - Re-import the list via the web interface.
Alternatively, use the command-line script:
/usr/share/astguiclient/ADMIN_manual_list_reset.pl \
--list-id 101 \
--campaign Outbound_Q4
This script safely resets the list, clearing all leads and resetting attempt counts. Check the script logs:
tail -f /var/log/astguiclient/ADMIN_manual_list_reset.log
Using the CLI for list diagnostics
Query the ViciDial database from the command line without entering MySQL:
mysql -u asterisk -p asterisk -e \
"SELECT lead_id, phone, status, called FROM vicidial_list WHERE list_id = 101 LIMIT 10;"
Get a count by status:
mysql -u asterisk -p asterisk -e \
"SELECT status, count(*) as count FROM vicidial_list WHERE list_id = 101 GROUP BY status;"
Find leads with callback scheduled:
mysql -u asterisk -p asterisk -e \
"SELECT lead_id, callback_date, callback_notes FROM vicidial_callbacks \
WHERE callback_date > NOW() ORDER BY callback_date LIMIT 20;"
Check for active agents on a list:
mysql -u asterisk -p asterisk -e \
"SELECT user, status, lead_id FROM vicidial_agent_status \
WHERE campaign = 'Outbound_Q4' AND status != 'OFFLINE';"
Connect to the Asterisk console to see if agents are paused or active:
asterisk -rx "vicidial show agents"
Hangup an agent's call:
asterisk -rx "channel request hangup SIP/2001"
Troubleshooting
Problem: Leads won't queue after resetting.
Check if the list itself is active:
SELECT active, campaign FROM vicidial_lists WHERE list_id = 101;
If active = 0, the list is paused. Set active = 1 to resume.
Problem: Deleted leads still appear in agent screen.
Agents may have cached the lead list in browser memory. Have them log out and log back in, or clear the browser cache.
Problem: Call logs show lead_id that no longer exists.
This is normal if you deleted leads after calls. To prevent orphaned logs in the future, use DEAD status instead of DELETE.
To see orphaned leads:
SELECT DISTINCT vl.lead_id FROM vicidial_log vl
LEFT JOIN vicidial_list vl2 ON vl.lead_id = vl2.lead_id
WHERE vl2.lead_id IS NULL LIMIT 20;
Problem: Bulk deactivation query timed out.
The vicidial_list table may lack indexes on frequently filtered columns. Add an index:
ALTER TABLE vicidial_list ADD INDEX idx_list_status (list_id, status);
Then retry the query.
Problem: Web interface is slow after bulk update.
ViciDial caches list state in memory. Restart the astguiclient services:
systemctl restart astguiclient
Wait 30 seconds for caches to rebuild.
Problem: Attempting to delete a lead returns foreign key constraint error.
A callback, inbound transfer, or agent note references this lead. Find and remove those references first:
SELECT * FROM vicidial_callbacks WHERE lead_id = 4521;
SELECT * FROM vicidial_inbound_anicode WHERE lead_id = 4521;
SELECT * FROM vicidial_agent_notes WHERE lead_id = 4521;
Delete or reassign those rows, then try deleting the lead again.
Frequently asked questions
Why does ViciDial mark calls as DEAD automatically?
ViciDial can be configured to auto-mark a lead as DEAD after a certain number of failed attempts (no answer, wrong number, answering machine). This is set in the campaign's dialer settings. If you want to disable auto-DEAD, go to Admin Campaigns, select your campaign, and set "Max attempts" to a high number (e.g., 999) or use a custom status like PAUSE instead. Leads marked DEAD manually will not be re-queued unless you reset them.
Can I export a list of deactivated leads?
Yes. Use the web interface (Admin Leads, Export) to download the list as CSV, or run a MySQL query and pipe it to a file: mysql -u asterisk -p asterisk -e "SELECT * FROM vicidial_list WHERE list_id = 101 AND status = 'DEAD';" > /tmp/deactivated_leads.txt. The CSV export includes all fields and can be reimported into another system for compliance records.
What happens to agent statistics if I delete a lead?
Deleting a lead does not erase the agent's call history or stats. The vicidial_closer_log records agent performance (talk time, dials, disposition). If you delete the lead after the call, the log entry remains but the agent can no longer view the lead's details in the agent screen. For this reason, use DEAD status instead of deletion if you want to preserve agent accountability.
Can I restore a deleted lead from backup?
Yes, but only if you have a database backup taken before the deletion. Restore the backup to a new database, extract the deleted lead row, and insert it into the production database. ViciDial does not have a trash/undelete feature for individual leads. Always backup before bulk delete operations: mysqldump -u asterisk -p asterisk vicidial_list > /tmp/backup.sql.
How do I reset leads without stopping active dialing?
Use the database directly (SQL UPDATE statements). Web interface resets may lock the list temporarily. When updating with SQL, the change takes effect immediately without stopping agents. However, agents who are already dialing a lead will not see the reset until they finish the call and the system refreshes the lead state (usually within 2-3 seconds).
Summary
You can now deactivate, reset, or delete leads in ViciDial using three approaches: the web interface for single leads and auditing, SQL UPDATE for bulk deactivation, and SQL DELETE for permanent removal (use sparingly). Deactivation (DEAD status) is the safest choice in production because it preserves call logs and agent accountability while removing leads from the dialing queue. Resetting clears the attempt counter and status, re-queuing a lead without losing history. Deleting is permanent and risks breaking callbacks and orphaning logs.
Always back up the database before bulk operations. Use START TRANSACTION and ROLLBACK if a query affects more rows than expected. After any bulk change, verify counts with SELECT queries and test with a single agent before resuming full-scale dialing. Run orphan log cleanup (DELETE from vicidial_log WHERE lead_id NOT IN...) monthly if you delete leads regularly, and add database indexes if bulk updates time out on large lists (100k+ leads).
Next steps: review the dialer campaign settings to confirm max-attempt rules are aligned with your deactivation policy, set up a monthly backup cron job if you have not already, and test a reset on a single lead during a quiet period to verify behavior matches your expectations.