VICIdial Optimization

VICIdial API Integration Examples

ViciStack Team · · 11 min read
VICIdial integration examples

Last updated: March 2026 | Reading time: ~28 minutes

VICIdial has two APIs that most people know exist but few people use well. The Non-Agent API handles backend automation — pushing leads, pulling reports, scheduling callbacks. The Agent API controls what happens on the agent screen — pausing, dialing, transferring, dispositioning.

Together, they let you build practically anything on top of VICIdial: CRM integrations, real-time dashboards, automated lead routing, web-to-lead forms, callback scheduling systems, and custom reporting pipelines.

The official documentation (NON-AGENT_API.txt and AGENT_API.txt) is thorough but written in the style of a 2008-era Unix man page — technically complete, practically incomprehensible if you’re just trying to add a lead from a web form. So here’s the practical version with real code examples in curl, Python, PHP, and Node.js.


API Basics

Endpoint URLs

Both APIs are accessed via HTTP GET or POST to PHP scripts on your VICIdial web server:

  • Non-Agent API: https://YOUR-SERVER/vicidial/non_agent_api.php
  • Agent API: https://YOUR-SERVER/agc/api.php

Always use HTTPS in production. If your VICIdial server doesn’t have an SSL certificate, set one up before exposing the API.

Authentication

Every API call requires two parameters:

  • user — A valid VICIdial user account
  • pass — The user’s password

The user must have API access enabled in their account settings. In the VICIdial Admin GUI:

  1. Go to Admin > Users
  2. Edit the API user
  3. Set user_level to 8 or higher (7 for limited functions)
  4. Enable modify_leads (for lead-related functions)
  5. Under Allowed API Functions, check the functions you want to allow
  6. Set API IP Restrictions to limit which IPs can make API calls (do this)

Response Format

The API returns plain text responses. Successful calls return data starting with SUCCESS: and failures start with ERROR: or NOTICE:. Some functions support JSON output by adding &header=YES to the request.


Non-Agent API: Lead Management

add_lead — Insert a New Lead

This is the most-used API function. Your web forms, CRM imports, and lead vendors push leads into VICIdial through this endpoint.

Minimum required parameters:

  • source — Identifier for the API source (for logging)
  • function=add_lead
  • phone_number — 10-digit phone number
  • list_id — The VICIdial list to add the lead to

curl example:

curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=webform&\
user=apiuser&\
pass=API_PASSWORD&\
function=add_lead&\
phone_number=3125551234&\
list_id=10001&\
first_name=John&\
last_name=Smith&\
address1=123+Main+St&\
city=Chicago&\
state=IL&\
postal_code=60601&\
email=john@example.com&\
vendor_lead_code=CRM-98765"

Response on success:

SUCCESS: add_lead LEAD HAS BEEN ADDED - 12345678|10001|3125551234|CRM-98765

The number 12345678 is the lead_id — save this for future API calls.

Python example:

import requests

api_url = "https://YOUR-SERVER/vicidial/non_agent_api.php"
params = {
 "source": "crm_sync",
 "user": "apiuser",
 "pass": "API_PASSWORD",
 "function": "add_lead",
 "phone_number": "3125551234",
 "list_id": "10001",
 "first_name": "John",
 "last_name": "Smith",
 "city": "Chicago",
 "state": "IL",
 "postal_code": "60601",
 "vendor_lead_code": "CRM-98765",
 "custom_fields": "Y",
 "cf_company_size": "50-100",
 "cf_industry": "manufacturing",
}

response = requests.get(api_url, params=params, verify=True, timeout=10)
print(response.text)

if "SUCCESS" in response.text:
 lead_id = response.text.split("|")[0].split(" - ")[1]
 print(f"Lead created: {lead_id}")

PHP example:

<?php
$api_url = "https://YOUR-SERVER/vicidial/non_agent_api.php";
$params = http_build_query([
 'source' => 'crm_sync',
 'user' => 'apiuser',
 'pass' => 'API_PASSWORD',
 'function' => 'add_lead',
 'phone_number' => '3125551234',
 'list_id' => '10001',
 'first_name' => 'John',
 'last_name' => 'Smith',
 'vendor_lead_code' => 'CRM-98765',
]);

