who wants to be a developer?
TRANSCRIPT
Cisco Confidential© 2015 Cisco and/or its affiliates. All rights reserved. 1
Who wants to be a Developer?
Phil Bellanti
Technical Marketing Engineer
2016 May 18th
+• Ask
• Call
• Conference
• Hangup
• Record
• Reject
• Say
• Transfer
Inbound Capabilities: User Calls or Texts App
• Surveys / Voting
• Voice Search
• Seasonal Spikes
• Audio Conferencing
• Information Lookup
• Basic Auto Attendant
Outbound Capabilities: App Calls or Texts User
• Voice Broadcast
• Conditional Alerts
• Click-to-Call
• Appointment Reminders
• Two Factor Authentication
• Confirmation SMS
PHP
<?php
answer();
say("Hello World");
hangup();
?>
Javascript
answer();
say("Hello World");
hangup();
Ruby
answer
say "Hello World"
hangup
Python
answer()
say("Hello World")
hangup()
Groovy
answer()
say("Hello World")
hangup()
<?php
$options = array('choices' => '1 (1, sales),
2 (2, support)');
$result = ask('Hi. For sales, say Sales or press 1.
For support, say Support or press 2.',
$options);
if ($result->name == 'choice') {
switch ($result->value) {
case 1:
say('Your money is important to us.');
break;
case 2:
say('Your call will be ignored in the order
received.');
break;
}
}
?>
Incoming Calls
answer();
say("Welcome to Tropo!");
hangup();
Incoming Calls
say("Welcome to Tropo!");
Try It!
Creating your
first application
Create an account
• Register at www.Tropo.com
• Create a new application
say("hello world");
Call It!
Playing Audio
say("http://www.phono.com/audio/trop
orocks.mp3")
Playing Audio
say("http://www.phono.com/audio/trop
orocks.mp3
http://www.phono.com/audio/holdmusi
c.mp3")
Try It• Create an application that…
• answers an incoming call
• says “Hello Tropo!”
• then plays an audio file.
• If you have a softphone like Jabber, you
can also call in using the application SIP
address
Solution
say("Hello Tropo!
http://www.phono.com/audio/troporocks.mp3");
Asking Questions
var result = ask("What's your favorite color? Choose from
red, blue or green.", {
choices:"red, blue, green"
});
say("You said " + result.value);
log("They said " + result.value);
Asking Questions
var result=ask("Pick a number from 0 to 9", {
choices:"0,1,2,3,4,5,6,7,8,9"
});
say("You said " + result.value);
log("They said " + result.value);
Grammar Builtins
result=ask("Pick a number from 0 to 9", {
choices:"[1 DIGIT]"
});
say("You said " + result.value);
log("They said " + result.value);
choices:"[4 DIGITS]"
OR
choices:"[4-16 DIGITS]"
var result = ask("Which color cup is the Holy Grail?", {
choices: "red, blue, green",
attempts: 3,
onChoice: function(event) {
say("You chose... wisely");
},
onBadChoice: function(event) {
say("You chose... poorly");
}
});
Two Styles
result=ask("Pick a number from 0 to 9", {
choices:"[1 DIGIT]"
});
say("You said " + result.value);
var result = ask("Which color cup is the Holy Grail?", {
choices: "red, blue, green",
onChoice: function(event) {
say("You chose... wisely");
},
});
ExerciseHow can we add a conditional statement to this
script to repeat back a correct choice?
var result = ask("Which color cup is the Holy Grail?", {
choices: "red, blue, green",
attempts: 3,
onChoice: function(event) {
say("You chose... wisely");
},
onBadChoice: function(event) {
say("You chose... poorly");
}
});
Solution
var result = ask("Which color cup is the Holy Grail?", {
choices: "red, blue, green",
attempts: 3,
onChoice: function(event) {
say("You chose... wisely");
},
onBadChoice: function(event) {
say("You chose... poorly");
}
});
if (result.name == "choice") {
say("You chose " + result.value);
}
Try It
• Ask the caller to pick a 3-6 digit number
and speak it back to them.
Solution
var result=ask("Pick a number 3 to 6 digits long", {
choices:"[3-6 DIGITS]"
});
say("You said " + result.value);
Recording
record("Leave your message at the beep. Press pound
when finished.", {
beep:true,
timeout:10,
silenceTimeout:7,
maxTime:60,
terminator:'#',
recordFormat:"audio/mp3",
recordURI:"ftp://example.com/1.mp3",
recordUser:"tropocloud",
recordPassword:"password"
}
);
var rec = record("Leave a message.");
say(rec.value);
var rec = record("Leave a message.");
say(rec.value);
var rec = record("Leave a message.");
say(rec.value);
startCallRecording("http://example.com/recording.js");
ask("What's your favorite color? Choose from red, blue or
green.", {
choices:"red, blue, green"
});
stopCallRecording();
startCallRecording("http://example.com/recording.js");
transfer("sip:[email protected]");
stopCallRecording();
var callerID = currentCall.callerID;
say("Welcome to speed therapy!");
record("Tell us how you feel in fifteen minutes or less!", {
beep:true,
maxTime:900,
recordURI:"http://example.com/recording.js",
transcriptionOutURI:"mailto:[email protected]",
transcriptionID:callerID
}
);
Try It• Voicemail application
• Ask for a message
• Play a beep
• Allow the caller to end recording with #
• Only allow 10 seconds
• Play the message to them when done.
Solution
var rec = record("Leave a message.", {
beep:true,
silenceTimeout:3,
maxTime:10,
terminator:'#' }
);
say(rec.value);
Outgoing Calls
Outgoing Calls
call("+14155550100");
say("Tag, you’re it!");
Outgoing Calls
call("+14155550100");
call("14155550100");
call("4155550100");
call("+1 415 555-0100");
call('+' + numberToDial);
say("Hey, "+ customerName +": "+ msg);
POST /rest/1/Sessions
{
"token": "abcdef123456",
"customerName": "John Dyer",
"numberToDial": "14075551212",
"msg": "the sky is falling."
}
call('+' + numberToDial);
say("Hey, "+ customerName +": "+ msg);
POST /rest/1/Sessions
{
"token": "abcdef123456",
"customerName": "John Dyer",
"numberToDial": "14075551212",
"msg": "the sky is falling."
}
call('+' + numberToDial);
say("Hey, "+ customerName +": "+ msg);
POST /rest/1/Sessions
{
"token": "abcdef123456",
"customerName": "John Dyer",
"numberToDial": "14075551212",
"msg": "the sky is falling."
}
call('+' + numberToDial);
POST /rest/1/Sessions
{
"whatever": "14075551212"
}
call('+' + numberToDial);
POST /rest/1/Sessions
{
"whatever": "14075551212"
}
call('+' + numberToDial);
POST /rest/1/Sessions
{
"whatever": "14075551212"
}
call('+' + whatever);
POST /rest/1/Sessions
{
"whatever": "14075551212"
}
https://api.tropo.com/1.0/sessions?action=create&tok
en=TOKEN&numberToDial=14074551212
REST Api Shortcut -
URL in browser
Try It
• Place a call to your SIP account and say
something.
• Start it with the Session API
• Pass the SIP address in the session Api
Solution
call(to);
say("Hello, Tropo!");
POST /rest/1/Sessions
{
"token": "abcdef123456",
"to": "sip:[email protected]",
}
Call Failure
call('+14155550100', {
timeout:120,
onAnswer: function() {
say("Tag, you are it!");
log("Obnoxious call complete");
},
onTimeout: function() {
log("Call timed out");
},
onCallFailure: function() {
log("Call could not be completed as dialed");
}
});
Transfers
& Call Control
Controlling a Call
transfer("+14075550100");
transfer([
"+14075550100",
"+16505559876"
]);
transfer(["+14075550100","sip:[email protected]
4.86"], {
playvalue: "http://example.com/holdmusic.mp3",
terminator: "*",
onTimeout: function(event) {
say("nobody answered");
}
});
Try It
• Work with a partner
• Call your Tropo SIP address
• Transfer the call to your partner’s SIP
address.
• Add a ring tone or a terminator
Solution
transfer("sip:[email protected]", {
playvalue: "http://example.com/holdmusic.mp3",
terminator: "*",
});
Rejecting calls
reject();
var callerID = currentCall.callerID;
if (callerID == "4155550100") {
reject();
}
Redirect
redirect("sip:[email protected]");
Hanging up
• Explicitly, through hangup();
• When a script ends
• When execution fails
Try It
• Reject, redirect, or hang up on a call
Conferencing
Conferencing
conference("1138");
conference("2600hz");
conference("Four score and seven", {
terminator: "*",
playTones: true,
onChoice: function(event) {
say("Disconnecting");
}
});
result=ask("What is your conference ID?",
{choices:"[4 DIGITS]"}
);
conference(result.value);
conference("12345", {
joinPrompt: "Someone joined",
leavePrompt: "Someone left",
});
Try It
• Work with a partner
• Ask for a conference ID
• Ask for the caller’s name (hint: record)
• Play their name into the conference
when they join
Solutionvar result=ask("What is your conference ID?",
{choices:"[4 DIGITS]"}
);
var rec = record("Say your name.");
conference(result.value, {
joinPrompt: rec.value + " joined",
leavePrompt: rec.value + " left",
});
Text Messaging
Text Messages
call("+14155550100",
{network:"SMS"}
);
say("Tag, you’re it!");
Text Messages
call("+14155550100",
{network:"SMS"}
);
say("Tag, you’re it!");
call('+' + to, {network:"SMS"});
say(msg);
POST /rest/1/Sessions
{
"token": "abcd12345",
"to": "14075551212",
"msg": "the sky is falling."
}
Incoming SMS
say("Welcome to Tropo!");
Incoming SMS
answer();
say("Welcome to Tropo!");
hangup();
Capture an incoming
text message
currentCall.initialText
Try It
• Create an inbound SMS app
• Send it a text message and have it reply
back with a response tailored to the
inbound text's content
Solution
if(currentCall.initialText == "Yes")
{
say("Awesome, I totally agree.");
}
else if(currentCall.initialText == "No")
{
say("Well that's just too bad");
}
else
{
say("That wasn't an option, sorry");
}
Multichannel
say("Thanks for your call. We'll text you the
information.");
hangup();
call(currentCall.callerID, {
network:"SMS"});
say("Here's what you asked for.");
Multichannel
say("Thanks for your call. We'll text you the
information.");
hangup();
var newcall =
call(currentCall.callerID, {
network:"SMS"});
newcall.value.say("Here's what you asked for.");
Message Shortcut
message("Here's what you asked for.",
{
to: "+16505551212",
network: "SMS"}
);
Message Shortcut
say("Thanks for your call. We'll text you the
information.");
message("Here's what you asked for.",
{
to: currentCall.callerID,
network: "SMS"}
);
say("This goes to the voice call.");
Call Data
Call Properties
• calledID
• calledName
• callerID
• callerName
• channel
• network
• id
• sessionId
• isActive function
Reading Caller ID
if (currentCall.callerID == "4075550100") {
say("Sending you to Adam.");
transfer("+19166002497");
}
Setting Caller ID
call("+19165550101", {
callerID:"+14075550100"
});
transfer("+19165550100", {
callerID: "14075550100"
});
Try It
• Call your SIP address
• Read your caller ID back to yourself
Solution
say("You are calling from " + currentCall.callerID);
Advanced Speech
Concepts
Speech Control
say("1234");
“One thousand two hundred thirty four”
Speech Control
say("1 2 3 4");
“One Two Three Four”
SSML
say("<speak>
<say-as interpret-as='vxml:digits'>
1234
</say-as>
</speak>");
“One Two Three Four”
say-as
• currency
• number
• phone
• date
• time
interpret-as='vxml:digits'
Prosody
say("<speak>One potato, two potato, three potato,
four. <prosody rate='-50%'>One potato, two
potato, three potato, four.</prosody></speak>");
TTS Fallback
say('<speak>
<audio src="http://example.com/welcome.wav">
This text will be spoken if
the audio file can not be
played.
</audio>
</speak>');
Try It
• Speak “1234” as “one thousand two
hundred thirty four” and then as digits
Solution
say("1234");
say("1 2 3 4");
say("<speak>
<say-as interpret-as = 'vxml:digits'>
1234
</say-as>
</speak>");
Grammars
• SimpleGrammar
• hamburger(burger, cheeseburger, hamburger)
• GrXML
• ABNF
• SRGS
SimpleGrammar
var foo = ask("Who?", {
choices: "department(support, engineering,
sales), person(jose, jason, adam)",
});
say("You said " + foo.choice.interpretation + ",
which is a " +
foo.value);
External Grammars
var result = ask("What's your destination?", {
choices:"http://example.com/tropo/destinations.grxml
"
});
<?xml version="1.0"?>
<grammar xmlns="http://www.w3.org/2001/06/grammar" root="main">
<rule id="main" scope="public">
<item repeat="1-16">
<ruleref uri="#digit">
<tag>out.concept = out.concept + rules.digit;</tag>
</ruleref>
</item>
</rule>
<rule id="digit">
<one-of>
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
</one-of>
</rule>
</grammar>
Audio Playback
• 8kHz, 8bit u-law (wav or raw) (*.wav or *.ulaw)
• 8kHz, 8bit a-law (wav or raw) (*.wav or *.alaw)
• 8kHz, 8bit pcm (wav) (*.wav)
• 8khz, 16bit pcm (wav or raw) (*.wav or *.pcm)
• MS-GSM (wav) (*.wav)
• GSM 6.10 (raw) (*.gsm)
• MP3
Method Details
Ask
• Collect input
Text
allowSignals
bargein
attempts
choices
interdigitTimeout
minConfidence
mode
onBadChoice
onChoice
onError
Ask Result
attempt – This will return an integer which will relay
what attempt the user is currently on.
value – This will return the users selection.
name – This will return the event that was accepted:
choice, badChoice, timeout, error
timestamp – This will return the timestamp of the
completed ask 2013-09-09T18:59:06.267Z
Call
destination
machineDetection
allowSignals
network
answerOnMedia
onAnswer
callerID
onBusy
channel
onCallFailure
• Outgoing Calls & Messages
headers
onError
onSignal
onTimeout
recordFormat
recordMethod
recordURI
timeout
voice
Call Result
value – a call object representing the state of the
current call.
timestamp – this will return the timestamp of the of the
connected call 2013-09-09T18:59:06.267Z
Conference
• Joins two or more calls in a conference.
Limited only by server capacity.
conferenceId
allowSignals
interdigitTimeout
joinPrompt
onHangup
onSignal
playTones
terminator
leavePrompt
mute
onChoice
onError
Hangup
• Disconnect a call or end a SIP session
• Automatic at the end of the script
Log
• Insert a line into the application logs
• Note: in PHP, this is _log()
• Only parameter is the string to insert into
the log
log("The user name is " + name);
Message
• Message-sending shortcut
• Equivalent to call, say, hangup sequence
to
callerID
channel
network
timeout
Record• Record user input
• See also startCallRecording &
stopCallRecordingonEvent
allowSignals
onHangup
attempts
onRecord
bargein
onSignal
beep
onTimeout
interdigitTimeout
recordFormat
maxTime
recordMethod
onError
recordPassword
recordUser
silenceTimeout
terminator
timeout
transcriptionID
transcriptionOutFormat
transcriptionOutURI
voice
Reject
• Return a busy signal instead of
answering
• CDR has a duration of 0
Say
• Speak TTS or play audio URL (or both)
• Does not await a response
text
allowSignals
onError
onHangup
onSignal
voice
startCallRecording
• Non-blocking, turns on a recording
• Local leg in one audio channel, remote leg in
another
• Stop with stopCallRecording
url
format
method
recordPassword
recordUser
transcriptionEmailFormat
transcriptionID
transcriptionOutURI
stopCallRecording
• Takes no parameters
• Stops the active call recording and
triggers upload
Transfer
• Simple mechanism to call a new number
and bridge to the current call
destination
allowSignals
answerOnMedia
callerID
headers
interdigitTimeout
onBusy
onCallFailure
onConnect
onError
onSignal
onSuccess
onTimeout
playrepeat
playValue
terminator
timeout
voice
wait
• Pauses specified number of milliseconds
• Differs from built-in sleep function by
being interruptible
• In Groovy use await()
milliseconds
onSignal
allowSignals
Rest APIs
Session
• Start a new session
• Send a signal to an existing session
Conference
• Mute and unmute participants
• Play an audio file to all members of a
conference
Provisioning
• Manage applications, users, and phone
numbers
• Full role-based access control
• Tropo Commander and UI both built on
this
WebAPI
What is it?
• Uses JSON over http to communicate
with Tropo
• Most large-scale customers stick with
Scripting
• Web Scale issues
Thank you.