Skip to main content

Hello Devs,

I’m working on a project where I need to receive and answer incoming phone calls via an API and handle them with backend AI for real-time responses. Here’s a quick overview of the flow:

1. The user initiates a phone call.
2. I receive a call notification via webhook — this part is working perfectly.
3. I then need to programmatically answer the call using the /restapi/v1.0/account/~/extension/~/call-control/{session_id}/answer endpoint.

 

 

The issue is with Step 3. Despite successfully receiving the call notification, I'm unable to answer the call through this endpoint. Here’s what I’ve tried so far:

  • Verified that I’m using the correct `session_id` from the webhook payload.
  • Confirmed that my access token has the necessary permissions.
  • Ensured that I’m using the correct API endpoint and adding necessary headers like Authorization.

 

Despite these checks, the API doesn’t seem to acknowledge the answer request, and the call doesn’t get connected. My goal is to answer the call, convert the audio to text (STT), process it with AI, and respond back using text-to-speech (TTS).

First of all, to be able to control a call via API, your app must be authenticated by a user who owns the call. In other words, you cannot control a call of another user (even the super admin user).

To answer a call, you need to know the device id of the phone, which the user is supposed to use to speak with the caller. You can read the user device and check the status of the device to make sure that it’s online.

I give you the sample code in Node JS, feel free to convert it to any other programming language.

var deviceId = ""
async function get_extension_devices() {
try{
let endpoint = '/restapi/v1.0/account/~/extension/~/device'
var resp = await platform.get(endpoint)
var jsonObj = await resp.json()
for (var record of jsonObj.records){
if (record.status == "Online"){
deviceId = record.id
break;
}
}
}catch(e){
console.log(e.message)
console.log(e.request.headers)
}
}

Once you have a device id and when you receive an inbound call notification, check to make sure the call status is “Proceeding” (Not “Ringing” as you wrote). For this, use the telephony session event notification instead of the user presence one (…/presence?detailedTelephonyState=true).

Then call the /answer API to answer the call.

function subscribe_for_telephony_notification(){
var eventFilters = n
'/restapi/v1.0/account/~/extension/~/telephony/sessions',
]
subscription.setEventFilters(eventFilters)
.register()
.then(function(subscriptionResponse) {
console.log("Ready to receive call notification via Websocket.")
})
.catch(function(e) {
console.error(e);
throw e;
});
}

subscription.on(subscription.events.notification, function(msg) {
if (msg.body.partiesb0].direction == "Inbound"){
if (msg.body.partiesb0].status.code == "Proceeding"){
answerCall(msg.body)
}
}
});

// Answer the call
async function answerCall(call){
var endpoint = `/restapi/v1.0/account/~/telephony/sessions/${call.telephonySessionId}`
endpoint += `/parties/${call.partiesc0].id}/answer`
var params = {
deviceId: deviceId
}
try {
var resp = await platform.post(endpoint, params )
var jsonObj = resp.json()
console.log(JSON.stringify(jsonObj))
console.log(resp.status)
}catch(e){
console.log(e.response.headers)
console.log(e.message)
}
}

 

Learn more about the telephony session event notification.


Reply