$response = file_get_contents("$api_url?$params");

if (strpos($response, 'SUCCESS') !== false) {
 preg_match('/- (\d+)\|/', $response, $matches);
 $lead_id = $matches[1];
 echo "Lead created: $lead_id\n";
}
?>

Node.js example:

const https = require('https');
const querystring = require('querystring');

const params = querystring.stringify({
 source: 'crm_sync',
 user: 'apiuser',
 pass: 'API_PASSWORD',
 function: 'add_lead',
 phone_number: '3125551234',
 list_id: '10001',
 first_name: 'John',
 last_name: 'Smith',
 vendor_lead_code: 'CRM-98765',
});

const url = `https://YOUR-SERVER/vicidial/non_agent_api.php?${params}`;

https.get(url, (res) => {
 let data = '';
 res.on('data', chunk => data += chunk);
 res.on('end', () => {
 console.log(data);
 if (data.includes('SUCCESS')) {
 const leadId = data.split(' - ')[1].split('|')[0];
 console.log(`Lead created: ${leadId}`);
 }
 });
}).on('error', console.error);

add_lead with Callback Scheduling

One of the most powerful features: inject a lead AND schedule a callback in a single API call. Perfect for web-to-lead forms where the customer requests a specific call-back time.

curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=webform&\
user=apiuser&\
pass=API_PASSWORD&\
function=add_lead&\
phone_number=3125551234&\
list_id=10001&\
first_name=Jane&\
last_name=Doe&\
callback=Y&\
campaign_id=SALES01&\
callback_status=CALLBK&\
callback_datetime=2026-03-27+14:30:00&\
callback_type=ANYONE&\
callback_comments=Requested+callback+after+2pm+CT"

Key callback parameters:

  • callback=Y — Enables callback scheduling
  • campaign_id — Which campaign the callback appears in (required when callback=Y)
  • callback_datetime — Use YYYY-MM-DD+HH:MM:SS format (use NOW for immediate)
  • callback_typeANYONE (any agent) or USERONLY (specific agent)
  • callback_user — Required if callback_type is USERONLY
  • callback_status — Default is CALLBK, the lead’s status gets set to CBHOLD

update_lead — Modify Existing Leads

Update lead data, change statuses, or add callback information to existing leads. You need either the lead_id or a combination of vendor_lead_code + phone_number to identify the lead.

curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=crm_sync&\
user=apiuser&\
pass=API_PASSWORD&\
function=update_lead&\
lead_id=12345678&\
address1=456+Oak+Ave&\
city=Chicago&\
email=jane.updated@example.com&\
custom_fields=Y&\
cf_company_size=100-250"

Update by vendor_lead_code (useful when your CRM doesn’t store VICIdial lead_ids):

curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=crm_sync&\
user=apiuser&\
pass=API_PASSWORD&\
function=update_lead&\
vendor_lead_code=CRM-98765&\
search_method=VENDOR_LEAD_CODE&\
address1=456+Oak+Ave"

lead_status_search — Find Leads by Status

Search for leads with a specific disposition status. Useful for building reports or syncing disposition data back to your CRM.

curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=reporting&\
user=apiuser&\
pass=API_PASSWORD&\
function=lead_status_search&\
status=SALE&\
list_id=10001&\
date=2026-03-26&\
header=YES"

Non-Agent API: Campaign and System Functions

recording_lookup — Pull Call Recordings

Retrieve recording URLs for a specific lead or date range. Essential for CRM integration where reps need to listen to calls.

curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=crm&\
user=apiuser&\
pass=API_PASSWORD&\
function=recording_lookup&\
lead_id=12345678&\
header=YES"

The response includes recording file paths that you can serve via HTTP. Make sure your web server is configured to serve files from the recording directory.

agent_stats_export — Pull Agent Performance Data

Export agent statistics for a date range. Perfect for feeding data into external BI tools.

curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=bi_tool&\
user=apiuser&\
pass=API_PASSWORD&\
function=agent_stats_export&\
datetime_start=2026-03-20+00:00:00&\
datetime_end=2026-03-26+23:59:59&\
campaign_id=SALES01&\
header=YES"

Agent API: Controlling the Agent Screen

The Agent API is different from the Non-Agent API. It controls active agent sessions — the same actions an agent performs by clicking buttons on the VICIdial agent web interface.

Endpoint: https://YOUR-SERVER/agc/api.php

Each Agent API call requires the agent_user parameter identifying which agent session to control.

Pausing and Unpausing Agents

Programmatically pause agents from an external system (workforce management, break scheduling, etc.):

# Pause agent with pause code BREAK
curl -s "https://YOUR-SERVER/agc/api.php?\
source=wfm&\
user=apiuser&\
pass=API_PASSWORD&\
agent_user=agent001&\
function=pause_agent&\
value=PAUSE&\
pause_code=BREAK"

# Unpause agent (resume dialing)
curl -s "https://YOUR-SERVER/agc/api.php?\
source=wfm&\
user=apiuser&\
pass=API_PASSWORD&\
agent_user=agent001&\
function=pause_agent&\
value=RESUME"

External Dial — Originate a Call

Trigger a manual dial from an external system. The agent’s screen gets populated and the call connects through the normal VICIdial call flow.

curl -s "https://YOUR-SERVER/agc/api.php?\
source=crm&\
user=apiuser&\
pass=API_PASSWORD&\
agent_user=agent001&\
function=external_dial&\
value=3125551234&\
lead_id=12345678&\
phone_code=1&\
search=YES&\
preview=NO&\
focus=YES"

Parameters:

  • value — Phone number to dial
  • lead_id — Associate with existing lead (optional)
  • search=YES — Search for existing lead by phone number
  • preview=NO — Dial immediately (YES shows preview first)
  • focus=YES — Bring the agent screen into focus

External Transfer

Transfer the active call to another number or extension:

curl -s "https://YOUR-SERVER/agc/api.php?\
source=crm&\
user=apiuser&\
pass=API_PASSWORD&\
agent_user=agent001&\
function=transfer_conference&\
value=BLIND_TRANSFER&\
phone_number=3125559876&\
consultative=NO"

Set Disposition

Programmatically set the disposition from an external system after the call ends:

curl -s "https://YOUR-SERVER/agc/api.php?\
source=crm&\
user=apiuser&\
pass=API_PASSWORD&\
agent_user=agent001&\
function=external_status&\
value=SALE&\
callback=NO"

Building a Web-to-Lead Integration

Here’s a complete example: a web form on your marketing site pushes leads directly into VICIdial for immediate dialing. The famous “speed to lead” — the faster you call a web lead, the higher the conversion rate. Under 5 minutes is the target.

The Form Handler (PHP)

<?php
# web-to-lead.php -- Receives form submissions, pushes to VICIdial

$VICIDIAL_SERVER = "https://dialer.yourcompany.com";
$API_USER = "webform_api";
$API_PASS = "SECURE_PASSWORD";
$LIST_ID = "10001";
$CAMPAIGN_ID = "WEBLEAD";

# Sanitize input
$phone = preg_replace('/[^0-9]/', '', $_POST['phone']);
$first = substr(strip_tags($_POST['first_name']), 0, 30);
$last = substr(strip_tags($_POST['last_name']), 0, 30);
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);

if (strlen($phone) !== 10) {
 http_response_code(400);
 echo json_encode(['error' => 'Invalid phone number']);
 exit;
}

# Push to VICIdial
$params = http_build_query([
 'source' => 'website',
 'user' => $API_USER,
 'pass' => $API_PASS,
 'function' => 'add_lead',
 'phone_number' => $phone,
 'list_id' => $LIST_ID,
 'first_name' => $first,
 'last_name' => $last,
 'email' => $email,
 'vendor_lead_code' => 'WEB-' . time(),
 'callback' => 'Y',
 'campaign_id' => $CAMPAIGN_ID,
 'callback_status' => 'CALLBK',
 'callback_datetime' => 'NOW',
 'callback_type' => 'ANYONE',
 'callback_comments' => 'Web form submission - call immediately',
]);

