DEV Community

Jason Shouldice
Jason Shouldice

Posted on • Edited on • Originally published at vicistack.com

VICIdial's Two APIs: A Practical Guide to Lead Injection, Webhooks, and Automation

VICIdial has two APIs that most operators never touch. The Non-Agent API handles system-level automation -- lead injection, stats pulling, campaign control. The Agent API controls live agent sessions -- disposition calls, trigger transfers, dial specific numbers. Together they turn VICIdial from a standalone dialer into a programmable call center engine that plugs into anything.

The documentation is scattered across VICIdial's docs/ directory, forum posts from 2014, and tribal knowledge locked in the heads of a few senior developers. Here's the consolidated working reference.

Non-Agent API vs Agent API

Non-Agent API (/vicidial/non_agent_api.php) -- No active agent session required. This is the workhorse for backend automation. External systems -- CRMs, web forms, marketing platforms, custom apps -- call this API to interact with VICIdial data and campaigns.

What it can do: add_lead (inject leads into lists), update_lead (modify existing lead data), agent_stats (pull agent performance data), campaign_stats (pull campaign-level metrics), call_agent (initiate outbound calls), start/stop/pause campaigns, dnc_check (query DNC lists), add_callback, remove_callback, recording_lookup, lead_search.

Agent API (/agc/api.php) -- Requires an active agent session. Controls what you'd normally do by clicking buttons on the agent screen. Use this when building a custom agent interface, integrating a CRM that needs to control VICIdial call flow, or automating agent actions.

What it can do: log agents in/out, pause/unpause, disposition calls, transfer calls, hang up, dial specific numbers, set callbacks, update lead data, switch campaigns, send DTMF, control recordings.

The key distinction: Non-Agent API for system-level operations (data in, data out, campaign management). Agent API for session-level operations (things during a live agent session).

Both use HTTP GET/POST with URL parameters. No WebSocket, no OAuth, no SDK libraries. Call a URL, pass credentials, get a response. Simple and frustrating in equal measure.

Authentication and Security

Every request needs three base parameters: source (freeform identifier for the calling system), user, and pass. Enable API access per user under Admin > Users > API Access. Set "API Allowed Functions" to restrict which endpoints each user can call.

The API has no built-in rate limiting, no API keys, and no token-based auth. Credentials travel as URL parameters, which means they appear in web server access logs. Security hardening is your responsibility:

HTTPS is mandatory. Without TLS, credentials travel in plaintext.

IP whitelist via .htaccess on the API files:

<Files "non_agent_api.php">
  Order Deny,Allow
  Deny from all
  Allow from 10.0.0.0/8
  Allow from 203.0.113.50
</Files>
Enter fullscreen mode Exit fullscreen mode

Dedicated API users with minimal permissions. Never use admin accounts for API access. Create users with only the functions they need.

Monitor API usage via the vicidial_api_log table. If you see unexpected sources, unknown IPs, or functions being called that shouldn't be, you have an access problem.

Lead Injection: add_lead

The most commonly used endpoint. Every web form, landing page, CRM, and lead vendor integration starts here.

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "source=webform" \
  --data-urlencode "user=apiuser" \
  --data-urlencode "pass=apipass" \
  --data-urlencode "function=add_lead" \
  --data-urlencode "phone_number=5551234567" \
  --data-urlencode "phone_code=1" \
  --data-urlencode "list_id=10001" \
  --data-urlencode "first_name=John" \
  --data-urlencode "last_name=Smith" \
  --data-urlencode "vendor_lead_code=CRM-2026-44921" \
  --data-urlencode "duplicate_check=DUPCAMP"
Enter fullscreen mode Exit fullscreen mode

Success response: SUCCESS: add_lead - leadass added - 5551234567|10001|12345678

Parse the lead_id at the end -- you'll need it for updates and tracking.

Key parameters: phone_number (required), phone_code (required, 1 for US/Canada), list_id (required, must exist), vendor_lead_code (your external ID -- critical for CRM sync), source_id (lead source tracking), rank (-99 to 99, higher = dialed sooner), owner (for owner-based routing), duplicate_check (DUPLIST, DUPCAMP, DUPSYS).

Custom Fields

