Calls

Place outbound calls with POST /api/calls. Inbound calls go to the webhook URL set on the number in the dashboard. Either way your endpoint returns markup (XML, or JSON for a smaller verb set) telling Connect what to do. See call-control markup. You can fetch a call's record by its SID.

API stabilityConnect is live. The API is v0.x, so field names may change before v1. Base URL: https://connect.telvox.dev/api. Sample numbers are placeholders; outbound dialling is set up for Indian numbers.

Properties

Fetching a call returns its call log record with these fields.

PropertyTypeDescription
call_sidstringUnique ID for the call: CA plus 32 uppercase letters and digits.
from_numberstringThe calling number. For outbound calls, the claimed number you passed as from.
to_numberstringThe number that was called.
directionenuminbound or outbound.
statusenumWhere the call is now. See the status values below.
durationintegerCall length in seconds, once the call has ended.
pricestringCost of the call as a decimal string. Can be null.
price_unitstringCurrency of price. Can be null.
webhook_urlstringWhere Connect fetched markup for this call: your url for outbound, the number's webhook URL for inbound.
status_callbackstringWhere status callbacks for this call are sent. Can be null.
recording_urlstringThe name of the call's recording (not a full URL). Pass it to GET /api/recordings/{recordingName}. Null if nothing was recorded.
recording_statusstringLatest recording state, for example recording, paused or stopped. Can be null.
recording_sourcestringHow the recording was made, for example bridge or channel. Can be null.
error_messagestringWhy the call failed, when it did. Otherwise null.
start_timestringISO 8601 time the call entered Connect.
ringing_atstringISO 8601 time the far end started ringing.
answered_atstringISO 8601 time the call was answered. Null if it never was.
end_timestringISO 8601 time the call ended.
created_atstringISO 8601 time the record was created.
updated_atstringISO 8601 time the record last changed.
metadataobjectInternal trace data. It may change at any time, so do not depend on it.

Status values

The status field moves through these values. The final ones (completed, busy, no-answer, failed, canceled) mean the call is over.

ValueTypeDescription
initiatedstatusThe call is being placed. POST /api/calls returns this.
ringingstatusThe destination is ringing.
in-progressstatusThe call was answered and is connected.
completedstatusThe call was answered and then ended.
busystatusThe destination returned busy.
no-answerstatusThe call rang but nobody answered.
failedstatusThe call could not be connected (network or carrier error).
canceledstatusThe call ended before it was answered.

Create a call

Place an outbound call. When the callee answers, Connect POSTs to your url and runs the XML or JSON markup it returns.

POST/api/calls

Place an outbound call from one of your claimed numbers.

ParameterTypeDescription
torequiredstringDestination number in E.164 (10 or more digits, + optional), or a SIP peer name on the platform.
fromrequiredstringA number you have claimed in the dashboard and that is active, in the same format shown there, for example +918045670100. Any other number returns 422.
urlrequiredstringConnect POSTs JSON {call_sid, to, from, direction} here when the call is answered. Reply with XML or JSON markup.
statusCallbackstringWhere to POST status callbacks for this call. status_callback is also accepted.
statusCallbackEventarrayAn array or a space-separated string. ringing, in-progress and the final status are always sent. Add initiated to also get the initiated event. status_callback_event is also accepted.
POST/api/calls
curl -X POST https://connect.telvox.dev/api/calls \
  -H "Authorization: Bearer $TELVOX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "from": "+918045670100",
    "to": "+919876500199",
    "url": "https://your.app/voice/answer",
    "statusCallback": "https://your.app/voice/status",
    "statusCallbackEvent": ["initiated"]
  }'
201 createdinitiated
201 response
{
  "call_sid": "CA7Q2M9X4K1B8N3T6R0W5Y2Z9C1V4H7JL5",
  "to": "+919876500199",
  "from": "+918045670100",
  "status": "initiated",
  "channel_id": "1719912345.1234"
}
201 created

If from is not one of your active numbers you get 422 with an error message. A missing or invalid field returns 422 with message and errors. If the call cannot be placed you get 500 with {"error": "Failed to initiate call: ..."}. See errors.

What your url receives

After the callee answers, Connect POSTs this JSON to your url with the header X-CPaaS-Event: webhook.outbound. Reply with markup. For inbound calls the number's webhook URL gets {"from", "to", "direction": "inbound"} instead, with no call_sid, and has 5 seconds to answer.

POSTyour url
{
  "call_sid": "CA7Q2M9X4K1B8N3T6R0W5Y2Z9C1V4H7JL5",
  "to": "+919876500199",
  "from": "+918045670100",
  "direction": "outbound"
}
200 · application/xml

Fetch a call

Get one call by its SID. The record is updated while the call is live, so you can poll it, or use it to catch up on a status callback you missed. A call SID that is not on your account returns 404.

GET/api/calls/{callSid}

Fetch one call's record by its SID.

