Early Access · centraletelefonice.ro customers

Calls missed by the whole team, not just by one extension

Smart Missed Calls knows the difference — a call routed through a queue that rang at 6 extensions and nobody picked up is ONE missed call, not six. And when someone calls back or the caller returns and a colleague answers, the entry leaves the list on its own. Full audit log included. For FreePBX and VitalPBX.

smart-missed-calls · auto-refresh
AP
Andrei Popescu ×3
+40 745 123 456 · DID 0376443322
Open
Sales Queue · Ext: 101, 102, 103, 104 8 min ago
DP
Dental Plus SRL
+40 311 555 333 · DID 0311555000
Open
IVR → 2 · Ext: 205 22 min ago
MI
Maria Ionescu ×2
+40 769 444 222 · DID 0376443322
Cleared
Reception · Ext: 101, 102 1 h ago
↩ Called back from ext. 102 — entry auto-closed
1 entry
per caller — not N per queue
auto
list cleans itself
<5 min
PBX install
Real screenshot

Dashboard — live data

Missed-call trends, resolution breakdown, hour of day, day of week, frequently called numbers — see instantly where you lose customers.

portal.pbxtools.ro/client/smart-missed-calls
Smart Missed Calls — Dashboard with missed call trends, resolution breakdown and live stats

Live capture from our portal — demo data.

Same call, two reports — see how they differ

A caller enters the "Sales" queue. The phone rings at 4 extensions with no answer. A 5th extension picks up and talks for 3 minutes. Here's how the standard report sees it versus Smart Missed Calls.

Standard CDR report
Ext 101 NO ANSWER
Ext 102 NO ANSWER
Ext 103 NO ANSWER
Ext 104 NO ANSWER
Ext 105 ANSWERED 3:14
→ 4 "missed" entries in the report
Looks like a disaster. Manager sends a complaint to the team. In reality, the call was handled — ext 105 talked to the customer.
Smart Missed Calls
Algorithm applied
SUM(ANSWERED ∧ Dial ∧ ext) = 1 → someone answered
Verdict: NOT a miss
→ 0 missed, 1 answered
The call does not show in the "missed" list because logically it wasn't — the customer was served. The list stays clean and actionable.

Same logic applies to ring groups, IVRs, chained transfers. Smart Missed Calls evaluates the WHOLE call before deciding "missed" or not.

The distinction that matters: "missed on one extension" vs "missed by the whole team"

Any FreePBX/VitalPBX CDR report will tell you extension 102 didn't answer. The real question is different: did SOMEONE eventually pick up? Or did the call fall through the queue, IVR and ring group with nobody catching it?

1

The standard report misleads you

A call into the "Sales" queue rings 5 extensions. The CDR shows 5 "NO ANSWER" rows — looks like a disaster. But a 6th extension picked up. Solved, not lost. Smart Missed Calls applies the right logic: 0 answers across the whole team = lost.

2

Static lists that age fast

This morning's report has 47 missed calls. During the day colleagues resolve 30 of them — but the list stays frozen in the PDF, the Excel, any static report. SMC is dynamic: when Maria calls Andrew back, his entry leaves the list automatically.

3

Same callers showing up 5 times

An insistent customer calls 6 times in 10 minutes. The raw report shows 6 entries. SMC aggregates per `(caller, DID)`: ONE entry with `missed_count=6` and the list of extensions that rang. Far more readable, far more actionable.

4

Nobody knows who did what

With email lists and no audit trail, the manager can't verify whether the call was actually called back or someone falsely marked it "resolved". SMC writes everything: who closed the entry, how (callback, answered later, manual mark, or retention), when, from which extension.

How it works — the actual algorithm

Three steps to start, but the internal mechanism is what makes the difference. We don't grep for "NO ANSWER" in CDR. We verify whether the call was answered BY ANYONE, anywhere in the dialplan.

1

Install the It4All agent on the PBX

One command on FreePBX or VitalPBX. Agent runs as systemd, talks to the portal via WebSocket over HTTPS/443. No exposed ports, no dialplan changes, no interference with MixMonitor or any other native service.

2

Algorithm: "did SOMEONE answer?"