If your lists have custom fields (Admin > Custom Fields), add custom_fields=Y and pass field values matching the field names:

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "function=add_lead" \
  --data-urlencode "custom_fields=Y" \
  --data-urlencode "policy_number=POL-2026-8812" \
  --data-urlencode "insurance_type=medicare_advantage"
Enter fullscreen mode Exit fullscreen mode

Duplicate Handling

The duplicate_check parameter controls what happens when a lead with the same phone exists: DUPLIST (same list), DUPCAMP (all lists in campaign), DUPSYS (entire system), DUPLISTPHONE (phone + list combo). If found, response is NOTICE: add_lead DUPLICATE.

Updating Leads: update_lead

Update any field on an existing lead by lead_id or by vendor_lead_code lookup:

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "function=update_lead" \
  --data-urlencode "vendor_lead_code=CRM-2026-44921" \
  --data-urlencode "search_method=VENDOR_LEAD_CODE" \
  --data-urlencode "search_location=LIST" \
  --data-urlencode "list_id=10001" \
  --data-urlencode "status=CALLBK" \
  --data-urlencode "comments=Customer called back, wants quote"
Enter fullscreen mode Exit fullscreen mode

Common use cases: mark leads as DNC from your compliance system, reset leads to NEW for re-dialing after a cooling period, set callback status from your CRM, change status based on external workflow triggers.

Disposition Webhooks: dispo_call_url

This is how VICIdial talks back to your systems in real time. Configure a URL at the campaign level that VICIdial calls when an agent dispositions a call. VICIdial substitutes live call data into the URL:

https://your-crm.com/webhook?lead_id=--A--lead_id--B--&status=--A--dispo--B--&agent=--A--user--B--&talk_time=--A--talk_time--B--
Enter fullscreen mode Exit fullscreen mode

Every disposition fires this webhook. Your CRM receives the outcome instantly. No polling, no batch sync.

There's also start_call_url which fires when a call connects to an agent -- useful for screen-popping your CRM before the agent says hello.

Real-Time Stats

Pull live performance data for external dashboards:

agent_stats returns current status, calls today, talk time, pause time, wait time for a specific agent. campaign_stats returns floor-level metrics: calls in queue, agents available, calls waiting, service level.

Poll every 30-60 seconds for a live wallboard. Don't poll faster -- the queries hit the database directly and VICIdial has no caching layer on these endpoints. At 5-second polling intervals with multiple dashboard instances, you'll create noticeable database load.

Click-to-Call

Use the Agent API to initiate outbound calls from your CRM:

curl "https://your-server/agc/api.php?\
source=crm&user=agent001&pass=agentpass&\
function=external_dial&agent_user=agent001&\
value=5551234567&phone_code=1&search=YES&preview=NO"
Enter fullscreen mode Exit fullscreen mode

The agent's phone rings, connects, and dials the number. The CRM triggered it without the agent touching VICIdial. Set search=YES to auto-load any existing lead data for that phone number.

Campaign Stats and Agent Stats

Pulling live operational data is essential for custom dashboards, alerting, and BI integration.

Campaign Stats

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "source=dashboard" \
  --data-urlencode "user=apiuser" \
  --data-urlencode "pass=apipass" \
  --data-urlencode "function=campaign_stats" \
  --data-urlencode "campaign_id=SALESCAMP" \
  --data-urlencode "stage=csv"
Enter fullscreen mode Exit fullscreen mode

Returns total calls today, agents logged in, agents in each status (INCALL, READY, PAUSED, DEAD), calls waiting in queue, average wait time, current dial level, drop rate, and hopper count.

The stage parameter controls output format: csv for CSV, json for JSON (newer builds).

Agent Stats

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "source=dashboard" \
  --data-urlencode "user=apiuser" \
  --data-urlencode "pass=apipass" \
  --data-urlencode "function=agent_stats" \
  --data-urlencode "agent_user=agent001" \
  --data-urlencode "stage=csv"
Enter fullscreen mode Exit fullscreen mode

Returns per-agent metrics: calls taken, talk time, pause time, wait time, dispositions, login/logout times.

Poll every 30-60 seconds for a live wallboard. Don't poll faster -- the queries hit the database directly and VICIdial has no caching layer on these endpoints. Multiple dashboard instances polling at 5-second intervals will create noticeable database load.

Alerting on Drop Rate