$ctx = stream_context_create(['http' => ['timeout' => 10]]);
$response = file_get_contents("$VICIDIAL_SERVER/vicidial/non_agent_api.php?$params", false, $ctx);

if (strpos($response, 'SUCCESS') !== false) {
 echo json_encode(['status' => 'ok', 'message' => 'We will call you shortly']);
} else {
 error_log("VICIdial API error: $response");
 echo json_encode(['status' => 'ok', 'message' => 'We will call you shortly']);
 # Still show success to user, handle API errors internally
}
?>

The key trick: callback=Y with callback_datetime=NOW and callback_type=ANYONE creates an immediate callback that the next available agent picks up. The lead gets called within seconds of form submission — not minutes, not hours.

CRM Webhook: Sync Dispositions Back

After a VICIdial agent disposes a call, you want that data in your CRM. VICIdial supports URL-based event triggers that fire on disposition.

In the VICIdial Admin GUI:

  1. Go to Campaigns > Campaign Settings
  2. Find Dispo Call URL
  3. Enter your webhook endpoint:
https://your-crm.com/api/vicidial-webhook?lead_id=--A--lead_id--B--&status=--A--dispo--B--&agent=--A--user--B--&phone=--A--phone_number--B--&talk_time=--A--talk_epoch--B--&vendor_code=--A--vendor_lead_code--B--

The --A--field_name--B-- tags get replaced with actual call data when the webhook fires. Your CRM endpoint receives a GET request with all the call details and can update the lead record accordingly.

Python webhook receiver (Flask):

from flask import Flask, request
import json

app = Flask(__name__)

@app.route('/api/vicidial-webhook', methods=['GET'])
def handle_disposition():
 lead_id = request.args.get('lead_id')
 status = request.args.get('status')
 agent = request.args.get('agent')
 phone = request.args.get('phone')
 talk_time = request.args.get('talk_time')
 vendor_code = request.args.get('vendor_code')

 # Update your CRM
 crm_update = {
 'vicidial_lead_id': lead_id,
 'disposition': status,
 'called_by': agent,
 'phone': phone,
 'talk_seconds': talk_time,
 }

 # Your CRM API call here
 print(f"Updating CRM for {vendor_code}: {json.dumps(crm_update)}")

 return 'OK', 200

if __name__ == '__main__':
 app.run(host='0.0.0.0', port=8080)

API Security Best Practices

1. Dedicated API User Accounts

Never use an admin account for API access. Create dedicated users with minimal permissions:

  • Web form import user: Only add_lead function enabled
  • CRM sync user: add_lead, update_lead, recording_lookup
  • Reporting user: Only read-only functions

2. IP Restrictions

Set API IP restrictions on every API user account. Your web server and CRM have known IPs — lock the API down to only those IPs.

3. HTTPS Only

Never send API credentials over HTTP. The user/pass parameters travel in the URL query string (or POST body), and without TLS they’re visible to anyone sniffing the network.

4. Rate Limiting

VICIdial doesn’t have built-in API rate limiting. If your web form gets hit by a bot, it’ll flood your VICIdial with garbage leads. Implement rate limiting at the form level (CAPTCHA, throttling) or at the web server level (nginx rate limiting).

5. Input Validation

Always sanitize data before sending it to the API. The API has some built-in validation, but SQL injection and XSS payloads in lead data can cause problems downstream in reports and agent screens.


Common API Errors and Fixes

ErrorCauseFix
ERROR: add_lead INVALID LIST IDList doesn’t exist or is inactiveVerify list_id in Admin > Lists
ERROR: NO FUNCTION SPECIFIEDMissing function parameterAdd function=add_lead (or whichever function)
ERROR: INVALID USERBad credentials or user not API-enabledCheck user/pass, enable API access in user settings
ERROR: FUNCTION NOT ALLOWEDFunction not enabled for this userEnable the specific function in user’s Allowed API Functions
ERROR: INVALID SOURCESource parameter missing or invalidAdd source=your_identifier to the request
ERROR: add_lead DUPLICATEPhone number already exists in listUse duplicate_check=DUPLIST to allow or update_lead instead
ERROR: IP NOT ALLOWEDYour IP isn’t in the user’s allowed listAdd your server’s IP to the API user’s IP restrictions

