← All Tutorials

How to Manage ViciDial Lists: Deactivate, Reset & Delete Leads

Monitoring & Observability Intermediate 13 min read #100 Published · Updated

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

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:

Related flags in the same table:

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.

  1. Navigate to Admin Leads (e.g., http://your-vicidial-server/vicidial/admin.php).
  2. Select your List from the dropdown.
  3. Use the Search form to find the lead by phone, name, or ID.
  4. Click the lead row to open its detail page.
  5. Change Status to DEAD.
  6. Set "Do Not Call" flag if you want to block it from future list reloads.
  7. 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:

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:

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:

  1. Orphaned call logs: A vicidial_log record pointing to a deleted lead_id cannot be joined back.
  2. Broken callbacks: If a callback is scheduled for a deleted lead_id, it will fail.
  3. 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:

  1. Note the list_id.
  2. Delete all leads in that list: DELETE FROM vicidial_list WHERE list_id = 101;
  3. 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.

Stuck on something specific?

Book a free 30-minute call. I run ViciDial centers across 3 countries and can usually unblock your setup in one session — or build it for you.

Book a Free Consultation