Nexmo Call Control Objects
A Call Control Object (NCCO) is a JSON array of actions that is used to control the flow of a Voice API Call.
Below you can find the One Dev Minute video explaining what NCCOs are and how to use them:
This section describes:
- About Nexmo Call Control Objects
- Creating a custom Call or Conversation for each user
- Connecting to endpoints that don't generate a ring back tone
- Executing an NCCO when a call is answered
About Nexmo Call Control Objects
The Call event model is asynchronous. A static or dynamically created NCCO script provides the business logic for your Call. When a Call is placed to your number, Vonage makes a synchronous request to the webhook endpoint you set as the answer_url
for your number and retrieves the NCCO object that controls the Call.
The general schema of an NCCO is:
[
{
"action": "<value>",
"<option1>": "<value>",
"<option2>": [
{
"type": "<value>",
"<option1>": "<value>"
},
{
"type": "<value>",
"<option1>": "<value>",
"<option2>": "<value>"
}
]
}
]
The elements of an NCCO instruction are:
-
action
- something to be done in the Call. -
option
- how to customize an action. -
type
- describes an option. For example,type=phone
for an endpoint option.
The order of actions in the NCCO controls the flow of the call. This is called the stack. The order of instructions on the stack matters: the actions are executed in order. Unless explicitly halted NCCO are executed on a FIFO basis. When an action is completed, the next action in the stack is executed. Actions that have to complete before the next action can be executed are synchronous. Other actions are asynchronous. That is, they are supposed to continue over the following actions until a condition is met. For example, a record
action terminates when the endOnSilence
option is met. When all the actions in the NCCO are complete, the voice call ends.
Some actions and options are:
[
{
"action": "talk",
"text": "Hello, you are listening to a call made using Voice API."
}
]
[
{
"action": "record",
"eventUrl": ["https://example.com/recordings"],
"endOnSilence": "3"
},
{
"action": "connect",
"eventUrl": ["https://example.com/events"],
"from":"441632960960",
"endpoint": [
{
"type": "phone",
"number": "441632960961"
}
]
}
]
[
{
"action": "stream",
"streamUrl": ["https://acme.com/streams/music.mp3"]
}
]
[
{
"action": "talk",
"text": "Welcome to a Voice API I V R. ",
"voiceName": "Amy",
"bargeIn": false
},
{
"action": "talk",
"text": "Press 1 for maybe and 2 for not sure followed by the hash key",
"voiceName": "Amy",
"bargeIn": true
},
{
"action": "input",
"type": ["dtmf"],
"dtmf: {
"submitOnHash": "true"
},
"eventUrl": ["https://example.com/ivr"]
}
]
For your NCCO to execute correctly, the JSON syntax must be valid. It is better to generate JSON dynamically using a JSON library than to attempt to write it yourself programmatically.
The actions you can use in an NCCO are:
-
record
- all or part of a call -
conversation
- create a standard or hosted conversation -
connect
- connect to a connectable endpoint such as a phone number or Vonage Business Cloud extension -
talk
- send synthesized speech to a conversation -
stream
- send audio files to a conversation -
input
- collect digits from the person you are calling, then process them
Creating a custom call or conversation for each user
When you make an outbound call or accept an inbound call, Vonage makes a request to your webhook endpoint at answer_url
and retrieves your NCCO. This request contains the following parameters:
Name | Description |
---|---|
to |
The endpoint being called. |
from |
The endpoint you are calling from. |
conversation_uuid |
The unique ID for this Conversation. |
uuid |
The unique ID for this Call. |
You can use these parameters to customize the NCCO you return to Vonage. The following code examples show how to provide the NCCO that controls your call or conversation:
<?php
$method = $_SERVER['REQUEST_METHOD'];
switch ($method) {
case 'GET':
//Retrieve with the parameters in this request
$to = $request['to']; //The endpoint being called
$from = $request['from']; //The endpoint you are calling from
$conversation_uuid = $request['conversation_uuid']; //The unique ID for this Conversation
$uuid = $request['uuid']; //The unique ID for this Call
//For more advanced Conversations you use the parameters to personalize the NCCO
//Dynamically create the NCCO to run a conversation from your virtual number
if( $to == "441632960960")
$ncco='[
{
"action": "talk",
"text": "Hello Russell, welcome to a Call made with Voice API"
}
]';
else
$ncco='[
{
"action": "talk",
"text": "Hello Rebekka, welcome to a Call made with Voice API"
}
]';
header('Content-Type: application/json');
echo $ncco;
break;
default:
//Handle your errors
handle_error($request);
break;
}
from flask import Flask, request, jsonify
app = Flask(__name__)
HOST = "localhost"
PORT = 3000
@app.route("/webhooks/answer")
def answer_call():
call_from = request.args['from']
# Dynamically build NCCO based on source phone
if call_from == "447700900000":
ncco = [
{
"action": "talk",
"text": "Hi John, we will be with you shortly."
}
]
elif call_from == "447700900001":
ncco = [
{
"action": "talk",
"text": "Hi Jane, we will be with you shortly."
}
]
else:
ncco = [
{
"action": "talk",
"text": "Hello, sorry, we do not recognize your number."
}
]
return jsonify(ncco)
if __name__ == '__main__':
app.run(host=HOST, port=PORT)
require 'socket'
require 'uri'
require 'json'
#Dynamically create the NCCO to send synthsized speech to a virtual number
# Initialize a TCPServer
def generate_ncco(request_line)
#Parse the parameters and check if the message was delivered
params = URI::decode_www_form(request_line).to_h
#Retrieve with the parameters in this request
to = params['to'] #The endpoint being called
from = params['from'] #The endpoint you are calling from
conversation_uuid = params['conversation_uuid'] #The unique ID for this Conversation
uuid = params['uuid'] #The unique ID for this Call
#For more advanced Conversations you use the parameters to personalize the NCCO
#Dynamically create the NCCO to run a conversation from your virtual number
if to == "441632960960"
ncco=[
{
"action": "talk",
"text": "Hello Russell, welcome to a Call made with Voice API"
}
]
else
ncco=[
{
"action": "talk",
"text": "Hello Rebekka, welcome to a Call made with Voice API"
}
]
end
return ncco.to_json
end
server = TCPServer.new('', 9999)
# Wait for connections
loop do
# Wait until a client connects
socket = server.accept
method, path = socket.gets.split
resp = generate_ncco(path)
# Return the 200 OK
headers = ["HTTP/1.1 200 OK",
"Content-Type: application/json",
"Content-Length: #{resp.length}\r\n\r\n"].join("\r\n")
socket.puts headers
#Return the NCCO
socket.puts resp
# Close the socket, terminating the connection
socket.close
end
Connecting to endpoints that don't generate a ring back tone
Sometimes you will connect to an endpoint that does not have a ring back tone provided by the carrier. If calling a phone endpoint, you will usually hear a ring back tone provided by the carrier, but if one is not provided for that endpoint the caller will experience silence and may be unsure if they are being connected or not. This may result in them hanging up the call. To get around this potential problem, you can use ringbackTone
in your NCCO to provide a ring back tone. For example:
[
{
"action": "talk",
"text": "Now connecting you"
},
{
"action": "connect",
"from": "VONAGE_NUMBER",
"ringbackTone": "https://example.com/tones/call.wav",
"endpoint": [
{
"type": "app",
"user": "alice"
}
]
}
]
Executing an NCCO when a call is answered
In some use cases you might want to execute an NCCO when a call is answered. For example, you might want to inform the callee that they are about to be connected into a conference call. To carry out NCCO operations when a call is answered the onAnswer
parameter can be used. For example:
[
{
"action": "talk",
"text": "Now connecting you"
},
{
"action": "connect",
"from": "VONAGE_NUMBER",
"endpoint": [
{
"type": "phone",
"number": "TO_NUMBER",
"onAnswer": {
"url": "https://example.com/ncco/on-answer.json"
}
}
]
}
]
You can also use onAnswer
in conjunction with ringbackTone
so that the caller can hear a ring back tone between when the callee answers the call, and when the callee is fully connected into the call:
[
{
"action": "talk",
"text": "Now connecting you"
},
{
"action": "connect",
"from": "VONAGE_NUMBER",
"endpoint": [
{
"type": "phone",
"number": "TO_NUMBER",
"onAnswer": {
"url": "https://example.com/ncco/on-answer.json",
"ringbackTone":"https://example.com/tones/connecting-callee.wav"
}
}
]
}
]
In a very straightforward case on-answer.json
might be:
[
{
"action": "talk",
"text": "You will now be connected into the conversation"
}
]