> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bananaflow.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks and Callbacks

> How Bananaflow AI handles telephony webhooks and audio streaming

## Overview

Bananaflow AI uses webhooks to communicate with telephony providers for call events and audio streaming. For outbound calls, Bananaflow 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` on `https://app.bananaflow.ai`. Audio streams use the same host over `wss://app.bananaflow.ai`.

## Webhook Types

### 1. Answer Webhook

When an outbound call connects, the provider requests instructions. The path is provider-specific, and Bananaflow appends the routing parameters as a query string:

```
?workflow_id={workflow_id}&workflow_run_id={workflow_run_id}&organization_id={organization_id}
```

| Provider | Method | Path |
| - | - | - |
| Twilio, Cloudonix | `POST` | `/twiml` |
| Plivo | `POST` | `/plivo-xml` |
| Vobiz | `POST` | `/vobiz-xml` |
| Vonage | `GET` | `/ncco` |

Telnyx, Asterisk ARI, and Exotel outbound have no answer webhook. Telnyx is call-control style – Bananaflow POSTs the stream and event URLs to Telnyx's API instead of returning markup. ARI streams over a WebSocket only. Exotel Connect Voice AI attaches `StreamUrl` at dial time.

<Tabs>
  <Tab title="Twilio (TwiML)">
    ```xml theme={null}
    <?xml version="1.0" encoding="UTF-8"?>
    <Response>
        <Connect>
            <Stream url="wss://app.bananaflow.ai/api/v1/telephony/ws/123/11/789" />
        </Connect>
    </Response>
    ```
  </Tab>

  <Tab title="Vonage (NCCO)">
    ```json theme={null}
    [
      {
        "action": "connect",
        "endpoint": [{
          "type": "websocket",
          "uri": "wss://app.bananaflow.ai/api/v1/telephony/ws/123/11/789",
          "content-type": "audio/l16;rate=16000"
        }]
      }
    ]
    ```
  </Tab>
</Tabs>

Here `123` is the workflow, `11` the organization, and `789` the workflow run.

### 2. Status Callbacks

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` |
| Exotel | `/exotel/status-callback/{workflow_run_id}` |

Providers report their own vocabulary; Bananaflow normalizes it into a common set of states:

* `initiated` - Call request received
* `ringing` - Call is ringing
* `in-progress` - Call is connected and streaming
* `answered` - Call was answered
* `completed` - Call ended normally
* `busy` - Line was busy
* `no-answer` - Call not answered
* `canceled` - Call was canceled before connecting
* `failed` - Call failed
* `error` - Provider reported an error

A status Bananaflow does not recognize is passed through unchanged rather than dropped.

### 3. WebSocket Audio Stream

Real-time audio streaming for voice interaction.

**Endpoint**: `/api/v1/telephony/ws/{workflow_id}/{organization_id}/{workflow_run_id}`

When the stream URL is signed, the URL Bananaflow hands the carrier gains a fourth segment holding the HMAC signature: `/api/v1/telephony/ws/{workflow_id}/{organization_id}/{workflow_run_id}/{token}`. It is a path segment rather than a query parameter because carriers do not reliably forward query strings – Twilio strips them from `<Stream url>` entirely.

Asterisk ARI instead connects to `/api/v1/telephony/ws/ari` and passes the same three values as query parameters, plus `token` when the URL is signed – see [Asterisk ARI](/integrations/telephony/asterisk-ari).

The Telnyx call-events webhook is the other exception: it takes `?token=` in the query string, because Telnyx does preserve query strings on webhook POSTs (the restriction above is specific to carrier media-stream URLs). The route verifies it before any database lookup, so an unauthenticated caller cannot tell an existing run from a missing one by status code or by timing.

The `organization_id` segment is the tenant that owns the workflow. Bananaflow scopes every workflow and workflow-run lookup by it, so a run belonging to one organization can never be served under another's id.

**Audio Formats**:

* **Twilio / Plivo / Vobiz**: 8kHz μ-law (MULAW), Base64-encoded in JSON messages
* **Vonage**: 16kHz Linear PCM, Binary frames
* **Asterisk ARI**: 8kHz Linear PCM via externalMedia

## How It Works

Bananaflow AI automatically:

1. Builds the webhook and stream URLs for each call on `app.bananaflow.ai`
2. Passes them to the telephony provider when initiating calls
3. Verifies webhook signatures for security:
   * **Twilio**: HMAC-SHA1 signature validation
   * **Plivo / Vobiz**: HMAC-SHA256 signature validation
   * **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

## Troubleshooting

<AccordionGroup>
  <Accordion title="Signature verification failures">
    * Providers sign the full URL, query string included, so the URL in your provider's console must match the one Bananaflow set exactly
    * Confirm the auth token or signing secret saved in Bananaflow matches your provider account
  </Accordion>

  <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>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.