Backend
Monitor Call Quality in Real Time with Telnyx Webhooks and Python
Harpreet Singh Seehra Dev.to (EN Zone)
1 views
Call quality is not a single number you check once. It is a stream of measurements — MOS, jitter, latency, packet loss — that arrive while a call is active and that you need to inspect afterward. This sample puts that stream into a Flask dashboard with live SSE updates, SQL-backed history, and threshold alerting, all verifiable without a Telnyx account.
I work with Telnyx. The code is available here: https://github.com/team-telnyx/telnyx-code-examples/tree/main/call-quality-monitor
What the sample does
The Call Quality Monitor receives Telnyx call quality webhooks, verifies each payload's Ed25519 signature, and stores the metrics in SQLite for historical analysis. An in-memory key-value store tracks per-call state so the dashboard can show what is happening right now. When MOS drops below a threshold or jitter exceeds a limit, an alert fires and is pushed to the browser over a Server-Sent Events stream.
The dashboard at / shows live metrics and alerts. The API exposes filtered queries by call ID, time range, and aggregate statistics. A demo server (demo/demo_server.py) generates an Ed25519 keypair on first run, signs webhook payloads, and posts them to the real /webhooks/call-quality endpoint — the full pipeline runs end-to-end on localhost:5555 without Telnyx credentials or ngrok.
Architecture
Telnyx Voice
│
│ Call quality webhooks (MOS, jitter, latency, packet loss)
▼
Flask App (app.py)
│
├── Ed25519 signature verification (pynacl)
│
├── Process quality metrics
│ ├── SQLite INSERT (historical analytics)
│ └── In-memory KV update (per-call state)
│
├── Threshold checker
│ ├── MOS < 3.5 → alert
│ ├── Jitter > 30ms → alert
│ └── Latency > 150ms → alert
│
└── SSE broadcast → browser dashboard
Run the demo locally
No Telnyx account is needed. The demo server generates its own Ed25519 keypair, signs webhook payloads, and posts them to the real Flask endpoint.
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/call-quality-monitor
pip install -r requirements.txt
pip install requests # needed by the demo webhook sender
python demo/demo_server.py
Open http://localhost:5555/ and use the demo controls:
Start 3 Calls — Simulates three concurrent calls with varying quality metrics. One call is healthy, one degrades over time, and one starts bad. The dashboard updates live via SSE.
Trigger Alert — Pushes a metric that crosses the MOS threshold and watch the alert appear in real time.
Reset Data — Clears the SQLite database and in-memory state.
The demo server runs on port 5555 and hosts both the Flask app and a webhook sender thread that posts signed payloads to /webhooks/call-quality. The Ed25519 keypair is generated on first run and stored in a local file. No external service is contacted.
How webhook verification works
Telnyx signs every webhook payload with an Ed25519 key. The Flask app verifies each signature using pynacl before processing the payload. This prevents forged webhook deliveries from injecting fake quality metrics into your dashboard.
import nacl.signing
import nacl.encoding
verify_key = nacl.signing.VerifyKey(
base64.b64decode(public_key_b64),
encoder=nacl.encoding.RawEncoder
)
verify_key.verify(signed_payload, signature)
The demo server generates its own keypair on first run, signs payloads with the private key, and the Flask app verifies them with the corresponding public key. In production, Telnyx holds the private key and you configure the public key from the Portal.
Why SSE instead of WebSocket
Server-Sent Events are unidirectional (server to browser), which is all a monitoring dashboard needs. SSE runs over standard HTTP, works through proxies without extra configuration, and reconnects automatically. The browser's EventSource API is simpler than WebSocket and sufficient for a read-only live feed.
Connect to live Telnyx webhooks
For production use, configure your Telnyx webhook URL in the Portal:
https://<your-domain>/webhooks/call-quality
Set these environment variables:
Variable
Description
Example
TELNYX_API_KEY
Your Telnyx API key
KEY019...
TELNYX_PUBLIC_KEY
Your Telnyx public key (Ed25519)
-----BEGIN PUBLIC KEY-----...
DB_PATH
SQLite database path
quality.db
MOS_THRESHOLD
Minimum acceptable MOS score
3.5
JITTER_THRESHOLD
Maximum jitter in ms
30
LATENCY_THRESHOLD
Maximum latency in ms
150
PORT
Flask server port
5000
API endpoints
Method
Endpoint
Description
POST
/webhooks/call-quality
Receive and verify Telnyx call quality webhooks
GET
/
Live SSE dashboard
GET
/events
SSE stream endpoint
GET
/api/quality/<call_id>
All metrics for a specific call
GET
/api/quality
All metrics with optional filters
GET
/api/quality/stats
Aggregate statistics
GET
/api/quality/alerts
All threshold alerts
GET
/health
Health check
Testing
python -m pytest smoke_test.py -v
9 tests covering webhook verification, metric storage, threshold alerting, API endpoints, and SSE streaming. All pass.
Read original: https://dev.to/harpreetseehra/monitor-call-quality-in-real-time-with-telnyx-webhooks-and-python-5aad
← Previous
My Security App Used to "Encrypt" Passwords With XOR. Here's the Post-Mortem I Wish More Devs Wrote.
Next →
Where Alpha Testing Fits in SDLC, Agile, and CI/CD
Related
AI psychosis might be a result of subscription fatigue
Backend
0
DEV Community
Dead Code Is More Dangerous Than Broken Code — How a Non-Homologous AI Caught the Blind Spot the AI Itself Had Rubber-Stamped
Backend
0
DEV Community
Borsa Verisiyle Çalışırken Sürekli Dönüp Dolaşıp Kullandığım 6 Python Kütüphanesi
Backend
0
Dev.to (EN Zone)
Web Developer = Embedded Developer: Real PHP Now Runs on the ESP32 (v1.0.0)
Backend
1
DEV Community
Comments0
No comments yet — be the first