GET/api/calls/{callSid}
curl https://connect.telvox.dev/api/calls/CA7Q2M9X4K1B8N3T6R0W5Y2Z9C1V4H7JL5 \
  -H "Authorization: Bearer $TELVOX_API_KEY" \
  -H "Accept: application/json"
200 ok
200 response
{
  "call_sid": "CA7Q2M9X4K1B8N3T6R0W5Y2Z9C1V4H7JL5",
  "from_number": "+918045670100",
  "to_number": "+919876500199",
  "direction": "outbound",
  "status": "completed",
  "duration": 47,
  "price": null,
  "price_unit": null,
  "webhook_url": "https://your.app/voice/answer",
  "status_callback": "https://your.app/voice/status",
  "recording_url": null,
  "recording_status": null,
  "error_message": null,
  "start_time": "2026-06-22T17:04:11.000000Z",
  "ringing_at": "2026-06-22T17:04:13.000000Z",
  "answered_at": "2026-06-22T17:04:19.000000Z",
  "end_time": "2026-06-22T17:05:06.000000Z",
  "created_at": "2026-06-22T17:04:11.000000Z",
  "updated_at": "2026-06-22T17:05:06.000000Z"
}
200 ok

Other internal fields such as metadata may also appear. Do not depend on them.

Call history and live calls

There is no endpoint to list calls. Your call history is in the dashboard, and your status callbacks give you a record of every call as it happens. There is also no REST endpoint to redirect or hang up a live call. To pause, resume or stop recording on a live call, see Recordings.

Status callbacks

Connect POSTs JSON to your statusCallback as the call moves on. ringing, in-progress and the final status are always sent; initiated only if you list it in statusCallbackEvent. Field names follow Twilio's call progress events. Each request has a 5 second timeout and is not retried. Requests carry User-Agent: cPaaS-Platform/1.0, X-CPaaS-Event and X-CPaaS-Call-Sid headers.

CallStatusSent when
initiatedThe call is being placed. Only if you subscribed to it.
ringingThe destination starts ringing.
in-progressThe call was answered.
completed, busy, no-answer, failed, canceledThe call is over. WebhookEvent is call.hangup, IsFinal is true, and Duration and CallDuration are included.

Callback payload

POSTyour statusCallback
{
  "ApiVersion": "2010-04-01",
  "AccountSid": "AC3b1f...",
  "CallSid": "CA7Q2M9X4K1B8N3T6R0W5Y2Z9C1V4H7JL5",
  "CallStatus": "in-progress",
  "Direction": "outbound-api",
  "From": "+918045670100",
  "To": "+919876500199",
  "Caller": "+918045670100",
  "Called": "+919876500199",
  "CallerCountry": "IN",
  "FromCountry": "IN",
  "CallbackSource": "call-progress-events",
  "SequenceNumber": "2",
  "Timestamp": "Mon, 22 Jun 2026 17:04:19 +0000",
  "WebhookEvent": "call.status",
  "EventType": "call.status",
  "CallbackId": "CA7Q2M9X4K1B8N3T6R0W5Y2Z9C1V4H7JL5:2",
  "IsFinal": false,
  "EventTimestamp": "2026-06-22T17:04:19.000Z",
  "WebhookUrl": "https://your.app/voice/answer"
}
reply 2xx within 5 sin-progress
FieldTypeDescription
CallSidstringThe call this callback is about.
CallStatusenuminitiated, ringing, in-progress, completed, busy, no-answer, failed or canceled.
From, TostringThe calling and called numbers. Caller and Called carry the same values.
Directionenumoutbound-api or inbound.
TimestampstringWhen the event happened, in RFC 2822 format.
EventTimestampstringThe same moment in ISO 8601.
SequenceNumberstringGoes up with each callback for the call. Use it to put callbacks in order.
WebhookEventenumcall.status for progress events, call.hangup for the final one. EventType carries the same value.
IsFinalbooleantrue on the last callback for the call.
CallbackIdstringCallSid:SequenceNumber. Use it to drop duplicates.
DurationstringFinal callback only. Billed minutes.
CallDurationstringFinal callback only. Call length in seconds.
HangupSource, HangupReason, HangupCausestringFinal callback only. Who ended the call and why.
ErrorMessagestringSet when the call failed.
AccountSid, ApiVersionstringAccount identifier and a fixed API version string, kept for Twilio-style parsers.
CallerCountry, FromCountrystringCountry code of the calling number, for example IN.
RecordingSid, RecordingDurationstringPresent when the call was recorded.
ClientRefstringThe client reference set on the number in the dashboard, when there is one.
WebhookUrlstringThe markup URL used for this call.

Fields with no value are left out. Other fields may appear; ignore the ones you do not use.

Securing your endpoint

Callbacks are not signed. Put a long random token in the callback URL and check it on every request. Match X-CPaaS-Call-Sidagainst calls you placed. Reply 2xx fast and do slow work later, and if you need to be sure of a call's final state, fetch it with GET /api/calls/{callSid}. More in webhooks & callbacks.