For each inbound call, the query aggregates all CDR rows sharing the same `linkedid`. Simultaneous conditions: ZERO rows with `disposition='ANSWERED' AND lastapp='Dial' AND dst=internal extension` (= no human spoke) AND at least one `NO ANSWER` row or `lastapp='missed_calls'` (= evidence of a miss). Only then is it a real miss.

3

Aggregation + auto-clear

Detection is keyed on `(client, caller, DID)`. The same insistent caller increments `missed_count` instead of duplicating entries. When the agent detects an outbound answered to that number OR a new inbound answered from it — the entry transitions to `cleared` automatically, no human input.

The list cleans itself — no click, no checkbox, no export

Three automatic paths from "open" to "cleared". Each is detected from CDR on the next keepalive cycle (5 min) and recorded in the audit log with the exact reason.

cleared_by
returned

An agent calls back

Andrew on ext. 102 dials the caller. The agent detects the outbound answered call and marks the entry `cleared_by=returned`, recording extension 102 in the audit.

cleared_by
answered_later

The caller comes back

The caller dials again 30 min later, this time Maria on ext. 105 picks up. Entry auto-closes with `cleared_by=answered_later`.

cleared_by
manual

Manager marks manually

For cases handled offline (whatsapp, email, in-person visit), a permitted user ticks "Resolved". The audit logs user-id, time, and their note.

Plus: automatic retention after N days (`cleared_by=expired`, optional per client) and automatic `reopened` if the caller comes back after a close. All with full audit.

What SMC does differently from any CDR report

Five mechanisms the native FreePBX or VitalPBX report doesn't have. All of them keep the list short, accurate, and actionable.

🧠

"Team" vs "extension" detection

A queue call ringing 5 extensions where the 6th picks up is NOT missed. A direct call to ext 102 with no answer IS missed. The distinction comes from `linkedid` aggregation in CDR — all events of one logical call grouped, not one row per ring.

🔄

The list cleans itself

Three automatic close paths: (1) an agent calls the number from an internal extension → `cleared_by=returned`. (2) The caller comes back and someone answers → `cleared_by=answered_later`. (3) Manager marks resolved manually from the dashboard → `cleared_by=manual`. Plus auto-retention after N days.

📑

Per-entry audit log

Every entry has a complete journal: created, incremented, notified, cleared (with reason), reopened. With actor (agent / specific user-id / cron) and timestamp. The manager can verify whether "manually resolved" was legitimate or forced.

🔔

5 notification cadences + dedupe

Off / realtime / hourly / daily / weekly / monthly — per-client, configurable in the portal. Realtime has dedupe per `(caller, DID)` (default 5 min) and a hard rate-limit of 50 emails/hour so the inbox doesn't drown when one caller insists.

📞

Full call context

For each entry you see: caller number + name (from CRM/directory), the DID it came in on, the route label (queue/IVR/ring group), ALL extensions that rang (the list), how many attempts, first and last attempt. The rest you decide with context.

🛡️

Only metadata leaves the PBX

Recordings, transcripts, conversation content — NEVER leave your PBX. The portal receives only: caller ID, DID, time, duration, called extensions, status. That's it. Enterprise customers get self-hosted: not even metadata leaves their infrastructure.

Calculator — how many of your calls are actually lost?

Set your real numbers. We use a realistic loss rate (3-8% for a well-staffed team, 10-15% for a peak-hour call center). See how much revenue you can recover with consistent callbacks.

Potential revenue lost / month
Recoverable with consistent callback (~60%)

Indicative estimate. Actual numbers depend on your domain (B2B SaaS, retail phone sales, technical support — all have different profiles). Use your own data.

Supported PBXs

We work with most IP PBX systems. Detection reads the PBX's native CDR directly — no dialplan changes, no plugins installed on the PBX. Coverage validated on FreePBX and VitalPBX; other systems are in development or available on request.

🟢 Full support

FreePBX (self-hosted)

FreePBX 14, 15, 16, 17. Detection based on asteriskcdrdb with the missed_calls marker. Supports queues, ring groups, IVR. Public availability in 2026.

🔴 Multi-tenant

VitalPBX (multi-tenant)

VitalPBX 4.x with full per-tenant support. Each tenant has its own dashboard, separate digest, configurable retention. Public availability in 2026.

