Passthru Applet
Overview
The Passthru Applet sends call and streaming metadata from Voice Applet flows to your server, especially useful when executing:
- Voicebot Applet (Bidirectional Streaming)
- Stream Applet (Unidirectional Streaming)
Passthru sends additional stream-specific parameters as query parameters, enriching standard passthru behaviour.
Refer to the standard passthru documentation here: Working with Passthru Applet
This guide is an extended version with additional parameters for streaming flows.

How It Works
Passthru makes an HTTP GET request to your URL, passing URL-encoded call and stream metadata.
Example:
GET https://yourserver.com/passthru-handler?
CallSid=56b1234567abcdef89abcdef12345678&
flow_id=voicebot-flow-xyz123&
Direction=inbound&
From=+918888000000&
To=+912233344455&
Stream[StreamSID]=6f048d2e897a0d2d4029560f3f541947&
Stream[Status]=completed&
Stream[Duration]=28&
Stream[RecordingUrl]=https://recordings.exotel.com/exotelrecordings/exotelt/6f048d2e897a0d2d4029560f3f541947.mp3&
Stream[StreamUrl]=wss://stream.customer.com/media&
Stream[DisconnectedBy]=botYour backend must parse:
- URL query parameters
- Nested keys (e.g., Stream[Status])
- JSON strings
JSON Format (Raw Query String)
Sometimes, all parameters are sent in a single JSON string under the Stream key:
Stream={"StreamSID":"62xxx...",
"RecordingUrl":"https://recordings.exotel.com/...",
"Status":"completed",
"Duration":"28",
"StreamUrl":"ws://10.32.76.120:5007/media",
"DisconnectedBy":"user"}- Ensure your backend deserialises this string correctly.
Handling Passthru Responses
Passthru requests can be handled synchronously or asynchronously:
- Sync: Exotel will immediately pass the call details synchronously during the call flow execution. It is possible only to make a binary decision using Passthru.
- 200 OK → Option A
- 302 Found → Option B
- The person on call will wait until your URL responds.
- Async: Exotel will asynchronously pass the call details without interrupting the call flow execution. Use this mode when you don’t want to dynamically change flow execution. The user will not experience a delay.
Streaming-Specific Fields (Flat Format)
Parameter | Description |
|---|---|
Stream[StreamSID] | Unique streaming session ID |
Stream[Status] | Status (completed, failed, cancelled) |
Stream[Duration] | Stream duration (seconds) |
Stream[StreamUrl] | WebSocket URL for streaming |
Stream[RecordingUrl] | URL to recording (if enabled) |
Stream[DisconnectedBy] | Disconnector (user, bot, NA) |
Stream[DetailedStatus] | Present on failure (e.g., Streaming_call_throttled) |
Stream[Error] | Error string (e.g., network failure or WS rejection) |
Note: The above fields are added on top of standard passthru parameters.
Throttling Scenario
Concurrency limit breaches trigger:
Stream[Status]=failed
Stream[DetailedStatus]=Streaming_call_throttledImplement retry or fallback strategies accordingly.
Failure Handling
Below are the most common failure and disconnection scenarios captured in the passthru payload:
Test 1: Call hung up during greeting
Expected: Capture who disconnected and status
{
"Status": "cancelled",
"DisconnectedBy": "user"
}Test 2: Invalid WebSocket URL
Expected: Failure metadata including error, stream URL, and disconnector
{
"StreamSID": "b68e46bca0fdexxxxx89643f6d81196d",
"RecordingUrl": "https://recordings.exotel.com/exotelrecordings/exotelt/b68e46bca0fdexxxxx89643f6d81196d.mp3",
"Status": "failed",
"Duration": "0",
"StreamUrl": "ws://xx.x.xx.xxx:50/media",
"Error": "3009 failed to establish ws conn dial tcp 10.1.76.120:50: connect: connection refused",
"DisconnectedBy": "NA"
}Test 3: Call cancelled after delay in streaming setup
Expected: Accurate cancellation reason and disconnection origin
{
"StreamSID": "6f048d2e897a0dxxxxx9560f3f541947",
"Status": "cancelled",
"DisconnectedBy": "user"
}Test 4: Call disconnected by bot after successful conversation
Expected: Final stream status and session metadata
{
"StreamSID": "f5dd49d7ac3xxxxx4b491ce948501947",
"Status": "completed",
"Duration": "29",
"StreamUrl": "wss://e33e-54-251-51-3.xxxxx-free.app",
"DisconnectedBy": "bot"
}These structured outputs ensure consistent understanding of streaming lifecycle and failure context.
Note: DisconnectedBy values are standardized to: user, bot, NA.
Passthru logs enriched with detailed Error messages improve debugging and recovery mechanisms.