Performance Considerations

Batch Lead Imports

If you need to import thousands of leads, don’t hit the API once per lead in a tight loop. The API processes each request synchronously, and high-frequency requests can overwhelm the web server.

Instead:

  • Use VICIdial’s built-in list loader for bulk imports (Admin > Lists > Load Leads)
  • If you must use the API, throttle to 5-10 requests per second
  • For large batches, generate a lead file and use the add_list function to upload the whole file

API Response Time

Expect 100-500ms per API call on a healthy system. If response times exceed 1 second consistently, check:

  • MySQL query performance (the API hits the database on every call)
  • Web server load (Apache workers competing with agent web sessions)
  • Network latency between your calling application and the VICIdial server

When the API Isn’t Enough

VICIdial’s API covers most common integration scenarios, but it has limitations:

  • No real-time event streaming (webhooks are disposition-only)
  • No bulk operations beyond lead file upload
  • Limited reporting functions compared to direct database access
  • Agent API requires an active agent session

For advanced integrations — real-time call event streaming, complex reporting, custom agent screen modifications — you’ll need direct database access (read-only, through a replica) or custom development on the VICIdial codebase.



Related reading:

Real-World Integration Patterns

Pattern 1: Lead Score Routing

Your CRM assigns lead scores (1-100) based on demographic data and behavioral signals. High-score leads should go to your best agents. Here’s how:

  1. When adding leads via API, store the score in a custom field:
curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=crm&\
user=apiuser&\
pass=API_PASSWORD&\
function=add_lead&\
phone_number=3125551234&\
list_id=10001&\
custom_fields=Y&\
cf_lead_score=85"
  1. Create two lists: 10001 (high-score leads) and 10002 (standard leads)
  2. In your API integration script, route leads to the appropriate list based on score
  3. Assign your best agents to campaign configurations that dial the high-score list first using list mix priority in the Admin GUI

Pattern 2: Real-Time CRM Screen Pop

When an agent connects to a call, you want your CRM to automatically open the customer record. VICIdial supports this through the agent interface’s “Web Form” feature.

In Campaign Settings, configure the Web Form URL:

https://your-crm.com/popup?phone=--A--phone_number--B--&name=--A--first_name--B--+--A--last_name--B--&lead_id=--A--lead_id--B--&vendor=--A--vendor_lead_code--B--

When the agent clicks “Web Form” (or it auto-opens based on campaign settings), the URL opens in a new tab with the lead’s data pre-filled. Your CRM uses the vendor_lead_code to look up the customer record and display it.

For automatic screen pop (no click required), set “Web Form Target” to “New Window” and enable “Auto-Launch Web Form” in the campaign settings. The CRM window opens the instant the call connects.

Pattern 3: Disposition-Triggered Automation

Beyond the simple webhook, you can chain multiple actions on disposition:

  • SALE disposition → Webhook to CRM → Create deal → Trigger e-signature email → Schedule follow-up callback
  • APPT disposition → Webhook to scheduling system → Block calendar slot → Send SMS confirmation
  • DNC disposition → Webhook to compliance system → Log the request → Trigger DNC registry update

Each of these chains starts with VICIdial’s Dispo Call URL firing to your middleware, which then orchestrates the downstream actions.

Pattern 4: Multi-System Lead Deduplication

If you receive leads from multiple sources (web forms, bought lists, partner referrals), you need to prevent duplicate calls. Use the API’s duplicate_check parameter:

curl -s "https://YOUR-SERVER/vicidial/non_agent_api.php?\
source=webform&\
user=apiuser&\
pass=API_PASSWORD&\
function=add_lead&\
phone_number=3125551234&\
list_id=10001&\
duplicate_check=DUPCAMP&\
duplicate_campaign_id=SALES01"