On roadmap

Other systems

FusionPBX, Issabel and other IP PBX distributions — on the roadmap. For any other SIP PBX we can scope a custom integration on request.

Privacy by design

Call data is sacred. Smart Missed Calls is designed so call content (recordings, transcripts, conversations) NEVER leaves your PBX.

Metadata only

We send to the portal: caller ID, DID, route label, list of called extensions, time and duration. That's it. No conversation, no voice, no message body.

TLS over port 443

The agent speaks to the portal via WebSocket over HTTPS on port 443. No ports opened on your PBX — works through any corporate firewall, no port forwarding, no VPN.

Immutable audit log

The `smart_missed_calls_audit` table is append-only. Every event (created, incremented, notified, closed, reopened) is logged with actor and timestamp. Nobody can "erase history".

Controlled retention

Configure how many days `open` entries persist (then auto-closed with `cleared_by=expired` and an audit entry). Set per client. No retention = "forever" mode — entries stay open until truly closed.

Self-hostable + GDPR

Enterprise customers can self-host the entire portal in their VPC — even metadata stays in their infrastructure. DPA on request, subprocessors published, right-to-be-forgotten implemented per caller.

Simple pricing, no surprises

Pay once a month, per connected PBX. 30-day Pro trial, no card required.

Free

$0

For small PBXs or testing.

  • 1 PBX connected
  • Live dashboard
  • Daily email digest (1 recipient)
  • 7-day retention
  • Community support
Request Early Access
Popular

Pro

$10 /month

For companies with real call volumes.

  • 1 PBX (or 1 VitalPBX tenant)
  • All digest cadences (hourly / daily / weekly / monthly)
  • Unlimited digest recipients
  • 90-day retention
  • Webhook & CRM integration (Odoo, HubSpot, Salesforce)
Request quote

Enterprise

Custom

For call centers and multi-PBX groups.

  • Unlimited PBXs
  • VitalPBX multi-tenant with strict isolation
  • Configurable retention (up to 7 years)
  • Optional self-hosted portal
  • 99.9% SLA & 24/7 dedicated support
Request quote

Frequently asked questions

Detailed answers to the most important questions about Smart Missed Calls.

