VICIdial isn't a CRM, and it was never built to be one. It's a dialer engine with a lead database bolted on — great at pacing calls, routing agents, and logging dispositions, terrible at being the system your sales or collections team actually lives in. So the moment a call center outgrows spreadsheets, someone on the team ends up staring at a VICIdial admin panel and a Salesforce (or HubSpot, or Zoho, or custom Rails app) instance, trying to figure out how to make the two talk to each other without hiring a full-time integration engineer.
This guide covers the four integration patterns that actually matter, how they're typically built, and — because this is the part most integration guides skip — where AMD accuracy quietly wrecks the data flowing between your dialer and your CRM even when the integration itself is working perfectly.
VICIdial Has No Native CRM Connectors
This surprises people who assume "enterprise dialer" means "plug-and-play." It doesn't. VICIdial ships with an open API (the non_agent_api.php and agc interfaces) and a flexible agent screen you can skin with an iframe, but there's no App Marketplace, no OAuth button for Salesforce, no HubSpot listing. Every VICIdial-to-CRM integration is either:
- Hand-coded PHP/webhook middleware sitting between the two systems, or
- A third-party connector product (Forth CRM, ViciStack-style skins, or a call center software layer like Convoso/Five9 that replaces VICIdial's UI entirely), or
- A generic iPaaS tool (n8n, Make, or custom scripts hitting both APIs on a schedule)
None of these are wrong. The right choice depends on call volume, in-house dev capacity, and how deeply the CRM needs to drive dialer behavior (versus just receiving records after the fact).
The Four Integration Patterns
| Pattern | What it does | Typical trigger | Failure mode if broken |
|---|---|---|---|
| Screen pop | Loads the CRM record in the agent's browser the instant a call connects | Call state change to INCALL |
Agent has no context, asks the lead to repeat themselves |
| Disposition sync | Writes the VICIdial call outcome (SALE, AM, NA, DNC, etc.) back to the CRM record | Agent hangs up / dispositions the call | CRM stage and dialer status drift apart, leads get called incorrectly |
| Lead injection | Pushes new/updated leads from the CRM into a VICIdial list in real time | CRM record created or field changed | Fresh leads sit uncalled for hours, or get dialed on stale contact info |
| Click-to-call | Lets an agent originate a VICIdial call from inside the CRM UI | Agent clicks a phone number | Agents fall back to manual dialing, killing your pacing ratio math |
Most call centers start with screen pop and disposition sync because those two directly touch agent productivity and reporting accuracy. Lead injection and click-to-call tend to get built once volume justifies the engineering time.
Building the Screen Pop
The mechanics are simple even though the plumbing takes effort. VICIdial's agent screen (vicidial/agc/vicidial.php) supports a custom "script" or iframe URL that gets passed session variables — lead_id, phone_number, list_id, campaign_id, and any custom fields you've mapped. Your middleware (or the CRM's own embed, if it supports one) reads those parameters and either:
- Loads the CRM record directly via a pre-built search URL (
https://yourcrm.com/leads?phone={phone_number}), or - Calls the CRM's API server-side, pulls the matching record, and renders a custom pop window that lives inside the VICIdial agent frame
Option 2 is more work but gives you control over what the agent actually sees — call history, deal stage, prior disposition notes — without exposing the full CRM UI. If you're running a BPO seat renting agent licenses across multiple client CRMs, this matters more than it sounds like it should, since VICIdial agents typically don't get direct CRM logins.
Disposition Sync: Where Most Integrations Quietly Fail
This is the pattern worth slowing down on, because it's also where AMD accuracy stops being a dialer-only problem and starts corrupting your CRM.
Every VICIdial disposition code needs a mapping to a CRM stage or status field. A typical map looks like this:
| VICIdial status | Meaning | CRM mapping |
|---|---|---|
SALE |
Converted | Stage → Closed Won |
AM |
Answering machine | Stage → Voicemail Left, next attempt scheduled |
NA |
No answer | Return to active queue |
DNC |
Do not call | Suppressed, flagged permanently |
CALLBK |
Callback requested | Stage → Callback Scheduled |
NI |
Not interested | Stage → Closed Lost |
That AM row is the problem. If your AMD engine is running at Asterisk's default accuracy — typically a 15–25% false positive rate — a meaningful share of the calls landing in that AM bucket were actually live humans who got hung up on or routed to a voicemail-drop message before an agent ever answered. Your disposition sync doesn't know the difference. It faithfully writes "Voicemail Left" to the CRM, the automation rule schedules a follow-up call for three days out, and a lead who was seconds from talking to a live agent disappears from active outreach.
The integration isn't broken. The data feeding it is. This is the same failure mode covered in more depth in VICIdial False Positive Rate: Why Your AMD Is Dropping Live Calls — but it's worth calling out specifically in a CRM context because the damage compounds. A missed live answer inside VICIdial is a lost call. A misdispositioned lead inside a CRM with stage-based automation is a lost pipeline record that your sales manager will never think to question, because nothing in the CRM looks wrong.
If you haven't already, run the disposition data through the framework in How to Audit Your Dialer's AMD Accuracy before you finalize your CRM mapping. Building automation on top of an unaudited AM bucket just moves the false-positive cost from your call reports into your revenue reports.
Lead Injection: Real-Time Push vs. Batch Sync
Two approaches, and the choice matters more than people expect:
Batch sync (cron job pulling new/changed CRM records every 5–15 minutes, pushing them into a VICIdial list via the non_agent_api add_lead or update_lead functions) is simpler to build and easier to debug. It's fine for outbound campaigns where a few minutes of lag doesn't matter.
Real-time push (CRM webhook fires on record creation, hits your middleware, which immediately calls the VICIdial API) matters when speed-to-lead is the whole game — inbound web leads, financial services, anything where a 10-minute delay measurably drops contact rates. If you're in that category, batch sync will quietly cost you conversions no dashboard will flag, because the leads still get called — just too late to matter.
Either way, dedupe logic needs to live somewhere. VICIdial will happily create duplicate lead records if your middleware doesn't check phone_number against the existing list before inserting, and duplicate leads mean the same person gets called by two different agents in the same shift — a compliance problem as much as an efficiency one.
Click-to-Call: The Pattern Most Teams Skip (and Shouldn't)
Click-to-call lets agents originate calls from inside the CRM instead of VICIdial's native interface, using the agi:// or API-triggered outbound call functions. Teams skip it because it feels like a nice-to-have rather than core infrastructure. But if your agents are working a mixed queue — some predictive-dialer campaigns, some manual outbound from CRM records — click-to-call is what keeps agent activity logged in one place instead of two, and it's what prevents agents from just picking up a softphone and dialing manually, which breaks your pacing ratio calculations entirely.
A Pre-Go-Live Checklist
Before you flip an integration live across your full agent floor:
- Field mapping is documented, not tribal knowledge living in one developer's head
- Disposition codes have been audited for AMD false-positive contamination before automation rules go live on top of them
- Dedupe logic exists on lead injection in both directions
- API rate limits on both VICIdial and the CRM side are known and won't get hit during peak dial hours
- A rollback plan exists — can you disable the sync without breaking active campaigns if something goes wrong at 9am on a Monday?
- Someone owns monitoring — API failures in middleware tend to fail silently unless you're actively watching for them
Where This Actually Matters
CRM integration work is invisible when it's working and expensive when it's not — mostly because the failures don't look like integration failures. A lead that gets marked "voicemail left" when it was actually a missed live answer doesn't throw an error. It just quietly leaves your pipeline.
That's the real argument for fixing AMD accuracy before you build automation on top of disposition data, not after. amdify.io replaces Asterisk's default AMD logic with a purpose-built AI model that cuts false positive rates from the 15–25% range down to 1–3%, which means the AM bucket flowing into your CRM is actually answering machines — not live leads your dialer mislabeled on the way out. If you're planning a CRM integration project, auditing AMD accuracy first is the cheapest fix you'll make in the entire build. Learn more at amdify.io.