2025-10-27 15:29:57 +05:30
---
title: "Webhooks and Callbacks"
description: "How Dograh AI handles telephony webhooks and audio streaming"
---
## Overview
2026-07-10 16:52:43 +05:30
Dograh AI uses webhooks to communicate with telephony providers for call events and audio streaming. For outbound calls, Dograh builds these URLs and hands them to the provider when it dials — you never configure them by hand. For inbound calls, you point your provider at a single dispatcher URL; see [Inbound Calls](/integrations/telephony/inbound).
Every webhook path lives under `/api/v1/telephony`.
2025-10-27 15:29:57 +05:30
## Webhook Types
2026-07-10 16:52:43 +05:30
### 1. Answer Webhook
When an outbound call connects, the provider requests instructions. The path is provider-specific, and Dograh appends the routing parameters as a query string:
2025-10-27 15:29:57 +05:30
2026-07-10 16:52:43 +05:30
```
?workflow_id={workflow_id}&workflow_run_id={workflow_run_id}&organization_id={organization_id}
```
2025-10-27 15:29:57 +05:30
2026-07-10 16:52:43 +05:30
| Provider | Method | Path |
| --- | --- | --- |
| Twilio, Cloudonix | `POST` | `/twiml` |
| Plivo | `POST` | `/plivo-xml` |
| Vobiz | `POST` | `/vobiz-xml` |
| Vonage | `GET` | `/ncco` |
2025-10-27 15:29:57 +05:30
2026-07-10 16:52:43 +05:30
Telnyx and Asterisk ARI have no answer webhook. Telnyx is call-control style — Dograh POSTs the stream and event URLs to Telnyx's API instead of returning markup. ARI streams over a WebSocket only.
2025-10-27 15:29:57 +05:30
<Tabs>
<Tab title="Twilio (TwiML)">
```xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Connect>
2026-07-10 16:52:43 +05:30
<Stream url="wss://your-domain/api/v1/telephony/ws/123/11/789" />
2025-10-27 15:29:57 +05:30
</Connect>
</Response>
```
</Tab>
<Tab title="Vonage (NCCO)">
```json
[
{
"action": "connect",
"endpoint": [{
"type": "websocket",
2026-07-10 16:52:43 +05:30
"uri": "wss://your-domain/api/v1/telephony/ws/123/11/789",
2025-10-27 15:29:57 +05:30
"content-type": "audio/l16;rate=16000"
}]
}
]
```
</Tab>
</Tabs>
2026-07-10 16:52:43 +05:30
Here `123` is the workflow, `11` the organization, and `789` the workflow run.
2025-10-27 15:29:57 +05:30
2026-07-10 16:52:43 +05:30
### 2. Status Callbacks
2025-10-27 15:29:57 +05:30
2026-07-10 16:52:43 +05:30
Receive call lifecycle events. Each is keyed on the workflow run:
| Provider | Path |
| --- | --- |
| Twilio | `/twilio/status-callback/{workflow_run_id}` |
| Plivo | `/plivo/hangup-callback/{workflow_run_id}`, `/plivo/ring-callback/{workflow_run_id}` |
| Vobiz | `/vobiz/hangup-callback/{workflow_run_id}`, `/vobiz/ring-callback/{workflow_run_id}` |
| Vonage | `/vonage/events/{workflow_run_id}` |
| Telnyx | `/telnyx/events/{workflow_run_id}` |
| Cloudonix | `/cloudonix/status-callback/{workflow_run_id}`, `/cloudonix/cdr` |
Providers report their own vocabulary; Dograh normalizes it into a common set of states:
2025-10-27 15:29:57 +05:30
- `initiated` - Call request received
- `ringing` - Call is ringing
2026-07-10 16:52:43 +05:30
- `in-progress` - Call is connected and streaming
2025-10-27 15:29:57 +05:30
- `answered` - Call was answered
- `completed` - Call ended normally
- `busy` - Line was busy
- `no-answer` - Call not answered
2026-07-10 16:52:43 +05:30
- `canceled` - Call was canceled before connecting
2025-10-27 15:29:57 +05:30
- `failed` - Call failed
2026-07-10 16:52:43 +05:30
- `error` - Provider reported an error
A status Dograh does not recognize is passed through unchanged rather than dropped.
2025-10-27 15:29:57 +05:30
### 3. WebSocket Audio Stream
Real-time audio streaming for voice interaction.
2026-07-10 16:52:43 +05:30
**Endpoint**: `/api/v1/telephony/ws/{workflow_id}/{organization_id}/{workflow_run_id}`
Asterisk ARI instead connects to `/api/v1/telephony/ws/ari` and passes the same three values as query parameters — see [Asterisk ARI](/integrations/telephony/asterisk-ari).
The `organization_id` segment is the tenant that owns the workflow. Dograh scopes every workflow and workflow-run lookup by it, so a run belonging to one organization can never be served under another's id.
2025-10-27 15:29:57 +05:30
**Audio Formats**:
2026-07-10 16:52:43 +05:30
- **Twilio / Plivo / Vobiz**: 8kHz μ-law (MULAW), Base64-encoded in JSON messages
2025-10-27 15:29:57 +05:30
- **Vonage**: 16kHz Linear PCM, Binary frames
2026-07-10 16:52:43 +05:30
- **Asterisk ARI**: 8kHz Linear PCM via externalMedia
2025-10-27 15:29:57 +05:30
## How It Works
Dograh AI automatically:
1. Constructs webhook URLs based on your deployment
2. Passes them to the telephony provider when initiating calls
3. Verifies webhook signatures for security:
- **Twilio**: HMAC-SHA1 signature validation
2026-07-10 16:52:43 +05:30
- **Plivo / Vobiz**: HMAC-SHA256 signature validation
2025-10-27 15:29:57 +05:30
- **Vonage**: JWT token verification
4. Processes status updates to track call lifecycle
5. Manages WebSocket connections for audio streaming
6. Handles provider-specific audio formats and protocols
2026-07-10 16:52:43 +05:30
Signature verification is implemented per provider in `verify_inbound_signature`. If you are adding a provider, see [Custom Telephony Provider](/integrations/telephony/custom).
2025-10-27 15:29:57 +05:30
## Local Development
For local development, use the built-in Cloudflare tunnel:
```yaml
# docker-compose.yml includes:
cloudflared:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate --url http://api:8000
```
The tunnel URL is automatically detected and used for webhooks.
## Troubleshooting
<AccordionGroup>
<Accordion title="Webhook URL not accessible">
- Verify your domain/tunnel URL is publicly accessible
- Check firewall rules allow incoming HTTPS traffic
- Test with `curl` from external network
</Accordion>
2026-07-10 16:52:43 +05:30
<Accordion title="Signature verification failures">
- Providers sign the full URL, query string included — a proxy that rewrites or reorders query parameters will invalidate the signature
- Confirm the backend's public URL matches what the provider was given, including scheme and port
</Accordion>
2025-10-27 15:29:57 +05:30
<Accordion title="WebSocket connection dropping">
- Check WebSocket upgrade headers are preserved
- Verify no timeout on load balancer/proxy
- Monitor for memory/CPU constraints
</Accordion>
2026-07-10 16:52:43 +05:30
2025-10-27 15:29:57 +05:30
<Accordion title="Status callbacks not received">
- Verify workflow_run_id is included in URL
- Check provider console for webhook errors
- Review webhook retry logs
</Accordion>
2026-07-10 16:52:43 +05:30
</AccordionGroup>