Telephony adapters for converting recordings to vCon format - supports Twilio and more
Project description
vCon Telephony Adapters
A monorepo of webhook-based adapters that convert telephony platform recordings into vCon (Virtual Conversation) format and post them to a vCon conserver.
Overview
This project provides a unified framework for converting call recordings from various telephony platforms into the standardized vCon format:
- Twilio - Convert Twilio call recordings via webhooks
- FreeSWITCH - Convert FreeSWITCH recordings via mod_http_cache events
- Asterisk - Convert Asterisk recordings via ARI events
- Telnyx - Convert Telnyx call recordings via webhooks
- Bandwidth - Convert Bandwidth call recordings via webhooks
Architecture
vcon-telephony-adapters/
├── core/ # Shared core modules
│ ├── base_builder.py # Abstract vCon builder
│ ├── base_config.py # Base configuration
│ ├── poster.py # HTTP posting to conserver
│ └── tracker.py # State tracking for duplicates
├── adapters/ # Platform-specific adapters
│ ├── twilio/ # Twilio adapter
│ ├── freeswitch/ # FreeSWITCH adapter
│ ├── asterisk/ # Asterisk adapter
│ ├── telnyx/ # Telnyx adapter
│ └── bandwidth/ # Bandwidth adapter
├── twilio_adapter/ # Backwards compatibility layer
├── tests/ # Test suite
└── main.py # CLI entry point
Requirements
- Python 3.10+
- vcon-lib - The vCon library for creating vCon objects
Installation
Prerequisites
First, install the vcon library:
pip install git+https://github.com/vcon-dev/vcon-lib.git
Using pip
pip install -e .
Development installation
pip install -e ".[dev]"
Quick Start
Running an adapter
# Twilio
vcon-adapter twilio
# FreeSWITCH
vcon-adapter freeswitch
# Asterisk
vcon-adapter asterisk
# Telnyx
vcon-adapter telnyx
# Bandwidth
vcon-adapter bandwidth
Twilio Adapter
Configuration
# Required
CONSERVER_URL=https://your-conserver.example.com/api/vcons
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=your_auth_token_here
# Optional
PORT=8080
VALIDATE_TWILIO_SIGNATURE=true
WEBHOOK_URL=https://your-domain.com
DOWNLOAD_RECORDINGS=true
RECORDING_FORMAT=wav
Twilio Configuration Options
| Variable | Required | Default | Description |
|---|---|---|---|
TWILIO_ACCOUNT_SID |
Yes* | - | Your Twilio Account SID |
TWILIO_AUTH_TOKEN |
Yes* | - | Your Twilio Auth Token |
VALIDATE_TWILIO_SIGNATURE |
No | true |
Validate webhook signatures |
WEBHOOK_URL |
No | - | Public URL for signature validation |
* Required when DOWNLOAD_RECORDINGS=true or VALIDATE_TWILIO_SIGNATURE=true
Configuring Twilio
-
In your Twilio console, configure your phone number or TwiML app to record calls.
-
Set the Recording Status Callback URL to your adapter endpoint:
https://your-domain.com/webhook/recording -
Select the recording status events you want to receive (at minimum,
completed).
Using with TwiML
<Response>
<Record
recordingStatusCallback="https://your-domain.com/webhook/recording"
recordingStatusCallbackEvent="completed"
/>
</Response>
FreeSWITCH Adapter
Configuration
# Required
CONSERVER_URL=https://your-conserver.example.com/api/vcons
# FreeSWITCH-specific
FREESWITCH_HOST=localhost
FREESWITCH_ESL_PORT=8021
FREESWITCH_RECORDINGS_PATH=/var/lib/freeswitch/recordings
FREESWITCH_RECORDINGS_URL_BASE=https://fs.example.com/recordings
FREESWITCH_WEBHOOK_SECRET=your_webhook_secret
# Optional
PORT=8082
VALIDATE_FREESWITCH_WEBHOOK=false
DOWNLOAD_RECORDINGS=true
RECORDING_FORMAT=wav
FreeSWITCH Configuration Options
| Variable | Required | Default | Description |
|---|---|---|---|
FREESWITCH_HOST |
No | localhost |
FreeSWITCH host |
FREESWITCH_ESL_PORT |
No | 8021 |
ESL port |
FREESWITCH_RECORDINGS_PATH |
No | /var/lib/freeswitch/recordings |
Local recordings path |
FREESWITCH_RECORDINGS_URL_BASE |
No | - | URL base for HTTP downloads |
FREESWITCH_WEBHOOK_SECRET |
No | - | HMAC secret for webhook validation |
VALIDATE_FREESWITCH_WEBHOOK |
No | false |
Enable webhook signature validation |
Configuring FreeSWITCH
Add mod_http_cache or a custom event handler to send recording events to the webhook:
# In your dialplan, after recording:
<action application="curl" data="https://your-domain.com/webhook/recording post ${recording_data}"/>
The webhook expects JSON data with FreeSWITCH event variables (uuid, caller_id_number, destination_number, etc.).
Asterisk Adapter
Configuration
# Required
CONSERVER_URL=https://your-conserver.example.com/api/vcons
# Asterisk-specific (for ARI access)
ASTERISK_HOST=localhost
ASTERISK_ARI_PORT=8088
ASTERISK_ARI_USERNAME=asterisk
ASTERISK_ARI_PASSWORD=asterisk
ASTERISK_RECORDINGS_PATH=/var/spool/asterisk/recording
# Optional
PORT=8083
VALIDATE_ASTERISK_WEBHOOK=false
ASTERISK_WEBHOOK_SECRET=your_webhook_secret
DOWNLOAD_RECORDINGS=true
RECORDING_FORMAT=wav
Asterisk Configuration Options
| Variable | Required | Default | Description |
|---|---|---|---|
ASTERISK_HOST |
No | localhost |
Asterisk host |
ASTERISK_ARI_PORT |
No | 8088 |
ARI HTTP port |
ASTERISK_ARI_USERNAME |
No | - | ARI username |
ASTERISK_ARI_PASSWORD |
No | - | ARI password |
ASTERISK_RECORDINGS_PATH |
No | /var/spool/asterisk/recording |
Local recordings path |
ASTERISK_WEBHOOK_SECRET |
No | - | HMAC secret for webhook validation |
VALIDATE_ASTERISK_WEBHOOK |
No | false |
Enable webhook signature validation |
Configuring Asterisk
Use a Stasis application or AGI script to send recording events to the webhook endpoint:
// ARI recording finished handler example
client.on('RecordingFinished', function(event) {
// POST to https://your-domain.com/webhook/recording
});
Telnyx Adapter
Configuration
# Required
CONSERVER_URL=https://your-conserver.example.com/api/vcons
TELNYX_API_KEY=KEY_xxxxxxxxxxxxx
# Optional
PORT=8084
VALIDATE_TELNYX_WEBHOOK=false
TELNYX_PUBLIC_KEY=your_public_key_for_signature_validation
DOWNLOAD_RECORDINGS=true
RECORDING_FORMAT=wav
Telnyx Configuration Options
| Variable | Required | Default | Description |
|---|---|---|---|
TELNYX_API_KEY |
Yes* | - | Telnyx API key for downloading recordings |
TELNYX_PUBLIC_KEY |
No | - | Public key for webhook signature validation |
VALIDATE_TELNYX_WEBHOOK |
No | false |
Enable webhook signature validation |
* Required when DOWNLOAD_RECORDINGS=true
Configuring Telnyx
-
In the Telnyx Mission Control Portal, configure your Call Control Application.
-
Set the Webhook URL for recording events:
https://your-domain.com/webhook/recording -
Enable
call.recording.savedevents.
Bandwidth Adapter
Configuration
# Required
CONSERVER_URL=https://your-conserver.example.com/api/vcons
BANDWIDTH_ACCOUNT_ID=your_account_id
BANDWIDTH_USERNAME=your_api_username
BANDWIDTH_PASSWORD=your_api_password
# Optional
PORT=8085
VALIDATE_BANDWIDTH_WEBHOOK=false
BANDWIDTH_WEBHOOK_USERNAME=webhook_user
BANDWIDTH_WEBHOOK_PASSWORD=webhook_pass
DOWNLOAD_RECORDINGS=true
RECORDING_FORMAT=wav
Bandwidth Configuration Options
| Variable | Required | Default | Description |
|---|---|---|---|
BANDWIDTH_ACCOUNT_ID |
Yes | - | Bandwidth Account ID |
BANDWIDTH_USERNAME |
Yes* | - | API username for downloading recordings |
BANDWIDTH_PASSWORD |
Yes* | - | API password for downloading recordings |
BANDWIDTH_WEBHOOK_USERNAME |
No | - | HTTP Basic Auth username for webhook |
BANDWIDTH_WEBHOOK_PASSWORD |
No | - | HTTP Basic Auth password for webhook |
VALIDATE_BANDWIDTH_WEBHOOK |
No | false |
Enable HTTP Basic Auth validation |
* Required when DOWNLOAD_RECORDINGS=true
Configuring Bandwidth
-
In the Bandwidth Dashboard, configure your Voice Application.
-
Set the Callback URL for recording events:
https://your-domain.com/webhook/recording -
Optionally configure HTTP Basic Authentication credentials.
Common Configuration
All adapters share these common configuration options:
| Variable | Required | Default | Description |
|---|---|---|---|
CONSERVER_URL |
Yes | - | URL of your vCon conserver endpoint |
CONSERVER_API_TOKEN |
No | - | API token for conserver authentication |
CONSERVER_HEADER_NAME |
No | x-conserver-api-token |
Header name for API token |
HOST |
No | 0.0.0.0 |
Host to bind the server to |
PORT |
No | 8080 |
Port to run the server on |
DOWNLOAD_RECORDINGS |
No | true |
Download and embed recording audio |
RECORDING_FORMAT |
No | wav |
Recording format (wav or mp3) |
INGRESS_LISTS |
No | - | Comma-separated routing lists for conserver |
STATE_FILE |
No | .{adapter}_state.json |
State tracking file |
LOG_LEVEL |
No | INFO |
Logging level |
API Endpoints
All adapters expose the same endpoint structure:
POST /webhook/recording
Receives recording events from the telephony platform.
Response: Always returns 200 OK with body "OK" to acknowledge receipt.
GET /health
Health check endpoint.
Response:
{
"status": "healthy",
"service": "vcon-{platform}-adapter"
}
GET /status/{recording_id}
Get the processing status for a specific recording.
Response (200):
{
"recording_id": "rec-xxxxx",
"vcon_uuid": "550e8400-e29b-41d4-a716-446655440000",
"status": "success"
}
vCon Structure
All adapters create vCons with this structure:
{
"vcon": "0.0.1",
"uuid": "auto-generated-uuid",
"created_at": "2025-01-21T10:30:00+00:00",
"parties": [
{"tel": "+15551234567"},
{"tel": "+15559876543"}
],
"dialog": [
{
"type": "recording",
"start": "2025-01-21T10:30:00+00:00",
"duration": 120.0,
"parties": [0, 1],
"originator": 0,
"mimetype": "audio/wav",
"body": "base64-encoded-audio-data",
"encoding": "base64"
}
]
}
Platform-Specific Tags
Each adapter adds metadata tags to the vCon:
Twilio:
source:twilio_adapterrecording_sid,call_sid,account_siddirection,recording_source- Caller/called geographic info
FreeSWITCH:
source:freeswitch_adapterfreeswitch_uuid,caller_nameaccount_code,freeswitch_contextsip_user_agent
Asterisk:
source:asterisk_adapterasterisk_channel,asterisk_uniqueidlinkedid,dialplan_contextsip_user_agent,asterisk_language
Telnyx:
source:telnyx_adaptertelnyx_recording_id,telnyx_call_session_idtelnyx_call_control_id,telnyx_connection_idrecording_channels
Bandwidth:
source:bandwidth_adapterbandwidth_recording_id,bandwidth_call_idbandwidth_account_id,bandwidth_application_idrecording_channels
Development
Running tests
# Run all tests with coverage
pytest
# Run tests for a specific adapter
pytest tests/adapters/twilio/
pytest tests/adapters/freeswitch/
pytest tests/adapters/asterisk/
pytest tests/adapters/telnyx/
pytest tests/adapters/bandwidth/
# Run with verbose output
pytest -v
The test suite includes 157+ tests covering all adapters with configuration, builder, and webhook tests.
Code formatting
black .
ruff check .
Type checking
mypy core adapters
Adding New Adapters
To add support for a new telephony platform:
-
Create a new directory in
adapters/:adapters/ └── yourplatform/ ├── __init__.py ├── config.py # Extend BaseConfig ├── builder.py # Extend BaseVconBuilder └── webhook.py # FastAPI endpoints -
Implement the platform-specific recording data class by extending
BaseRecordingData -
Implement the builder by extending
BaseVconBuilderand implementing_download_recording() -
Create the webhook endpoints in a
create_app()function -
Register the adapter in
main.py
Deployment
Docker
FROM python:3.11-slim
WORKDIR /app
COPY . .
# Install vcon library
RUN pip install git+https://github.com/vcon-dev/vcon-lib.git
RUN pip install -e .
EXPOSE 8080
CMD ["vcon-adapter", "twilio"]
Docker Compose (Multiple Adapters)
version: '3.8'
services:
twilio-adapter:
build: .
ports:
- "8080:8080"
environment:
- CONSERVER_URL=https://your-conserver.example.com/api/vcons
- TWILIO_ACCOUNT_SID=${TWILIO_ACCOUNT_SID}
- TWILIO_AUTH_TOKEN=${TWILIO_AUTH_TOKEN}
command: ["vcon-adapter", "twilio"]
telnyx-adapter:
build: .
ports:
- "8084:8084"
environment:
- CONSERVER_URL=https://your-conserver.example.com/api/vcons
- TELNYX_API_KEY=${TELNYX_API_KEY}
- PORT=8084
command: ["vcon-adapter", "telnyx"]
bandwidth-adapter:
build: .
ports:
- "8085:8085"
environment:
- CONSERVER_URL=https://your-conserver.example.com/api/vcons
- BANDWIDTH_ACCOUNT_ID=${BANDWIDTH_ACCOUNT_ID}
- BANDWIDTH_USERNAME=${BANDWIDTH_USERNAME}
- BANDWIDTH_PASSWORD=${BANDWIDTH_PASSWORD}
- PORT=8085
command: ["vcon-adapter", "bandwidth"]
Production Checklist
- Enable webhook validation for your platform
- Store credentials securely (e.g., in a secrets manager)
- Use HTTPS for all endpoints
- Configure a persistent volume for the state file
- Set appropriate
LOG_LEVEL(e.g.,WARNINGorERRORfor production) - Consider running multiple adapter instances behind a load balancer
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vcon_telephony_adapters-0.2.0.tar.gz.
File metadata
- Download URL: vcon_telephony_adapters-0.2.0.tar.gz
- Upload date:
- Size: 50.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69011a6941164156886018dee860d252151ceb86b3f1e87a6ee2ccc78abe6386
|
|
| MD5 |
7ef0678ec1ebda3f3a17ca81fb4ff827
|
|
| BLAKE2b-256 |
d48074e28903c9d8184ef245d3ad337bb8568259bf878734181fcb67976ef01b
|
File details
Details for the file vcon_telephony_adapters-0.2.0-py3-none-any.whl.
File metadata
- Download URL: vcon_telephony_adapters-0.2.0-py3-none-any.whl
- Upload date:
- Size: 48.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7dd012499e08bcb42632c9a4d00a90c16a8564d9e859173f662afc8fcc93b58
|
|
| MD5 |
3b8a851d76b69c128622b42a0d1cd78a
|
|
| BLAKE2b-256 |
3b2e3479e3b2d7009a9e8c2004ce2e8c355490e14f936500914899e35f291fd1
|