| voxtelesys_integration | ||
| license.txt | ||
| MANIFEST.in | ||
| README.md | ||
| requirements.txt | ||
| setup.py | ||
Voxtelesys Integration for ERPNext / Frappe Helpdesk
Frappe app that wires the Voxtelesys voice + SMS platform into ERPNext — giving Helpdesk agents click-to-call, inbound call popups, agent routing, call recording, SMS send/receive, and auto-ticketing on missed calls.
Two architectures are supported and can run side by side:
| Path | Use when | Endpoint |
|---|---|---|
| Direct API (v2.x) — ERPNext talks to Voxtelesys directly | You want click-to-call, agent routing, SMS, and recording driven from the desk UI | api.voxtelesys.handle_inbound_call, api.sms.handle_inbound_sms |
| 3CX bridge (v1.x, legacy) — 3CX brokers calls, ERPNext just auto-creates tickets | Your 3CX PBX already routes inbound calls and you only want ticketing on the ERPNext side | api.inbound_call |
Architecture overview
Direct API path
Caller ── PSTN ──→ Voxtelesys ──webhook──→ ERPNext
│
├─ writes Voxtelesys Call Log
├─ creates HD Ticket on missed call
├─ rings agent (Round Robin / Availability)
└─ returns VoXML <Dial> → call connects to agent's phone
3CX bridge path
Caller ── PSTN ──→ Voxtelesys SIP trunk ──→ 3CX PBX
│
├─ rings extensions normally
└─ CF_URLFetch ─→ ERPNext (creates HD Ticket only)
Installation
cd ~/frappe-bench
bench get-app https://forge.wilddragon.net/zgaetano/voxtelesys_integration.git
bench --site erp.broadcastmgmt.cloud install-app voxtelesys_integration
bench --site erp.broadcastmgmt.cloud migrate
bench restart
After install, three custom fields are added via fixtures:
User.custom_voxtelesys_number— E.164 number to ring for inbound routingHD Ticket.custom_voxtelesys_call_sid— dedup for direct-API missed-call ticketsHD Ticket.custom_3cx_call_id— dedup for 3CX-bridge tickets
Configuration (direct API path)
- Get a Voxtelesys API token from the Voxtelesys developer portal.
- Open Voxtelesys Settings in ERPNext and fill in:
- Voxtelesys API Token (Bearer token)
- Default Caller ID (E.164, used for outbound voice and SMS)
- Public Base URL (e.g.
https://erp.broadcastmgmt.cloud) - Webhook Signing Secret (optional but recommended — HMAC-SHA256)
- Enable Call Recording if desired
- Inbound Call Routing (
Round Robin,Availability-Based, orDirect (no routing))
- Copy the two Webhook URLs shown in Voxtelesys Settings and paste them into:
- Voice API Profile → Answer URL:
…/api/method/voxtelesys_integration.api.voxtelesys.handle_inbound_call - SMS Profile → Inbound Webhook:
…/api/method/voxtelesys_integration.api.sms.handle_inbound_sms
- Voice API Profile → Answer URL:
- Tick Enabled and save.
- Test with the Test API Connection button on Voxtelesys Settings.
Agent routing setup
For Round Robin / Availability-Based routing to work, each agent's User
record needs a Voxtelesys Number set (the field is added automatically by
the fixture). This is the actual phone number Voxtelesys will dial — usually
the agent's cell or desk phone DID, in E.164.
Configuration (3CX bridge path)
- 3CX → Management Console → Call Flow Designer
- Create or edit the Call Flow for your inbound DID
- Add a CF_URLFetch block:
- URL:
https://erp.broadcastmgmt.cloud/api/method/voxtelesys_integration.api.inbound_call - Method: POST
- Parameters:
caller_id=[caller_id]called_did=[called_did](optional)call_id=[call_id](recommended — enables dedup)
- URL:
- Optional secret token:
bench --site … set-config voxtelesys_webhook_secret yourtokenand append?secret=yourtokento the URL.
Usage
Click-to-call
- HD Ticket form: a "Voxtelesys → Call ..." button appears in the toolbar whenever the ticket's linked Contact has a mobile / phone number.
- Lead / Contact forms: same button group; works on any Phone field via
the
frappe.phone_call.handleroverride. - A floating call bar appears at the bottom of the screen showing live call status. Clicking "Open Log" jumps to the Call Log entry.
Inbound calls
When a call hits the inbound webhook, the agent on shift gets a popup with the caller's number and a "Ringing…" indicator. If no agent answers, a missed-call HD Ticket is auto-created (toggle via Voxtelesys Settings → Auto-create Helpdesk Ticket on Missed Call).
SMS
- Send: "Voxtelesys → Send SMS" button on HD Ticket and Lead forms.
- Receive: inbound MO messages from a known Contact with an open HD
Ticket are automatically appended as a
Communicationrow on the ticket thread (toggle via Voxtelesys Settings → Auto-attach Inbound SMS to Open Ticket). - All messages are persisted to the Voxtelesys SMS Log doctype with Dynamic Link entries for cross-referencing.
DocTypes
| Name | Purpose |
|---|---|
| Voxtelesys Settings | Single — global config |
| Voxtelesys Call Log | One row per call (in or out) with status, duration, recording URL, links |
| Voxtelesys SMS Log | One row per SMS (in or out) with body, status, delivery receipt, links |
Scheduled jobs
sync_pending_call_logsruns every 5 minutes to reconcile any Call Log rows stuck inRingingorIn Progressbecause a status webhook was missed. Configured inhooks.py:scheduler_events.
Whitelisted API surface
| Method | Auth | Purpose |
|---|---|---|
voxtelesys_integration.api.voxtelesys.handle_inbound_call |
guest | Voxtelesys voice webhook |
voxtelesys_integration.api.voxtelesys.handle_call_status |
guest | Voxtelesys status callback |
voxtelesys_integration.api.voxtelesys.make_outbound_call |
user | Click-to-call from desk UI |
voxtelesys_integration.api.voxtelesys.test_connection |
sysmgr | Settings → Test button |
voxtelesys_integration.api.voxtelesys.get_linked_call_logs |
user | Form sidebar history |
voxtelesys_integration.api.sms.send_sms |
user | Send SMS from desk UI |
voxtelesys_integration.api.sms.handle_inbound_sms |
guest | Voxtelesys SMS webhook |
voxtelesys_integration.api.sms.get_linked_sms_logs |
user | Form sidebar SMS history |
voxtelesys_integration.api.inbound_call |
guest | Legacy 3CX CF_URLFetch entrypoint |
Guest endpoints verify a HMAC-SHA256 signature in the
X-Voxtelesys-Signature header against the Webhook Signing Secret in
settings (if configured). The legacy 3CX endpoint uses a query-string
?secret= token from site_config.json instead.
Development
cd ~/frappe-bench/apps/voxtelesys_integration
git remote -v # should point at forge.wilddragon.net
bench --site erp.broadcastmgmt.cloud clear-cache && bench restart
To export updated fixtures after editing custom fields in the UI:
bench --site erp.broadcastmgmt.cloud export-fixtures --app voxtelesys_integration
License
MIT