Build a monitoring script that polls campaign_stats and fires alerts when drop rate approaches the 3% FCC limit:

import requests
import time

def get_campaign_stats(campaign_id):
    params = {
        "source": "monitor",
        "user": "apiuser",
        "pass": "apipass",
        "function": "campaign_stats",
        "campaign_id": campaign_id,
        "stage": "csv",
    }
    resp = requests.get(VICIDIAL_API, params=params, timeout=10)
    stats = {}
    for line in resp.text.strip().split("\n"):
        if "|" in line:
            parts = line.split("|")
            if len(parts) >= 2:
                stats[parts[0].strip()] = parts[1].strip()
    return stats

def monitor_loop(campaigns, interval=30):
    while True:
        for cid in campaigns:
            stats = get_campaign_stats(cid)
            drop_rate = float(stats.get("drop_rate", 0))
            if drop_rate > 2.5:
                send_slack_alert(f"WARNING: {cid} drop rate at {drop_rate}%")
        time.sleep(interval)
Enter fullscreen mode Exit fullscreen mode

Start Call URL: Real-Time Screen Pops

The Start Call URL fires when a call connects to an agent -- before the agent says a word. This is how you build real-time screen pops in external CRMs. When the call connects, VICIdial hits your URL with lead data:

https://your-crm.com/api/screen-pop?agent=--A--user--B--&lead_id=--A--lead_id--B--&phone=--A--phone_number--B--&first_name=--A--first_name--B--&vendor_lead_code=--A--vendor_lead_code--B--
Enter fullscreen mode Exit fullscreen mode

Your CRM receives the data, looks up the record by vendor_lead_code, and pops the relevant screen for the agent. By the time the agent says "Hi," the CRM already has the customer's history, previous interactions, and notes visible.

Combined with Dispo Call URL, you get complete lifecycle visibility: your CRM knows when a call starts (start_call_url), what happened during the call (agent updates via web forms), and how it ended (dispo_call_url).

Campaign Control via API

The Non-Agent API can start and stop campaigns programmatically:

# Pause a campaign
curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "source=scheduler" \
  --data-urlencode "user=apiuser" \
  --data-urlencode "pass=apipass" \
  --data-urlencode "function=campaign_status" \
  --data-urlencode "campaign_id=SALESCAMP" \
  --data-urlencode "value=PAUSED"
Enter fullscreen mode Exit fullscreen mode

Use this for automated scheduling: start campaigns at 9 AM, pause during lunch, stop at 5 PM. Or build compliance logic that pauses campaigns when the drop rate approaches limits. Or trigger campaign changes based on external events -- weather alerts, inventory levels, staffing changes.

Agent API: Controlling the Agent Session

The Agent API is less commonly used but powerful for custom integrations. Use it when your CRM needs to control VICIdial call flow directly.

External Disposition

Set a disposition from your CRM without the agent clicking anything in VICIdial:

curl "https://your-server/agc/api.php?\
source=crm&user=agent001&pass=agentpass&\
function=external_status&agent_user=agent001&\
value=SALE"
Enter fullscreen mode Exit fullscreen mode

External Pause/Resume

Pause an agent from your workforce management system:

curl "https://your-server/agc/api.php?\
source=wfm&user=agent001&pass=agentpass&\
function=external_pause&agent_user=agent001&\
value=PAUSE"
Enter fullscreen mode Exit fullscreen mode

Transfer Calls

Transfer the agent's current call to a specific number or ingroup:

curl "https://your-server/agc/api.php?\
source=crm&user=agent001&pass=agentpass&\
function=transfer_conference&agent_user=agent001&\
value=DIAL&phone_number=5559876543"
Enter fullscreen mode Exit fullscreen mode

This enables CRM-driven routing -- your system decides where the call should go based on qualification data, agent skills, or business rules, and triggers the transfer via API.

Error Handling and Rate Limiting

Responses are plain text, not JSON (usually). They start with SUCCESS, ERROR, or NOTICE. HTTP 200 doesn't mean the operation succeeded -- always check response text.

Common errors:

  • ERROR: add_lead INVALID LIST ID -- The list_id doesn't exist in VICIdial
  • ERROR: NO FUNCTION SPECIFIED -- Missing or misspelled function parameter
  • ERROR: agent_user is not logged in -- Agent API called without active session
  • ERROR: lead_id IS NOT VALID -- Lead doesn't exist
  • ERROR: Function not allowed -- API user doesn't have permission for that function

