Connect Applet Setup for Inbound SIP Trunking
Connect Applet: Configuration, Dynamic URL, and Escalation via Passthru for Agent handover
Your System receive calls from PSTN
Overview
You can configure the Connect applet's parameters in one of two ways:
- Flow Builder — set sip:<TrunkID> in the Dial Whom field parameters directly in the applet's UI.
- Dynamic URL — control parameters at runtime via your own application endpoint.
Regardless of which method you choose, you must still configure the transitions (which applet runs next) while building the flow.
If you configure parameters dynamically, you set:
- A Primary URL, which handles the requests.
- An optional Fallback URL, contacted if something goes wrong with the Primary URL.
Request (Exotel → Your Application)
If an application URL is set for the Connect applet, Exotel makes a GET request to that URL with call details as URL-encoded HTTP query parameters. Only some parameters may be passed, depending on where the Connect applet sits in the flow.
Header
Header | Description |
|---|---|
Exotel-Version | Version of Connect applet parameters against which your endpoint's response will be validated. Current version: 1.0. |
Query Parameters
Parameter | Description |
|---|---|
CallSid | Unique identifier of the call. |
CallFrom | Outgoing call: number the call is made from. Incoming call: number the call is received from. |
CallTo | Outgoing call: number being dialed out. Incoming call: number where the call landed. |
Direction | incoming or outbound-dial. |
Created | Timestamp when the call is created (yyyy-mm-dd hh:mm:ss). |
DialCallDuration | Seconds from when the call is triggered to when the second leg ends (including conversation time). Can be 0 depending on the previous applet and if there's no second leg. |
StartTime | Timestamp when the call started (yyyy-mm-dd hh:mm:ss). |
EndTime | Constant value 1970-01-01 05:30:00 (Unix epoch). Use the Call Details API a few minutes after the call ends to get accurate end time. |
CallType | See table below. |
DialWhomNumber | Number of the agent who was dialed last. |
flow_id | Flow ID associated with the call. |
From | Incoming call: caller's number. Outgoing call: number of the first leg. |
To | Incoming call: the ExoPhone the call came into. Outgoing call: the number dialed. |
CurrentTime | Current server time (yyyy-mm-dd hh:mm:ss). |
CallType values:
Scenario | Value |
|---|---|
IVR only, no Connect applet | call-attempt |
Call conversation happened | completed |
Client hung up during Connect applet | client-hangup |
Connect applet, no agent picked up | incomplete |
Went to voicemail applet | voicemail |
Conditional Parameters
Passed only if certain conditions are met:
Parameter | Description |
|---|---|
DialCallStatus | What happened on the second leg if the previous applet was "Connect". Values: completed, busy, no-answer, failed, canceled. |
digits | Passed if a Gather or IVR applet preceded this one; equals the digits entered. Note: comes wrapped in double quotes (") — trim them to get the actual digits. |
CustomField | If the call was initiated via API, the value passed as CustomField in that API call. |
RecordingUrl | Populated if the previous applet was "voicemail"; contains the voicemail recording URL. There may be a delay before it's accessible, depending on recording length. |
Response (Your Application → Exotel)
This is what Exotel expects back from your GET request. It decides how Connect executes during the call to PSTN number
Response header: Content-Type: application/json
Sample response
{
"fetch_after_attempt": false,
"destination": {
"numbers": ["+919812345678"]
},
"outgoing_phone_number": "+918047115777",
"record": true,
"recording_channels": "dual",
"max_ringing_duration": 45,
"max_conversation_duration": 3600,
"music_on_hold": {
"type": "operator_tone"
},
"start_call_playback": {
"playback_to": "both",
"type": "text",
"value": "This text would be spoken out to the callee"
}
}- For custom routing to Inbound SIP trunk, use a Dynamic URL to fetch the destination URI and pass headers, as described above.
- Up to 10 custom SIP headers are supported (e.g. X-param1=value1, max 4000 bytes total). Headers prefixed with Exotel- or Veeno- are reserved by the platform.
Connect Applet — Dynamic URL response example for SIP Transfer:
{
"fetch_after_attempt": false,
"destination": { "trunk": "trunk-2134" },
"custom_params": "param1=value1¶m2=value2",
"record": true,
"recording_channels": "dual"
}Response parameters
Parameter | Mandatory/Optional | Description |
|---|---|---|
fetch_after_attempt | Optional; default false | Whether to re-fetch parameters (including destination numbers) after each unsuccessful dial attempt. false: dial happens based on the initial response only, no subsequent hits to the URL. true: Connect re-fetches parameters (hits the URL again) if a dial attempt fails. If two consecutive fetches return the exact same destination numbers, Exotel will not retry further even if this is true. Re-fetch request includes standard params plus <connect> params from previous dial attempts; response format is the same as above. |
destination | Mandatory | The destination(s) to dial. See sub-parameters below. |
destination.numbers | — | Array of E.164-format numbers to dial, in the order they appear. Example: "destination": {"numbers": ["+622131921111", "+622131921112"]}. |
destination.trunk | — | Route the call to a SIP trunk instead of a number, e.g. "destination": {"trunk": "trunk-2134"}. Used for SIP Transfer to agents/contact centers (see Escalation via Passthru Applet below). |
outgoing_phone_number | Optional; default = incoming ExoPhone | ExoPhone to dial out from (E.164 format). Must exist in your account. Subject to telecom circle/region restrictions (e.g., outgoing ExoPhone in Delhi can't be used if the incoming ExoPhone is in Bangalore). Both legs' ExoPhones can be on the same server. If the ExoPhone isn't in your account or fails validation, Exotel falls back to using the same ExoPhone as the first leg. Consult Exotel support before using this. |
record | Optional; default false | Whether to record the call. |
recording_channels | Optional; default single | single or dual (caller and callee in separate channels). |
max_ringing_duration | Optional; default 30 | Ringing duration limit, in seconds. Can be increased up to 60. |
max_conversation_duration | Optional; default 900 (15 min) | Conversation duration limit, in seconds. Can be increased up to 4500 (75 min). |
music_on_hold | Optional; default default_tone | default_tone (Exotel's default), operator_tone (audio returned by the operator on the dialing channel as-is), or custom_tone (audio URL provided in the response). Example: {"type": "custom_tone", "value": "<audio_url>"}. |
parallel_ringing | Optional | Dial all destination numbers simultaneously: {"activate": true, "max_parallel_attempts": 5}. max_parallel_attempts range 1–10, default 5. Chargeable feature — confirm with your Account Manager or [email protected] before use. |
dial_passthru_event_url | Optional | URL requested for dial start and dial end events. |
start_call_playback | Optional | Play a recording or TTS to the called number. playback_to: both or callee. type: audio_url or text. Example: {"playback_to": "both", "type": "text", "value": "hello, this is a sample text"}. Audio file requirements: 8 kHz sample rate, 16-bit depth, 128 kbps bit rate, mono channel, .wav format. If reusing the same audio_url filename, it will be cached by Exotel servers — use dynamic filenames if the audio content changes each time. |
custom_params | Optional | Custom SIP headers passed with a trunk-routed call, e.g. "custom_params": "param1=value1¶m2=value2". Up to 10 custom headers, max 800 bytes each(overall 4KB). Headers prefixed with Exotel- or Veeno- are platform-reserved. |
All of the above can also be set via the dashboard if you configure the Connect applet through the Flow Builder instead of a Dynamic URL.
Fallback URL triggers
The Fallback URL is called when:
- The Primary URL doesn't return HTTP 200 OK.
- The Primary URL doesn't respond within the timeout period (5 seconds).
- The Primary URL returns an invalid response:
- Content-Type is not application/json.
- Mandatory parameters are missing.
- audio_url / text isn't a valid HTTP/HTTPS URL returning 200.
Transition to Next Applet
Set these transitions in the Flow Builder to decide what runs next:
References
- Programmable Connect: Working with Connect Applet (Dynamic URL)Programmable Connect: Working with Connect Applet (Dynamic URL)
- Passthru AppletPassthur