Finding Revenue Leakage Between Telephony and Billing

🔭 Scout's Take

When your phone system and billing platform don't talk to each other, services slip through unbilled. This case study covers building a reconciliation engine that audits extensions, phone numbers, and call center agents across NetSapiens and Rev.io. You'll see how real-time variance detection works, how ignore lists handle non-billable items, and why WebSocket updates matter for operations teams.

The Challenge

NetSapiens provisions phone services. Rev.io bills customers. These systems don't synchronize automatically. An extension gets created in NetSapiens, someone opens a ticket to add it to billing, the ticket sits for a day, billing adds it manually. Except sometimes the ticket gets lost. Or the provisioning team forgets to create it. Or billing adds the wrong product.

The gaps compound over time. A customer adds 5 extensions in January, billing only invoices 3 of them. In March, someone ports 2 phone numbers out but billing keeps charging for them. A call center agent gets removed from the queue but stays on the invoice for 6 months. Each discrepancy is small individually, but across hundreds of customers and thousands of services, the leakage adds up.

Manual reconciliation doesn't scale, and it's stale before the audit is even done. Opening spreadsheets, exporting data from both systems, running VLOOKUP formulas — it takes hours, and for larger accounts that add and remove users on a weekly basis, the data is already out of date by the time you finish. Subtle issues like wrong product mappings or quantity mismatches get missed entirely. The team needed continuous automated auditing that surfaces every variance in real time.

The Approach

The platform runs three parallel audits: extensions, phone numbers, and call center agents. Each audit pulls data from NetSapiens and Rev.io, normalizes it into a common format, and compares the two datasets side by side. Discrepancies get flagged and categorized: unbilled items in NetSapiens, orphaned billing in Rev.io, quantity mismatches, product mapping errors.

Extensions audit compares NetSapiens users against Rev.io subscriptions. For each NetSapiens domain, the system fetches all active users and matches them against billing accounts. If a user exists in NetSapiens but has no corresponding billing subscription, it's flagged as unbilled. If a subscription exists but the user is deleted in NetSapiens, it's flagged as orphaned billing.

Phone number audit handles the complexity of number formatting. NetSapiens stores numbers in E.164 format. Rev.io sometimes stores them with or without country codes. The audit normalizes both datasets to 10-digit format for comparison, then flags mismatches.

Call center audit cross-references queue agents. NetSapiens tracks agents, supervisors, and office managers assigned to call queues. Rev.io bills for call center seats using product mappings (e.g., "Call Center Agent" SKU). The audit checks if every active agent in NetSapiens has a corresponding billing subscription. It also validates quantities: if a customer has 10 agents in NetSapiens but is only billed for 7 seats, that's a variance.

Audit Workflow

NetSapiens Extensions Phone Numbers Rev.io Subscriptions Products Reconciliation Engine Normalize & Compare Detect Variances Variances Unbilled in NetSapiens Orphaned in Rev.io Quantity Mismatches Real-Time Updates • Redis cache (15-min TTL) • WebSocket broadcasts • Background sync jobs

Ignore Lists & Exclusions

Not everything in NetSapiens should be billed. NetSapiens treats system resources as users — voicemail boxes, auto-attendants, routing users, internal extensions — but a business doesn't bill customers for those. Ignores are actually more important for extensions than phone numbers, because of how many non-billable system users exist in a typical deployment. The platform supports ignore lists at multiple levels:

Ignoring an item doesn't make it disappear from the system. It right-sizes the account so the audit flags it as Good rather than throwing a variance. The ignore state persists in the database and syncs across audit runs. When someone marks an item as ignored, the variance count updates immediately via WebSocket. No refresh needed.

Data Flow Diagram

Data Collection NetSapiens API /users, /dids, /queues Rev.io API /subscriptions, /products Processing Reconciliation Logic 1. Normalize formats 2. Apply ignore filters 3. Cross-reference datasets 4. Flag variances Storage & Delivery PostgreSQL Audit results, ignore lists Redis Cache 15-minute TTL React Dashboard • Real-time variance display • WebSocket updates (no polling)

Technical Stack

The Outcome

Every discrepancy surfaces automatically. The dashboard shows unbilled extensions, orphaned phone numbers, call center agent mismatches — everything that doesn't align between NetSapiens and Rev.io. Operations teams log in, see the variance count, and drill into specific domains to investigate. No spreadsheets, no manual exports, no VLOOKUP formulas.

The system is always live. Unlike spreadsheet audits that are stale before they're finished, this runs continuously. When someone creates 3 extensions in NetSapiens but billing only adds 2 subscriptions, the audit flags it within 15 minutes (cache refresh interval). The team sees the variance, creates the missing subscription, and the account flips to Good on the next sync. For larger accounts adding and removing users weekly, that real-time accuracy is the difference between catching leakage and not.

Ignore lists right-size accounts without cluttering the UI. System users like voicemail boxes and routing extensions get marked once and stay excluded permanently. Instead of throwing a variance, those accounts flag as Good. The ignore state persists in the database and syncs across all audit runs. WebSocket updates mean the variance count adjusts immediately when someone marks an item as ignored.

The platform enforces data consistency between systems that were never designed to talk to each other. NetSapiens handles provisioning, Rev.io handles billing, and the reconciliation engine ensures they stay aligned. When they drift, the system surfaces it in real time so the team can fix it before customers notice or revenue gets lost.