2026-05-11 09:14:55 -04:00
|
|
|
# Voxtelesys Integration for ERPNext Helpdesk
|
2026-05-11 08:01:11 -04:00
|
|
|
|
2026-05-11 09:14:55 -04:00
|
|
|
Minimal Frappe app that receives an HTTP webhook from **3CX** when an inbound
|
|
|
|
|
call arrives (via a Voxtelesys SIP trunk) and automatically creates an
|
|
|
|
|
**HD Ticket** in Frappe Helpdesk.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Architecture
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
Voxtelesys SIP trunk → 3CX PBX → CF_URLFetch (Call Flow) → ERPNext webhook → HD Ticket
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Installation
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
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
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Webhook Endpoint
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
POST https://erp.broadcastmgmt.cloud/api/method/voxtelesys_integration.api.inbound_call
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Parameters (POST body or query string)
|
|
|
|
|
|
|
|
|
|
| Parameter | Required | Description |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `caller_id` | Yes | Inbound caller number e.g. `+12025551234` |
|
|
|
|
|
| `called_did` | No | DID that was dialled |
|
|
|
|
|
| `call_id` | No | 3CX internal call ID (for deduplication) |
|
|
|
|
|
|
|
|
|
|
### Response
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
{ "ok": true, "ticket": "HD-TICKET-00001" }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 3CX Call Flow Setup
|
|
|
|
|
|
|
|
|
|
1. Open **3CX Management Console → Call Flow Designer**
|
|
|
|
|
2. Create a new Call Flow (or edit your inbound DID's flow)
|
|
|
|
|
3. Add a **CF_URLFetch** block with these settings:
|
|
|
|
|
- **URL**: `https://erp.broadcastmgmt.cloud/api/method/voxtelesys_integration.api.inbound_call`
|
|
|
|
|
- **Method**: POST
|
|
|
|
|
- **Parameters**:
|
|
|
|
|
- `caller_id` = `[caller_id]` (3CX variable for inbound caller number)
|
|
|
|
|
- `called_did` = `[called_did]` (optional)
|
|
|
|
|
- `call_id` = `[call_id]` (optional, enables deduplication)
|
|
|
|
|
4. Connect the block in your call flow — it can run in parallel with ringing, no need to wait for the response
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Optional: Webhook Secret
|
|
|
|
|
|
|
|
|
|
To prevent unauthorized calls to the endpoint, add this to your site config:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
bench --site erp.broadcastmgmt.cloud set-config voxtelesys_webhook_secret "yourtoken"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Then append `?secret=yourtoken` to the 3CX webhook URL.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Optional: Custom Field for Deduplication
|
|
|
|
|
|
|
|
|
|
To prevent duplicate tickets if 3CX retries the webhook, add a custom field
|
|
|
|
|
to HD Ticket:
|
|
|
|
|
|
|
|
|
|
- **DocType**: HD Ticket
|
|
|
|
|
- **Field Name**: `custom_3cx_call_id`
|
|
|
|
|
- **Field Type**: Data
|
|
|
|
|
|
|
|
|
|
This can be done via **ERPNext → Customize Form → HD Ticket**.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## License
|
|
|
|
|
|
|
|
|
|
MIT
|