Implement retry logic with exponential backoff for timeouts. Log every API interaction for debugging. Store the response text, not just the HTTP status code.

VICIdial won't rate-limit you. If you fire 1,000 add_lead calls per second, the database will buckle. For bulk imports, throttle to 5-10 calls/second -- add a 100ms sleep between calls. A 10,000-lead CSV file takes about 17 minutes at that rate, which is fast enough and won't strain the database.

For real-time webhook injection (web form submits one lead at a time), the natural rate is fine.

Callback Management

The Non-Agent API handles callback scheduling programmatically:

# Schedule a callback for a specific agent
curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "source=crm" \
  --data-urlencode "user=apiuser" \
  --data-urlencode "pass=apipass" \
  --data-urlencode "function=add_callback" \
  --data-urlencode "lead_id=12345678" \
  --data-urlencode "campaign_id=SALESCAMP" \
  --data-urlencode "callback_datetime=2026-03-26 14:30:00" \
  --data-urlencode "callback_type=USERONLY" \
  --data-urlencode "callback_user=agent001" \
  --data-urlencode "callback_comments=Wants quote comparison"
Enter fullscreen mode Exit fullscreen mode

Callback types: USERONLY (specific agent), ANYONE (first available agent in campaign), USERONLY_NO (specific agent, no penalty if missed).

Remove callbacks when a customer contacts you through another channel:

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "function=remove_callback" \
  --data-urlencode "lead_id=12345678" \
  --data-urlencode "campaign_id=SALESCAMP"
Enter fullscreen mode Exit fullscreen mode

This is how you build cross-channel callback management. Customer schedules a callback on your website, your backend calls add_callback. Customer emails to cancel, your CRM calls remove_callback. The VICIdial dialer handles the timing; your systems handle the business logic.

DNC Management via API

Check numbers against the internal DNC list before importing:

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "function=dnc_check" \
  --data-urlencode "phone_number=5551234567"
Enter fullscreen mode Exit fullscreen mode

Response: DNC NUMBER NOT FOUND (safe to dial) or DNC NUMBER FOUND (do not call).

For bulk list cleaning, loop through your list with dnc_check before injection. This catches numbers that were DNC'd internally by agents but might not appear on external DNC lists.

Recording Lookup

Pull recording metadata and download links:

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "function=recording_lookup" \
  --data-urlencode "lead_id=12345678" \
  --data-urlencode "date=2026-03-25"
Enter fullscreen mode Exit fullscreen mode

Returns recording filenames, locations, and metadata. Useful for QA systems that need to pull recordings for scoring, compliance systems archiving calls, and CRM integrations that want to display call recordings inline.

Lead Search

Search for leads by phone number, vendor_lead_code, or other fields:

curl -G "https://your-server/vicidial/non_agent_api.php" \
  --data-urlencode "function=lead_search" \
  --data-urlencode "phone_number=5551234567" \
  --data-urlencode "search_location=SYSTEM"
Enter fullscreen mode Exit fullscreen mode

Returns lead_id, status, list_id, and other lead data. Use this for deduplication before injection, for CRM lookups that need VICIdial lead status, or for building search interfaces.

Building a Webhook Receiver

When you configure Dispo Call URL, you need a server endpoint that receives and processes the webhook. Here's what that looks like in practice:

Python Flask Receiver

from flask import Flask, request, jsonify
import logging

app = Flask(__name__)
logger = logging.getLogger(__name__)

@app.route("/api/vicidial/disposition", methods=["GET", "POST"])
def handle_disposition():
    data = {
        "lead_id": request.args.get("lead_id"),
        "phone": request.args.get("phone"),
        "status": request.args.get("status"),
        "agent": request.args.get("agent"),
        "talk_time": request.args.get("talk_time"),
        "vendor_lead_code": request.args.get("vendor_lead_code"),
        "campaign": request.args.get("campaign"),
        "recording": request.args.get("recording"),
    }

    status = data["status"]
    if status == "SALE":
        # Trigger fulfillment, notify manager via Slack
        send_slack_notification(data)
    elif status == "CALLBK":
        # Schedule callback in your external system
        schedule_callback(data)
    elif status == "DNCL":
        # Add to suppression lists
        add_to_suppression(data)

    # Always sync to CRM
    sync_to_crm(data)
    return jsonify({"status": "received"}), 200