duplicate_check options:

  • DUPLIST — Check within the same list only
  • DUPCAMP — Check across all lists in the campaign
  • DUPSYS — Check the entire VICIdial system
  • DUPFULL — Check system-wide plus the DNC list

The API returns ERROR: add_lead DUPLICATE if the phone number already exists, and your integration code can handle it accordingly (update existing lead, skip, or log for review).

Pattern 5: Automated Campaign Activation

For operations that run different campaigns at different times (morning shift campaigns, afternoon campaigns, after-hours), automate the start and stop:

import requests
from datetime import datetime

API_URL = "https://YOUR-SERVER/vicidial/non_agent_api.php"
CAMPAIGNS = {
 "MORNING": {"start": 8, "end": 12},
 "AFTERNOON": {"start": 12, "end": 17},
 "EVENING": {"start": 17, "end": 20},
}

current_hour = datetime.now().hour

for campaign, hours in CAMPAIGNS.items():
 if hours["start"] <= current_hour < hours["end"]:
 action = "ACTIVE"
 else:
 action = "PAUSED"

 resp = requests.get(API_URL, params={
 "source": "scheduler",
 "user": "apiuser",
 "pass": "API_PASSWORD",
 "function": "update_campaign",
 "campaign_id": campaign,
 "active": action,
 }, timeout=10)
 print(f"{campaign}: {action} - {resp.text}")

Schedule this via cron every hour. No more manual campaign activation at shift boundaries.

That’s the kind of work we do at ViciStack. We’ve built CRM integrations, custom real-time dashboards, ML-based lead scoring pipelines, and automated campaign management systems on top of VICIdial’s API and database. If you need something the stock API can’t do, the $5K engagement gets you a working integration, not a proposal.

REVENUE CALCULATOR

How Much Revenue Is Your VICIdial Leaving on the Table?

Adjust the sliders to match your call center. See what optimized dialing could mean for your bottom line.

50
5 500
3%
1% 15%
$500
$50 $5,000

With optimized VICIdial

6.0% connect rate

Industry avg with ViciStack optimization

Additional Sales / Day

+54

Additional Monthly Revenue

$567,000

Annual Revenue Impact

$6,804,000

Get Your Personalized Analysis

Free · No credit card · Results in 5 minutes

Still running default VICIdial settings?

Most call centers leave 40-60% of their dialer performance on the table. Get a free analysis and see exactly what to fix.

Get Free Analysis

Ready to Double Your Live Connections?

100+ call centers switched to ViciStack and saw 2x more live connections at $150/agent/mo flat. No per-minute billing, no surprises.

2xLive Connections
$150Per Agent / Month
5 minResponse Time

No credit card required · 100+ call centers trust ViciStack

← Previous VICIdial vs Every Alternative: Honest Comparisons With Real Pricing Next → VICIdial call recording storage optimization

Related Articles

VICIdial Optimization

VICIdial API Integration Examples

· 11 min read
Technical Guides

VICIdial API Guide: Non-Agent API & Agent API With Working Code Examples

· 24 min read
Technical Guides

VICIdial CRM Integration Guide: Salesforce, HubSpot & Custom

· 24 min read
Technical Guides

Migrating from GoAutoDial to VICIdial: Step-by-Step

· 16 min read

Related Status Codes

A — Answering Machine B — Busy CALLBK — Callback Scheduled DISPO — Disposition Screen DNC — Do Not Call

Related Glossary Terms

Agent Screen Automatic Number Identification (ANI) Asterisk Manager Interface (AMI) Callback Campaign Caller ID (CID) Conversion Rate Direct Inward Dialing (DID)

See How VICIdial Compares

VICIdial vs. GoAutoDial Read comparison →

Comprehensive Guides

Complete VICIdial Implementation Guide Read guide → VICIdial Performance Optimization Guide Read guide →

Want These Results for Your Center?

Get a free performance audit from our VICIdial optimization experts. We'll identify the highest-impact changes for your specific setup.

System Down? Get Help in 5 Minutes
Real-time support within 5 minutes. 24/7. Call or text 343-204-2353