A Django app for testing Vonage webhooks and simple voice flows locally.
It provides:
- A webhook event viewer (
/events) with request payload/history capture. - An inbound SMS viewer (
/inboundsms) with live message history. - A "Place Call" page (
/placecall) to trigger and hang up outbound test calls via Vonage.
The landing page for the local webhook server. It provides quick navigation to event logs, inbound SMS monitoring, and outbound call testing.

Use this page to place an outbound test call to an E.164 phone number using the configured Vonage application credentials. It also shows captured call request payloads for debugging.

This state appears after a call is successfully created and tracked as active. It exposes a Hang Up action so you can end the current call directly from the UI.

This page displays inbound SMS messages received by the webhook endpoints. It helps verify number routing and payload parsing during local testing.

The event viewer captures incoming webhook requests, including headers and payloads, in a rolling in-memory log. It is useful for inspecting raw webhook traffic and troubleshooting integrations.

- Python 3.12+ (project currently appears to run on Python 3.14)
- pip
requirements.txt is currently empty, so install dependencies manually:
pip install django vonage vonage-voicepython -m venv .venv
source .venv/bin/activate
pip install django vonage vonage-voice
python manage.py migrate
python manage.py runserverOpen: http://127.0.0.1:8000/
Note: When running locally, you need a public tunnel (for example ngrok) so Vonage can send webhooks to your machine. Start your tunnel and configure your Vonage webhook URLs to use the generated public HTTPS URL.
This project auto-loads .env from the repository root.
For webhook viewing and inbound SMS pages, no Vonage credentials are required.
For outbound calling (/placecall), set:
VONAGE_APPLICATION_ID(required)VONAGE_PRIVATE_KEY(required; file path or key contents)VONAGE_SOURCE_NUMBER(required unlessVONAGE_VIRTUAL_NUMBERis set)VONAGE_VIRTUAL_NUMBER(optional fallback for source number and shown on SMS page)VONAGE_API_KEY(optional in current implementation)VONAGE_API_SECRET(optional in current implementation)VONAGE_SIGNATURE_SECRET(optional)
Example .env:
VONAGE_APPLICATION_ID=your-app-id
VONAGE_PRIVATE_KEY=/absolute/path/to/private.key
VONAGE_SOURCE_NUMBER=+15550001111
VONAGE_VIRTUAL_NUMBER=+15550001111
VONAGE_API_KEY=your-api-key
VONAGE_API_SECRET=your-api-secret
VONAGE_SIGNATURE_SECRET=your-signature-secretUI routes:
GET /home pageGET /eventswebhook event viewerGET /inboundsmsinbound SMS viewerGET /placecallplace-call formPOST /placecalltrigger callPOST /placecall/hanguphang up tracked active call
Webhook/API routes:
POST /webhook/answerreturns NCCO talk responsePOST /webhook/eventsstores generic webhook eventGET /webhook/events/listlist stored events (?since_id=<id>supported)POST /webhook/events/clearclear event historyGET|POST /webhook/inboundinbound SMS webhook aliasGET|POST /webhook/inboundsmsinbound SMS webhookGET /webhook/inboundsms/listlist SMS history (?since_id=<id>supported)GET|POST /webhook/deliverydelivery receipt webhook (event log only)
Send a test event:
curl -X POST http://127.0.0.1:8000/webhook/events \
-H "Content-Type: application/json" \
-d '{"type":"ping","source":"local"}'Send a test inbound SMS:
curl -X POST http://127.0.0.1:8000/webhook/inboundsms \
-d "msisdn=14155550100&to=18339893850&text=hello"python manage.py test voice- Event/SMS/request logs are in-memory and reset when the process restarts.
- The default Django SQLite database is
db.sqlite3. ALLOWED_HOSTSalready includeslocalhost,127.0.0.1, and*.ngrok-free.app.