Enter fullscreen mode Exit fullscreen mode

VICIdial sends disposition webhooks as HTTP GET requests (the parameters are in the URL, not the POST body). Your receiver needs to handle GET parameters even though the convention elsewhere is POST for webhooks. Make sure your endpoint returns 200 quickly -- VICIdial makes the HTTP call synchronously during the disposition process, so a slow response delays the agent's next call.

PHP Receiver

<?php
$data = array(
    'lead_id' => $_GET['lead_id'] ?? '',
    'phone'   => $_GET['phone'] ?? '',
    'status'  => $_GET['status'] ?? '',
    'agent'   => $_GET['agent'] ?? '',
);

error_log("DISPO: {$data['phone']} -> {$data['status']}");

$pdo = new PDO('mysql:host=localhost;dbname=your_crm', 'user', 'pass');
$stmt = $pdo->prepare("
    INSERT INTO call_dispositions
    (lead_id, phone, status, agent, created_at)
    VALUES (?, ?, ?, ?, NOW())
");
$stmt->execute([$data['lead_id'], $data['phone'],
    $data['status'], $data['agent']]);

http_response_code(200);
echo "OK";
?>
Enter fullscreen mode Exit fullscreen mode

Bulk Operations: Python Script for CSV Import

For importing lead files, a Python script with proper throttling and error handling:

import requests
import csv
import time
import logging

VICIDIAL_API = "https://your-server/vicidial/non_agent_api.php"
API_USER = "apiuser"
API_PASS = "apipass"

def inject_lead(lead_data):
    params = {
        "source": "csv_import",
        "user": API_USER,
        "pass": API_PASS,
        "function": "add_lead",
        "phone_code": "1",
        "list_id": lead_data.get("list_id", "10001"),
        "phone_number": lead_data["phone"],
        "first_name": lead_data.get("first_name", ""),
        "last_name": lead_data.get("last_name", ""),
        "vendor_lead_code": lead_data.get("external_id", ""),
        "duplicate_check": "DUPCAMP",
    }
    resp = requests.get(VICIDIAL_API, params=params, timeout=10)
    result = resp.text.strip()
    if "SUCCESS" in result:
        return result.split("|")[-1]
    return None

def import_csv(filepath):
    success = 0
    dupes = 0
    with open(filepath) as f:
        for row in csv.DictReader(f):
            result = inject_lead(row)
            if result:
                success += 1
            else:
                dupes += 1
            time.sleep(0.1)  # 100ms throttle
    print(f"Done: {success} added, {dupes} dupes/errors")
Enter fullscreen mode Exit fullscreen mode

At 100ms per call, a 10,000-lead file finishes in about 17 minutes. Fast enough for any practical purpose without straining the database.

Integration Patterns

Pattern 1: Web Form to Dialer

Landing page collects lead info, submits to your backend, your backend calls add_lead. Lead appears in VICIdial's hopper and gets dialed within seconds. Set rank=99 for hot leads to get them dialed first. This is the most common integration -- virtually every call center that accepts web leads needs this pipeline.

Pattern 2: CRM Sync Loop

Dispo Call URL pushes dispositions to your CRM in real time. Your CRM processes the data, updates lead status, and can call update_lead back to VICIdial if it needs to change anything (reset status, update fields, schedule callbacks). This creates a bidirectional sync where VICIdial and your CRM stay in lockstep without batch processes or manual exports.

Pattern 3: Custom Agent Interface

Build your own agent UI that embeds VICIdial's call controls via the Agent API. Your agents work in your CRM, and your CRM calls external_dial, external_status, external_pause, and transfer_conference behind the scenes. The agent never sees VICIdial's default interface. This is the most complex pattern but gives you total UI control.

Pattern 4: Automated Campaign Management

A scheduler script starts/stops campaigns based on time, staffing levels, or external triggers. Combined with campaign_stats polling, you can auto-adjust operations: pause campaigns when drop rate approaches 3%, shift agents between campaigns based on queue depth, start evening campaigns when day campaigns wind down.

Pattern 5: Lead Scoring Pipeline

Your marketing system scores leads based on behavior (pages visited, form fields, time on site). It calls update_lead to set the rank field. High-score leads get rank=99 and jump to the front of the dialing queue. Low-score leads get rank=-50 and dial last. VICIdial doesn't care how the rank was calculated -- it just dials highest rank first.

Resetting Aged Leads for Re-Dialing

One of the most common automated workflows: find leads that were called 30+ days ago without a final outcome, and reset them for re-dialing.

You can't do this directly through the Non-Agent API in one call -- you need to find the leads first (via lead_search or by querying the database), then update each one via update_lead:

def reset_aged_leads(list_id, days=30):
    """Find and reset old called leads back to NEW status."""
    import mysql.connector

    db = mysql.connector.connect(
        host="localhost", user="cron",
        password="cronpass", database="asterisk"
    )
    cursor = db.cursor()
    cursor.execute("""
        SELECT lead_id FROM vicidial_list
        WHERE list_id = %s
          AND status IN ('NA', 'NI', 'B', 'DC', 'N')
          AND last_local_call_time < DATE_SUB(NOW(), INTERVAL %s DAY)
    """, (list_id, days))

    leads = cursor.fetchall()
    print(f"Found {len(leads)} aged leads to reset")

    for (lead_id,) in leads:
        params = {
            "source": "reset_script",
            "user": API_USER,
            "pass": API_PASS,
            "function": "update_lead",
            "lead_id": str(lead_id),
            "status": "NEW",
        }
        requests.get(VICIDIAL_API, params=params, timeout=10)
        time.sleep(0.05)

    cursor.close()
    db.close()
Enter fullscreen mode Exit fullscreen mode

Run this weekly via cron. It gives your agents fresh passes at leads that have had time to cool off, without manual list management.

Common Gotchas

The API returns plain text, not JSON. Don't parse the response as JSON unless you specifically requested stage=json on a function that supports it. Most functions return pipe-delimited text.

List IDs must exist before injection. If you call add_lead with a list_id that doesn't exist in VICIdial, you get ERROR: add_lead INVALID LIST ID. Create lists in admin first.

The Agent API requires an active session. If the agent logged out or their session timed out, every Agent API call returns an error. Your integration needs to handle this gracefully.

Phone number formatting matters. The API expects 10-digit US numbers without formatting. No dashes, no parentheses, no country code prefix. Strip everything except digits before calling.

There's no bulk API endpoint. Every operation is one lead at a time. For 10,000 leads, that's 10,000 HTTP requests. Budget for time and implement throttling. Some operators build a middleware layer that accepts bulk submissions and serializes them into individual API calls with proper pacing.

VICIdial API responses include newlines. Always .strip() the response text before parsing. Trailing newlines will break string comparisons like if result == "SUCCESS".

Custom field names are case-sensitive. If your custom field in VICIdial is PolicyNumber and you pass policynumber in the API call, the field won't populate. Match exactly.

API Versioning and Compatibility

VICIdial doesn't version its API in the traditional sense. Functions get added in new SVN revisions but existing functions rarely change their interface. The version function tells you what build you're running:

curl "https://your-server/vicidial/non_agent_api.php?\
source=test&user=apiuser&pass=apipass&function=version"
Enter fullscreen mode Exit fullscreen mode

When VICIdial adds new API functions, they appear silently in the next SVN update. Check the CHANGES file or the function list in non_agent_api.php source to discover new capabilities. Functions like campaign_stats with stage=json were added in later revisions -- if your build is old, that format option might not exist.

When to Use the API vs. the Admin GUI

The API is for automation and integration. The admin GUI is for human-driven configuration. Don't use the API for things that are easier done in admin (creating campaigns, setting up carriers, defining dispositions). Do use the API for repetitive operations (lead injection, status updates, callback scheduling) and for connecting VICIdial to other systems (CRMs, dashboards, compliance tools, workforce management).

The sweet spot: your humans configure VICIdial's structure through admin, and your code handles the data flow through the API.

ViciStack builds automated lead injection pipelines, CRM disposition webhooks, real-time dashboards, and custom API integrations for VICIdial operations. Leads flow in real-time, deduplicated and routed to the right campaign. Talk to us about your integration needs.

Originally published at https://vicistack.com/blog/vicidial-api-integration/

Top comments (0)