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]=bot
Your 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)
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_throttled
Implement 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.
Active Stream Monitoring API
Monitor active streams:
MUM Region:
curl -X GET 'http://api.in.exotel.com/v1/Accounts/{Tenant ID}/ActiveStreams'
SGP Region:
curl -X GET 'https://api.exotel.com/v1/Accounts/{Tenant ID}/ActiveStreams'
Sample Response:
{
"status": "success",
"active_streams": 12,
"max_allowed_streams": 100,
"account_sid": "Exotel"
}
Best Practices
Position Passthru immediately after Stream or Voicebot Applets.
Backend should handle both flat and JSON query formats.
Trigger fallback based on Stream[DetailedStatus].
Actively monitor concurrency limits.
Log StreamSID, RecordingUrl, and detailed errors for debugging and auditing.
Clearly interpret and handle disconnect causes (DisconnectedBy).
Passthru backend responses must comply with synchronous (HTTP codes) or asynchronous processing models appropriately.
Use Cases
Real-time monitoring of stream health
Dynamic routing based on real-time stream conditions
Enhanced debugging through detailed error reporting
Optimised concurrency and call management
Graceful error handling and escalation mechanisms
Deployment Strategy
Follow structured rollout:
Dev Environment: Validate passthru logic with mock logs.
QA/Staging: Test real call scenarios thoroughly.
Canary Release (Prod): Roll out feature gradually, monitoring closely.
Full Release: Expand to all users upon successful canary release.
Ensure rollback capabilities via feature flags and previous stable versions.
Summary
The Passthru Applet for Voice Streaming significantly enhances standard passthru functionality by providing extensive stream metadata, failure reasons, and real-time observability. Leverage these capabilities to:
Monitor and optimize streaming performance
Facilitate precise error handling and debugging
Enable intelligent and dynamic routing decisions
Implement these advanced passthru mechanisms to build robust, observable, and scalable voice-streaming integrations with Exotel APIs.