Skip to main content

Connect Two Numbers

Initiate an outbound call that connects two phone numbers — typically an agent and a customer. Exotel first calls the From number, waits for it to answer, then dials the To number and bridges the two legs.

Using Voice v1 endpoint

Call initiation in Voice v3 uses the Voice v1 endpoint (/v1/Accounts/...). Use the Voice v3 Call Details API to fetch enhanced reporting on the call after it is placed.

Endpoint​

POST /v1/Accounts/<account_sid>/Calls/connect

Content-Type: application/x-www-form-urlencoded

Regional Base URLs​

RegionBase URL
Singaporehttps://<api_key>:<api_token>@api.exotel.com
Mumbaihttps://<api_key>:<api_token>@api.in.exotel.com

Request Parameters​

Required​

ParameterTypeDescription
FromStringThe number dialled first (typically your agent or dialler). Preferably E.164 format (e.g., +919900XXXXXX).
ToStringThe customer's phone number. Preferably E.164 format.
CallerIdStringYour Exotel ExoPhone / virtual number used as the outbound caller ID.

Optional​

ParameterTypeDefaultDescription
CallTypeString—Set to trans for transactional calls.
TimeLimitInteger—Maximum call duration in seconds. Maximum value: 14400 (4 hours).
TimeOutInteger—Ringing timeout in seconds before the call is considered unanswered.
WaitUrlString—Audio file URL (WAV) played to the From caller while waiting for To to answer. File should be under 2 MB. Note: URLs are cached — append a unique query parameter (e.g., ?v=2) when updating audio.
RecordBooleanfalseSet to true to record the conversation.
RecordingChannelsStringsinglesingle (merged audio) or dual (separate channels per leg).
RecordingFormatStringmp3mp3 or mp3-hq (high quality).
StreamUrlString—WebSocket URL for real-time audio streaming. See AgentStream.
StreamBeginString—When streaming starts: at Leg1Connect or at Leg2Connect.
CustomFieldString—Custom metadata string, max 128 characters. Passed through to StatusCallback and applets.
StartPlaybackToNewStringCalleeWho hears pre-call audio: Callee or Both.
StartPlaybackValueNewString—Audio URL played to the specified party before the call connects.
StatusCallbackString—Webhook URL to receive call status updates (POST).
StatusCallbackEventsArray—Events to trigger the callback: terminal, answered, or both.
StatusCallbackContentTypeStringmultipart/form-dataFormat of the callback payload: multipart/form-data or application/json.

Code Examples​

curl -X POST \
'https://<api_key>:<api_token>@api.exotel.com/v1/Accounts/<account_sid>/Calls/connect' \
-d 'From=+919900XXXXXX' \
-d 'To=+918800XXXXXX' \
-d 'CallerId=09XXXXXXXXX' \
-d 'Record=true' \
-d 'TimeLimit=600' \
-d 'StatusCallback=https://your-server.com/callback' \
-d 'StatusCallbackEvents[]=terminal'

Response​

{
"Call": {
"Sid": "b6cfaf5f5cef3ca0fc937749ef96d245",
"ParentCallSid": null,
"DateCreated": "2024-03-03 10:48:33",
"DateUpdated": "2024-03-03 10:53:33",
"AccountSid": "<account_sid>",
"To": "0XXXXX38847",
"From": "0XXXXX30240",
"PhoneNumberSid": "0XXXXXX4890",
"Status": "in-progress",
"StartTime": "2024-03-03 10:48:33",
"EndTime": null,
"Duration": null,
"Price": null,
"Direction": "outbound-api",
"AnsweredBy": null,
"RecordingUrl": null,
"Details": {
"ConversationDuration": 0,
"Leg1Status": "in-progress",
"Leg2Status": "queued",
"Legs": []
}
}
}

Response Fields​

FieldTypeDescription
Call.SidStringUnique call identifier. Use this with the Call Details API for enhanced reporting.
Call.ParentCallSidString / nullParent call identifier if this is a child call.
Call.DateCreatedDateTimeTimestamp when the call was created.
Call.DateUpdatedDateTimeTimestamp of the last status update.
Call.AccountSidStringYour Exotel account SID.
Call.ToStringThe To phone number.
Call.FromStringThe From phone number.
Call.PhoneNumberSidStringIdentifier of the ExoPhone used as CallerId.
Call.StatusStringCall status — see Call Statuses below.
Call.StartTimeDateTimeTime the call was initiated.
Call.EndTimeDateTime / nullTime the call ended (null while in progress).
Call.DurationString / nullTotal duration in seconds (updates ~2 minutes after call ends).
Call.PriceString / nullCall cost (updates ~2 minutes after call ends).
Call.DirectionStringoutbound-api for calls initiated via this endpoint.
Call.AnsweredByString / nullHuman, Machine, NotSure, or NA.
Call.RecordingUrlString / nullDirect URL to recording MP3 (populated if Record=true).
Call.Details.ConversationDurationIntegerSeconds both parties were connected.
Call.Details.Leg1StatusStringStatus of the From leg.
Call.Details.Leg2StatusStringStatus of the To leg.
Call.Details.LegsArrayPer-leg detail objects with Id and OnCallDuration.
note

Duration, Price, and EndTime are populated asynchronously — typically within 2 minutes after the call ends. Use the StatusCallback webhook to receive the final values.

Call Statuses​

StatusDescription
queuedCall is queued, waiting to be sent to the operator.
in-progressCall is currently active.
completedCall ended normally.
failedCall could not be completed.
busyTo number was busy.
no-answerCall was not answered within TimeOut.

StatusCallback Webhook​

When the call reaches a terminal state (or is answered, if configured), Exotel sends a POST to your StatusCallback URL.

Payload Fields​

ParameterDescription
CallSidUnique call identifier.
EventTypeterminal or answered.
StatusFinal call status (completed, failed, busy, no-answer).
FromFrom-leg number.
ToTo-leg number.
PhoneNumberSidExoPhone identifier.
StartTimeCall start timestamp.
EndTimeCall end timestamp.
DurationTotal call duration in seconds.
ConversationDurationTalk time in seconds.
RecordingUrlRecording URL (if Record=true).
Directionoutbound-api.
CustomFieldCustom data passed in the original request.
LegsArray of per-leg status objects (see below).

Legs Array​

{
"Legs": [
{
"OnCallDuration": 41,
"Status": "completed",
"AnsweredBy": "NA"
},
{
"OnCallDuration": 32,
"Status": "completed",
"AnsweredBy": "Human"
}
]
}

AnsweredBy values:

ValueDescription
HumanAnswered by a person.
MachineAnswered by voicemail or an IVR.
NotSureCould not determine.
NANot applicable (first / From leg).

HTTP Status Codes​

CodeDescription
200Success — call queued.
400Bad Request — missing or invalid parameters.
401Unauthorized — invalid API credentials.
429Rate limit exceeded (200 calls/minute).
500Server error.

Fetch Enhanced Call Details​

After placing a call, use the Call.Sid from the response to retrieve enhanced reporting via Voice v3:

curl -X GET \
'https://<api_key>:<api_token>@ccm-api.exotel.com/v3/accounts/<account_sid>/calls/<call_sid>' \
-H 'Content-Type: application/json'

The v3 Call Details response includes richer metadata: DTMF digits, recording objects, app/flow information, and per-leg data. See Call Details (v3).

Try It​