POST /api/v1/voice-webhook
Central voice webhook handler for Telnyx call lifecycle events
Voice Webhook
Processes all Telnyx call lifecycle events — call initiated, answered, ended, transcription complete, etc. Updates call records, triggers post-call actions (GHL notes, tags, ingestion).
Volume: ~6K runs/week | Auth: None (Telnyx webhook)
Request
POST /api/v1/voice-webhook
Content-Type: application/jsonBody Parameters
| Field | Type | Required | Description |
|---|---|---|---|
call_id | string | ✅ | Telnyx call ID |
event | string | ✅ | Event type (see below) |
call | object | Full call object from Telnyx | |
transcript | string | Call transcript | |
summary | string | AI-generated call summary | |
sentiment | string | Sentiment analysis result | |
duration_ms | number | Call duration in milliseconds | |
duration_seconds | number | Call duration in seconds | |
disconnection_reason | string | Why the call ended | |
call_status | string | Current call status | |
recording_url | string | URL to call recording | |
custom_analysis_data | object | Custom analysis results | |
variables | object | Resolved variables from the call | |
location_id | string | GHL location ID | |
contact_id | string | GHL contact ID | |
assistant_id | string | Assistant that handled the call | |
direction | string | inbound or outbound | |
to | string | Destination number | |
from | string | Source number | |
call_type | string | Type of call | |
campaign_id | string | Campaign ID | |
public_log_url | string | Public call log URL | |
call_success | boolean | Whether the call was successful | |
start_timestamp | string | ISO timestamp of call start | |
end_timestamp | string | ISO timestamp of call end |
Event Types
| Event | Description |
|---|---|
call_initiated | Call has been placed |
call_answered | Call was answered |
call_ended | Call has ended |
call_machine_detection | Voicemail/machine detected |
transcription_complete | Full transcript available |
analysis_complete | AI analysis finished |
Responses
Missing call_id or event
{ "event": "done", "call_id": "done", "path": "none" }Call Ended (with post-processing)
{
"status": "processed",
"event": "call_ended",
"call_id": "telnyx_call_uuid",
"actions": ["call_updated", "ghl_note_added", "tag_applied", "ingested"]
}Event Recorded
{
"status": "recorded",
"event": "call_initiated",
"call_id": "telnyx_call_uuid"
}Test with cURL
Call initiated event
curl -X POST http://localhost:3000/api/v1/voice-webhook \
-H "Content-Type: application/json" \
-d '{
"call_id": "call_test_001",
"event": "call_initiated",
"direction": "outbound",
"to": "+15559876543",
"from": "+15551234567",
"location_id": "loc_123",
"assistant_id": "asst_456"
}'Call ended event
curl -X POST http://localhost:3000/api/v1/voice-webhook \
-H "Content-Type: application/json" \
-d '{
"call_id": "call_test_001",
"event": "call_ended",
"duration_seconds": 180,
"transcript": "Agent: Hello! How can I help?\nCaller: I need to reschedule...",
"summary": "Customer called to reschedule appointment",
"sentiment": "positive",
"call_success": true,
"location_id": "loc_123",
"contact_id": "contact_789",
"assistant_id": "asst_456"
}'Pipeline Flow
- Validate
call_idandeventpresent - Upsert call record in DB (Prisma)
- For
call_ended:- Fetch SubAccount access token
- Add GHL contact note with transcript/summary
- Apply call outcome tag to GHL contact
- Send to ingestion pipeline
- Update call record with final data
- For other events: record and return