What's the real difference between Smart Missed Calls and the native "missed calls" report in FreePBX/VitalPBX?
The native FreePBX report lists EVERY CDR row with disposition='NO ANSWER'. For a queue call ringing 5 extensions where the 6th picks up, you see 5 "missed" entries — technically correct but deeply misleading as a business signal. Smart Missed Calls aggregates all events of a call by `linkedid`, simultaneously checks the conditions (ZERO `disposition='ANSWERED' AND lastapp='Dial' AND dst=internal extension` PLUS evidence of a miss), and only THEN flags it. Plus, when the same caller insists, you don't get 6 entries — you get 1 entry with `missed_count=6`. And the entry leaves the list ON ITS OWN when someone calls back or the caller returns and gets answered.
How does the list "clean itself"? What do I actually have to do?
Nothing special. There are three automatic paths from `open` to `cleared`: (1) **returned** — one of your agents dials the caller's number from an internal extension, the agent detects the outbound answered and marks the entry `cleared_by=returned` recording which extension made the callback; (2) **answered_later** — the caller comes back and this time someone answers, the agent detects an inbound answered from the same caller+DID and marks `cleared_by=answered_later`; (3) **manual** — a manager ticks "resolved" from the dashboard (audit logs the user). Plus retention-based close (if you set N days inactivity) and automatic `reopened` if the caller comes back after a close. The full story of every entry lives in the audit log.
What does it mean that you "don't interfere with native FreePBX/VitalPBX"?
Our agent does NOT modify the dialplan, doesn't add new AMI, doesn't open extra ports, doesn't touch native recording files. On FreePBX we read asteriskcdrdb (read-only). On VitalPBX we iterate tenants and read each per-tenant DB (read-only). Communication with our portal goes through a WebSocket over HTTPS on port 443 — the same port any browser uses. UCP, Sonata Recording, Call Reports, MixMonitor — everything keeps working as VitalPBX/FreePBX expects. We are strictly observers.
How often does the list update? With what latency do I see a new missed call?
Default: 5 minutes (agent keepalive interval). Every 5 minutes the agent runs the query, finds qualifying new calls, and ships them to the portal via a REST endpoint. Perfect for a business dashboard — fast enough for coherent callbacks, light enough not to load the PBX CPU. Enterprise customers needing sub-30-seconds get push mode based on AMI listening. For sales, reception, support — 5 minutes is exactly the right balance.
How is the callback made? Is there a "call" button in the dashboard?
The callback is made FROM the agent's phone — softphone (Blureon Phone, MicroSIP, Zoiper, etc.) or physical IP phone. Smart Missed Calls is NOT a telephony app, it's a reporting/monitoring dashboard. The magic is that **you don't have to do anything special** to mark the entry resolved: if your agent dials the caller's number from a known internal extension, our agent picks up the outbound CDR row in the next cycle and closes the entry automatically with `cleared_by=returned`. The list updates itself. If you have click-to-call set up on your extension, you can copy-paste the number directly into your softphone.
How does aggregation work — does an insistent caller appear once or N times?
One entry. The aggregation key is `(client, caller_number, did)`. The first missed call creates the entry with `missed_count=1`. Subsequent calls from the same caller on the same DID increment `missed_count`, update `last_missed_at` and add any new ringing extension to the `extensions[]` array (max 10, dedup). That lets you see at a glance "Andrew tried 6 times across 4 different extensions" — useful context, not noise. And if the entry was closed and the caller comes back later, it auto-reopens with audit `reopened`.
Does it work with my CRM?
On the entry list, the caller name appears enriched from the CRM if you've set up integration (Odoo, HubSpot, Salesforce, Zoho — on Pro/Enterprise). Custom CRMs go through the generic webhook (the portal POSTs JSON to your URL with exponential retry on every new or cleared event). On Free, context comes only from the company directory and raw caller ID. Important: SMC does NOT auto-create contacts in your CRM — it only reads them for display. If you want an automatic activity/task on every missed call, do that via webhook + workflow inside your CRM.
Can I verify whether the team closes entries honestly or marks them "resolved" abusively?
Yes, that's exactly the role of the `smart_missed_calls_audit` table. Append-only, it logs each event with actor and timestamp: created, incremented, notified, cleared (with the exact reason — returned/answered_later/manual/expired), reopened. For `cleared_by=manual` entries you have the user who acted, the time, and their note. As an admin you can `reopen` a suspicious entry (audit captures that too). In practice, if an agent manually marks "resolved" without an actual callback, you'll see: "cleared_manual by user 12, no subsequent `cleared_returned` audit" — clear signal.
Which FreePBX and VitalPBX versions are supported? And what data leaves the PBX?
FreePBX 14, 15, 16, 17 — we read asteriskcdrdb with dual fallback: explicit marker `lastapp='missed_calls'` (the FreePBX native handler) OR custom CDR aggregation by `linkedid`. VitalPBX 4.x with multi-tenant support — each tenant isolated in its own dashboard, its own digest, its own DPA. Data that leaves: caller_number, caller_name (when present in CDR), DID, route_label (queue/IVR/ring group), extensions[], missed_count, first_missed_at, last_missed_at, status, cleared_*. No audio, no transcripts, no conversation content. Ever.
How do I activate the module on my PBX?
Three steps: (1) account on portal.pbxtools.ro and add the PBX (client + pbx_server config); (2) download the It4All agent with the generated API key — one copy-paste line on FreePBX/VitalPBX, installs systemd service and starts; (3) at Client level you toggle `smart_missed_calls_enabled=true`, configure retention_days, allow_manual_resolve, notification frequency and recipients. On the next keepalive cycle (5 minutes) you get the first backfill of missed calls from the past 24h. For high-volume PBXs we recommend logging into the dashboard on day one and verifying that aggregation + auto-clear behave as you expect.

Want Smart Missed Calls on your PBX?

We currently activate the module exclusively for centraletelefonice.ro customers. Tell us about your setup and we'll add you to the Early Access list — no missed call goes unseen.

💡 Got a feature or integration idea?

Help us build the ideal product for your business.

Suggest a feature

📬 Stay Updated

Subscribe to the PBXTools newsletter and be the first to know when we launch new features.