LaML XML Specification
What is LaML?
Simple LaML document example
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Welcome to SignalWire!</Say>
</Response>
LaML is the language used by SignalWire to determine how the phone numbers in your account react during calls or text messages. When a call or message comes into one of your SignalWire phone numbers, SignalWire makes an HTTP request to the URL endpoint you configured for that number. Your response to that request instructs SignalWire on what to do next.
Responses to the HTTP request are in an XML format we call LaML. LaML allows you to specify instructions using simple LaML commands called verbs. SignalWire starts at the top of your LaML document and executes your LaML commands in order, from top to bottom.
How LaML works
When an message or call is received by one of your SignalWire phone numbers, SignalWire lookup the URL endpoint you configured for that phone number and make an HTTP request to it. The URL endpoint then responds to the request with a LaML document that determines what to do next.
SignalWire will read the instructions in the LaML document, from top to bottom, and execute the commands in order.
You can generate and respond with raw XML yourself, or utilize one of the SignalWire helper libraries to help you generate it easily.
Outbound calls and messages started via the LaML REST API are controlled the same way. When you start an outbound call or message, you also pass a link to a LaML document. SignalWire will make a request to this document to determine how it should proceed with the call or message.
While a single LaML document is executed at a time, many documents can be linked together and generated dynamically to create complex applications to fit any need.
LaML Syntax
<?xml version="1.0" encoding="UTF-8"?>
<!-- All responses must contain the Response element -->
<Response>
<!-- Say and Dial are examples of Verbs -->
<Say>Connecting you...</Say>
<Dial>
<!-- Number is an example of a Dial Noun -->
<Number>+15551234567</Number>
</Dial>
</Response>
LaML is XML-based and consists of the following elements:
- the
<Response>
element -- tag defining the body of the LaML document - verb -- an XML tag denoting the action that you want SignalWire to take
- noun -- the item for the action specified in the associated verb
Response Element
The root element of all LaML documents is a <Response>
tag. All messaging verbs in a document must be nested within a single <Response>
element, and each document can only have a single one.
Empty Response
Empty response example
<?xml version="1.0" encoding="UTF-8"?>
<Response></Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
<?php
use SignalWire\LaML;
$response = new LaML;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
}
}
from signalwire.voice_response import VoiceResponse
response = VoiceResponse()
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new
puts response.to_s
When an incoming SMS, MMS, or call to a SignalWire phone number is received, SignalWire will automatically respond with the proper LaML directions to handle those incoming messages. Even if no actions are required to handle these messages, a <Response>
must be used. To receive incoming messaging without requiring further actions, respond with <Response></Response>
.
Verbs
A verb identifies the action to take.
Verbs are executed sequentially, so one instruction must complete fully before the next one is executed. Some verbs have optional attributes that can override the flow of execution, allowing you to dynamically change what happens based on events within the call.
All verbs are case sensitive, so calling <ThisAction>
is different from calling <thisaction>
.
Voice Verbs
The following verbs cause the specified action to take place during the call:
Verb | Action |
---|---|
<Dial> |
Initiates a call to another phone number. |
<Gather> |
Collects input from the remote number, either as pressed digits or as speech. |
<Play> |
Plays an audio file in the call. |
<Record> |
Records and saves the audio in the call. |
<Say> |
Reads the supplied text into the call. |
<Stream> |
Streams a call to a websocket. |
The following verbs control what happens to the call itself:
Verb | Action |
---|---|
<Enqueue> |
Place the call into a queue. |
<Hangup> |
Disconnect the call. |
<Leave> |
Remove the call from the queue it is currently in. |
<Pause> |
Wait before continuing to execute further instructions. |
<Redirect> |
Stop executing the instructions in this LaML document, and start executing those in another specified document. |
<Reject> |
Decline an incoming call. |
Messaging Verbs
The following verbs are used to manage messages and responses:
Verb | Action |
---|---|
<Message> |
Sends a message to another phone number. |
<Redirect> |
Stop executing the instructions in this LaML document, and start executing those in another specified document. |
Fax Verbs
The following verbs are used to manage faxes:
Verb | Action |
---|---|
<Receive> |
Receives an incoming fax. |
<Reject> |
Rejects an incoming fax. |
Nouns
An example of using a
<Conference>
noun within a<Dial>
verb:
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference>my-example-conference</Conference>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.conference('my-example-conference')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->conference('my-example-conference');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference("my-example-conference");
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Conference
response = VoiceResponse()
dial = Dial()
dial.conference('my-example-conference')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.conference('my-example-conference')
end
end
puts response.to_s
A noun is what the verb uses to complete its action. Placed inside a verb tab, it can be the text that is read in a call, or other XML or LaML elements that represent the target of the action, such as Conference
or Number
.
Each verb has its own set of supported nouns. See the documentation for a specific verb for more details.
Data Formats
Dates and Times
All dates and times in requests to and from SignalWire LaML API are UTC, and presented in RFC 2822 format.
For example, the date and time of 8:01 AM CDT on July 23rd, 2018 is presented as: Mon, 23 Jul 2018 13:01:00 +0000
Phone Numbers
All phone numbers in requests to or from the SignalWire LaML API are in E.164 format, an unambiguous general format for specifying international phone numbers. Numbers in this format start with a plus sign ("+") and the country code.
For example, a US-based phone number like (555) 123-4567
would be formatted like: +15551234567
.
If a number cannot be represented in E.164 format, then SignalWire uses the raw Caller ID string that was received.
Voice LaML
Voice LaML is a set of actions defined in an XML document you can use to tell SignalWire what to do when you receive an incoming call or instructions for outbound calls.
Overview
When a call is made to one of your SignalWire phone numbers, SignalWire looks up the Voice LaML document from the URL you configured, and reads the instructions you provided to determine what to do.
Voice LaML allows you to dynamically control what happens, responding with specific instructions based on the caller, time of day, incoming call, and much more.
Request for LaML
SignalWire makes an HTTP request to your configured endpoint just like a regular web form submission (POST) or page load (GET). The request includes contextual information about the call, allowing you to respond dynamically and fluidly to the call to meet the needs of your application.
You can configure the endpoint URL and HTTP Method in your phone number settings panel on your SignalWire dashboard, or via the REST API.
Request Parameters
SignalWire sends the following parameters, as either URL query parameters or POST parameters, to your endpoint when it receives a call:
Parameter | |
---|---|
CallSid string |
A unique identifier for the call. |
AccountSid string |
The unique ID of the Account this call is associated with. |
From string |
The phone number that sent this call, in E.164 format. |
To string |
The phone number of the call recipient, in E.164 format. |
CallStatus string |
The status of the call. Can be one of the following values: ringing, in-progress, queued, failed, busy, no-answer, or completed. |
ApiVersion string |
The version of the SignalWire API. Incoming calls use the API version placed on the number called. Outgoing calls use the version of the REST API request. |
Direction string |
An identifier to describe the direction of the call: outbound-dial: calls launched through the <Dial> verb outbound-api: calls launched through the REST API inbound: for inbound calls |
ParentCallSid string |
A unique identifier for the call that created this call. |
CallStatus Values
The following are the possible CallStatus parameter values. These are also used in <Dial>
's DialCallStatus:
Value | |
---|---|
ringing |
The call is ringing. |
in-progress |
The call was answered and is in progress. |
queued |
The call is ready and in line to initiate. |
failed |
The call could not be completed. Usually occurs when phone number does not exist. |
busy |
The caller encountered a busy signal. |
no-answer |
The call ended without an answer. |
completed |
The call was answered and ended normally. |
canceled |
The REST API canceled the call while it was ringing or queued. |
Responding to SignalWire
An example of a LaML document that reads a message to the caller before playing an audio file.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Hello, World!</Say>
<Play>https://your-application.com/audio.mp3</Play>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.say('Hello, World!')
response.play('https://your-application.com/audio.mp3')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->say('Hello, World!');
$response->play('https://your-application.com/audio.mp3');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Say("Hello, World!");
response.Play(new Uri("https://your-application.com/audio.mp3"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Say, Play
response = VoiceResponse()
response.say('Hello, World!')
response.play('https://your-application.com/audio.mp3')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.say(message: 'Hello World!')
response.play(url: 'https://your-application.com/audio.mp3')
end
puts response.to_s
When a message comes into one of your SignalWire phone numbers, SignalWire makes an HTTP request to the URL endpoint you configured for that number. Your response to that request instructs SignalWire on what to do next.
Responses to the HTTP request are in LaML. SignalWire starts at the top of your LaML document and executes your LaML commands in order, from top to bottom.
Status Callbacks
SignalWire can send your application callbacks at various lifecycle stages of your call. Status callbacks do not allow you change the application execution directly, so callbacks do not have to respond with LaML, but they allow your application to get updates as a call is happening.
You should respond to any callbacks with a 200 OK or 204 No Content, otherwise you will see failures in your application log on SignalWire.
The StatusCallback request contains the Standard Request Parameters plus the following optional parameters:
Parameter | |
---|---|
CallbackSource string |
The source of the status callback. |
CallDuration integer |
The duration, in seconds, of the finished call. Only present on the completed event. |
Timestamp string |
The timestamp, in RFC 2822 format, of when the event occurred. |
<Dial>
The <Dial>
verb connects an existing call to another phone number. <Dial>
will end this new call if: the called number does not answer, the number does not exist, or SignalWire receives a busy signal.
Verb Attributes
Attribute | |
---|---|
action optional |
The action attribute takes in an absolute URL. SignalWire will make a GET or POST request to this URL after the dialed call ends. If no action is provided, SignalWire will continue to the next verb in the document. SignalWire will end the call if there are no more verbs following the <Dial> verb in the document. See below for request parameters. |
answerOnBridge optional |
If set to true, the inbound call will ring until the number that was dialed answers the call. If the inbound call is a SIP call, SignalWire will send a 180 or 183 to your SIP server as soon as it connects to SignalWire. When the <Dial> call is connected, a 200 will be sent. Default value is false. |
callerId optional |
The inbound caller's phone number, which is displayed to the number that was dialed. The caller ID must be a valid E.164 number. |
hangupOnStar optional |
The initiator of the call can hangup on the dialed number by using the * key. Default value is false. |
method optional |
The method attribute specifies whether the request to action is a GET or a POST . Valid values are GET or POST , default value is POST . |
record optional |
The record attribute allows the ability to record both legs of a call. Recordings are available as mono-channel or dual-channel. See below for a detailed explanation of these channels. Default value is do-not-record . |
recordingStatusCallback optional |
The recordingStatusCallback attribute takes in an absolute or relative URL. SignalWire will make a GET or POST request to this URL when recording is available. Default value is POST . See below for request parameters. |
recordingStatusCallbackEvent optional |
The different recording statuses. Possible values are completed , in-progress , and absent . To specify multiple events, separate with a space. Defaults to completed . |
recordingStatusCallbackMethod optional |
Whether the request to recordingStatusCallback URL is a GET or a POST . Default is POST . |
recordingStorageUrl optional |
The recordingStorageUrl attribute accepts an absolute URL as the destination to send a recording to, if you prefer to host your own recordings and bypass SignalWire storage. |
recordingStorageUrlMethod optional |
Specifies which HTTP verb to use when sending the recording to the recordingStorageUrl . Available values are: POST and PUT. Defaults to POST. |
ringTone optional |
The ability to change the ringback tone played to the caller when dialing a number. Default value is the ringback tone from the carrier. Available values are the following ISO 3166-1 alpha-2 country codes: at, au, bg, br, be, ch, cl, cn, cz, de, dk, ee, es, fi, fr, gr, hu, il, in, it, lt, jp, mx, my, nl, no, nz, ph, pl, pt, ru, se, sg, th, uk, us, us-old, tw, ve, za. |
timeLimit optional |
Maximum duration, in seconds, for a <Dial> . Default value is 4 hours. |
timeout optional |
The time, in seconds, that SignalWire will wait for a call to be answered before setting the status of the call to no-answer . Default is 30 seconds. Minimum value is 5 seconds and maximum value is 600 seconds. |
trim optional |
Whether or not silence in the beginning and end of recordings are removed. Use trim-silence to achieve this behavior. Default value is do-not-trim . |
The action
URL request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
DialCallStatus string |
The status of the dialed call attempt. See below for status values. |
DialCallSid string |
The unique identifier of the new call leg. |
DialCallDuration integer |
The duration, in seconds, of the dialed call. |
RecordingUrl string |
The URL of the recorded audio file. This parameter is only present if record is set on a <Dial> . |
The DialCallStatus
parameter of the action
attribute can be one of the following values:
Value | |
---|---|
completed |
The number that was dialed answered the call and was successfully connected to the caller. |
answered |
When calling to a conference, the number that was dialed answered the call and was successfully connected to the caller. |
busy |
SignalWire received a busy signal when connecting to the dialed number. |
no-answer |
The number that was dialed did not answer the call in time. |
failed |
SignalWire was unable to connect to the dialed number. This usually occurs when the dialed number does not exist. |
canceled |
The call was canceled through a REST API before it was answered. |
record
Channels
The record
attribute allows for recordings in mono-channel or dual-channel:
- mono-channel: both legs of a call are combined into one channel in one recording file
- record-from-answer: starts the recording when the call is answered
- record-from-ringing: starts the recording when ringing begins
- dual-channel: both legs of a call use separate channels in one recording file
- record-from-answer-dual: starts the recording when the call is answered
- record-from-ringing-dual: starts the recording when ringing begins
The recordingStatusCallback
request contains the following parameters:
Parameter | |
---|---|
AccountSid string |
The unique ID of the Account this call is associated with. |
CallSid string |
A unique identifier for the call. Always refers to the initial caller. |
RecordingSid string |
The unique identifier for the recording. |
RecordingUrl string |
The URL for the audio recording. |
RecordingStatus string |
The status of the recording. Possible values are: in-progress, completed, failed. |
RecordingDuration integer |
The duration, in seconds, of the recording. |
RecordingChannels integer |
The number of channels in the recording. Can be 1 or 2. |
RecordingSource string |
The type of call that initiated the recording. |
Nouns
The noun of a LaML verb is nested within the verb upon which the verb acts. <Dial>
has the following nouns:
Noun | |
---|---|
<Conference> |
A conference call between two or more callers. |
<Number> |
A phone number with additional attributes. |
<Queue> |
A line for callers to wait in. The current call will be connected to the call at the front of the queue. |
<Conference>
<Dial>
verb's <Conference>
noun permits the connection to a named conference room.
Noun Attributes
Attribute | |
---|---|
muted optional |
Whether or not a caller can speak in a conference. Default is false. |
beep optional |
Whether or not a sound is played when callers leave or enter a conference. Default is true. See below for all possible values. |
startConferenceOnEnter optional |
The conference begins once a specific caller enters into the conference room, unless it has already started. If a participant joins and startConferenceOnEnter is false, that participant will hear background music and stay muted until a participant with startConferenceOnEnter set to true joins the call. Default is true. |
endConferenceOnExit optional |
If a participant with endConferenceOnExit set to true leaves a conference, the conference terminates and all participants drop out of the call. Default is false. |
waitUrl optional |
URL for the music to play in the background while participants are waiting to enter a conference room. Only supports <Play> , <Pause> , and <Redirect> . If no waitUrl is provided, SignalWire will use its hold music. |
waitMethod optional |
Specifies whether the request to waitUrl is a GET or a POST . The default value is POST . |
maxParticipants optional |
The maximum number of participants allowed in a named conference room. |
record optional |
Can be used to record an entire <Conference> . record-from-start will begin recording the conference call once the first two participants join in on the call. Wait music is not recorded. Default is do-not-record . |
trim optional |
Whether or not silence in the beginning and end of recordings are removed. Default value trim-silence follows this behavior. |
statusCallbackEvent optional |
Specifies conference state changes. The first participant to join the named conference is able to manipulate and set events. All other changes made by other participants will be ignored. See below for all possible events. |
statusCallback optional |
The URL to make requests to for each statusCallbackEvent event. The URL is set by the first participant to enter a conference. All other information provided by other participants will be ignored. See below for request parameters. |
statusCallbackMethod optional |
The type of HTTP request to use when requesting a statusCallback . Default is POST . |
recordingStatusCallback optional |
The recordingStatusCallback attribute takes in an absolute URL. SignalWire will make a GET or POST request to this URL when recording is accessible. See below for request parameters. |
recordingStatusCallbackMethod optional |
The type of HTTP request to use when requesting a recordingStatusCallback . Default is POST . |
recordingStatusCallbackEvent optional |
Specifies recording status changes. To specify multiple values, separate them by a space. Default is completed and failed . See below for details. |
eventCallbackUrl optional |
The 'eventCallbackUrl' attribute takes a URL as an argument and makes a POST request to it when a conference ends. |
The beep
attribute has the following values:
Value | |
---|---|
true |
Plays a beep when a caller leaves or enters a conference. The default value for beep . |
false |
Disables the beep when callers leave and enter conferences. |
onEnter |
Only plays a beep when a caller enters a conference. |
onExit |
Only plays a beep when a caller leaves a conference. |
The statusCallbackEvent
attribute has the following events:
Event | |
---|---|
start |
The conference has started as long as there are at least two people in the conference room and one of the participant's startConferenceOnEnter is set to true. |
end |
The conference ends when the last participant in the call or a participant with endConferenceOnExit set to true leaves the call. |
join |
When a participant joins a conference. |
leave |
When a participant leaves a conference. |
mute |
When a participant has been muted or un-muted. |
hold |
When a participant has been put on hold or put out of hold. |
speaker |
When a participant has begun or stopped speaking. |
The statusCallback
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
ConferenceSid string |
A unique identifier for the named Conference. |
FriendlyName string |
Name of the conference. |
AccountSid string |
A unique identifier for the Account this call is associated with. |
Timestamp string |
The timestamp, in RFC 2822 format, of when an event occurred. |
StatusCallbackEvent string |
Conference state changes. Possible events are: conference-end , conference-start , participant-leave , participant-join , participant-mute , participant-unmute , participant-hold , participant-unhold , participant-speech-start , participant-speech-stop . |
CallSid string |
A unique identifier for the call. |
Muted string |
Whether a participant is muted or not. |
Hold string |
Whether a participant is on hold or not. |
EndConferenceOnExit string |
When a participant has this set on true and they leave a call, conference ends. |
StartConferenceOnEnter string |
When a participant has this set on true and they join a call, conference begins. |
EventName string |
The name of the event. |
RecordingUrl string |
The URL of the recorded audio file. |
Duration integer |
The time, in seconds, of the conference call. |
RecordingFileSize string |
The size of the recorded audio file. |
The recordingStatusCallback
request contains the following parameters:
Parameter | |
---|---|
AccountSid string |
A unique identifier for the Account this recording is associated with. |
ConferenceSid string |
A unique identifier for the Conference this recording is associated with. |
RecordingSid string |
The unique identifier for the recording. |
RecordingUrl string |
The URL for the audio recording. |
RecordingStatus string |
The status of the recording. Possible values are: in-progress , complete , failed . |
RecordingDuration integer |
The duration, in seconds, of the recording. |
RecordingChannels integer |
The number of channels in the recording. Only 1 channel is supported for conference recordings. |
RecordingStartTime integer |
The timestamp for when the recording started. |
RecordingSource string |
The type of call that initiated the recording. |
The recordingStatusCallbackEvent
attribute has the following status values:
Value | |
---|---|
in-progress |
The recording has begun. |
completed |
The recording has completed and is accessible. |
failed |
The recording is not accessible because of a failure. |
<Conference> Examples
A Simple Conference Call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference>Room 1234</Conference>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.conference('Room 1234')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->conference('Room 1234');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference("Room 1234");
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Conference
response = VoiceResponse()
dial = Dial()
dial.conference('Room 1234')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.conference('Room 1234')
end
end
puts response.to_s
The first participant would join the conference "Room 1234" and listen to wait music in the background until a second participant joins the conference. Once participants have joined the conference, the wait music comes to an end, a beep is played, and the conference call begins.
A Moderated Conference Call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference startConferenceOnEnter="false">
moderated-conference-room
</Conference>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.conference('moderated-conference-room', { startConferenceOnEnter: false })
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->conference('moderated-conference-room', array( 'startConferenceOnEnter' => false ));
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference("moderated-conference-room",
startConferenceOnEnter: false);
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Conference
response = VoiceResponse()
dial = Dial()
dial.conference('moderated-conference-room', start_conference_on_enter=False)
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.conference('moderated-conference-room', start_conference_on_enter: false)
end
end
puts response.to_s
You can set the startConferenceOnEnter
to false so that a group of participants can join in the conference room but the conference cannot begin until the moderator has entered the call. As the participants wait for the conference to begin, hold music will be playing in the background.
Start A Moderated Conference Call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference startConferenceOnEnter="true" endConferenceOnExit="true">
moderated-conference-room
</Conference>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.conference('moderated-conference-room', { startConferenceOnEnter: true, endConferenceOnExit: true })
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->conference('moderated-conference-room', array(
'startConferenceOnEnter' => true,
'endConferenceOnExit' => true )
);
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference("moderated-conference-room",
startConferenceOnEnter: true, endConferenceOnExit: true);
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Conference
response = VoiceResponse()
dial = Dial()
dial.conference('moderated-conference-room', start_conference_on_enter=True, end_conference_on_exit=True)
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.conference('moderated-conference-room', start_conference_on_enter: true, end_conference_on_exit: false)
end
end
puts response.to_s
Now, since the moderator has joined in on the conference call, startConferenceOnEnter
is set to true which means the conference can begin. All the participants that were waiting on hold will now be connected to the conference room; the hold music will come to an end and a beep notification will play indicating conference entrance. Once the moderator leaves the call, the conference will come to an end and all participants will be disconnected from the call.
Joining a Conference Call Muted
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference muted="true">ConferenceRoom</Conference>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.conference({ muted: true }, 'ConferenceRoom')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->conference('ConferenceRoom', array( 'muted' => true ));
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference("ConferenceRoom", muted: true);
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Conference
response = VoiceResponse()
dial = Dial()
dial.conference('ConferenceRoom', muted=True)
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.conference('ConferenceRoom', muted: true)
end
end
puts response.to_s
Participants who enter a conference call muted can hear the other participants in the call who are un-muted. However, the un-muted participants cannot hear the muted callers. Muting and un-muting can be enable and disabled in real-time via a REST API.
Recording a Conference Call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Conference record="record-from-start"
recordingStatusCallback="https://www.example.com/recording_update">
ConferenceCall
</Conference>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.conference('ConferenceCall', { record: 'record-from-start', recordingStatusCallback: 'https://www.example.com/recording_update' })
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->conference('ConferenceCall', array(
'record' => 'record-from-start',
'recordingStatusCallback' => 'https://www.example.com/recording_update' )
);
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Conference("ConferenceCall", record: "record-from-start",
recordingStatusCallback: new Uri("https://www.example.com/recording_update"));
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Conference
response = VoiceResponse()
dial = Dial()
dial.conference('ConferenceCall', record='record-from-start', recording_status_callback='https://www.example.com/recording_update')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.conference('ConferenceCall', record: 'record-from-start', recording_status_callback: 'https://www.example.com/recording_update')
end
end
puts response.to_s
The recording of the conference call will begin when at least two participants join the conference room. A recordingStatusCallback
will be sent when the recording is accessible.
Notes On Usage
- You can freely name the conference room to fit your preference. However, only callers within a project can join in on a named conference room. Callers from separate projects will not be able to connect to that same conference room.
- You can customize the background music as callers are waiting to join a conference call
- Conferences will not begin unless there are 2 or more parties present.
<Number>
<Dial>
verb's <Number>
noun specifies what phone number to dial. You can use up to 10 <Number>
s within a <Dial>
to simultaneously call several people. The first person to answer the call will be connected to the caller and the rest of the called numbers will be hung up.
Noun Attributes
Attribute | |
---|---|
sendDigits optional |
Play DTMF tones when a call is answered. Useful when dialing numbers with extensions. SignalWire will initially dial the main phone number, then send the DTMF tones for the extension when the automated system answers. |
url optional |
A specified URL for a document that runs on the callee's end after the dialed number answers but before the call is connected. This allows the caller to provide information to the dialed number, giving them the opportunity to decline the call, before they answer the call. |
method optional |
The method attribute specifies whether the request to action is a GET or a POST . Valid values are GET or POST , default value is POST . |
statusCallbackEvent optional |
The current status of the call. The call moves from initiated to ringing when the phone starts ringing. It moves from ringing to answered when the phone call is answered. Finally, it moves from answered to completed when the call is terminated. The status will be set to completed through the following reasons: busy, canceled, completed, failed, or no-answer. To specify multiple events, separate each one with a space. See below for the different call statuses. |
statusCallback optional |
The URL to make requests to for each statusCallbackEvent event. See below for request parameters. |
statusCallbackMethod optional |
The type of HTTP request to use when requesting a statusCallback . Default is POST . |
The statusCallbackEvent
attribute has the following call status values:
Value | |
---|---|
initiated |
Dialing of a call has begun. |
ringing |
The call has begun ringing. |
answered |
The call has been answered. |
completed |
The call has been terminated. The status will be set to completed through the following reasons: busy, canceled, completed, failed, or no-answer. |
The statusCallback
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
CallDuration integer |
A duration, in seconds, of the finished call. |
RecordingUrl string |
The URL for the audio recording of the call. Only present when CallStatus is completed. |
RecordingSid string |
The unique identifier for the recording of the call. Only present when CallStatus is completed. |
RecordingDuration integer |
The duration, in seconds, of the recorded audio of the call. Only present when CallStatus is completed. |
Timestamp string |
The timestamp, in RFC 2822 format, of when an event occurred. |
CallbackSource string |
The source of the call connection. |
<Number> Examples
Dialing an Extension
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Number sendDigits="www5645">
123-456-7890
</Number>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.number({ sendDigits: 'www5645' }, '123-456-7890')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->number('123-456-7890', array( 'sendDigits' => 'www5645' ));
echo $response;
?>
using System;
using Twilio.TwiML;
using Twilio.TwiML.Voice;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Number("123-456-7890", sendDigits: "www5645");
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Number
response = VoiceResponse()
dial = Dial()
dial.number('123-456-7890', send_digits='www5645')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.number('123-456-7890', send_digits: 'www5645')
end
end
puts response.to_s
After entering the phone number, we want to wait a little before entering in the extension. In order to do this, a w
can be placed in front of the extension number. Each w
will wait 0.5 seconds before dialing the extension. In this example, SignalWire will wait 1.5 seconds before dialing the extension 5645.
Concurrent Phone Calls
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Number>123-456-7890</Number>
<Number>987-654-3210</Number>
<Number>102-938-4750</Number>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.number('123-456-7890')
dial.number('987-654-3210')
dial.number('102-938-4750')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->number('123-456-7890');
$dial->number('987-654-3210');
$dial->number('102-938-4750');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Number("123-456-7890");
dial.Number("987-654-3210");
dial.Number("102-938-4750");
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Number
response = VoiceResponse()
dial = Dial()
dial.number('123-456-7890')
dial.number('987-654-3210')
dial.number('102-938-4750')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.number('123-456-7890')
dial.number('987-654-3210')
dial.number('102-938-4750')
end
end
puts response.to_s
You can simultaneously call up to 10 <Number>
s. The first caller to pick up the phone will be connected to the caller and the rest of the called numbers will be hung up.
Notes on Usage
- You can have up to 10
<Number>
s within a<Dial>
. - If you dial an office number or a phone on airplane mode, the call will be picked up within the first ring and all other calls will be hung up.
<Sip>
Dialing to a SIP destination.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Sip>sip:alice@example.com</Sip>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.sip('sip:alice@example.com')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->sip('sip:alice@example.com');
echo $response;
?>
using System;
using Twilio.TwiML;
using Twilio.TwiML.Voice;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Sip(new Uri("sip:alice@example.com"));
response.Append(dial);
Console.WriteLine(response.ToString());
}
}
from signalwire.voice_response import VoiceResponse, Dial, Sip
response = VoiceResponse()
dial = Dial()
dial.sip('sip:alice@example.com')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.sip('sip:alice@example.com')
end
end
puts response.to_s
<Dial>
verb's <Sip>
noun permits the set up of VoIP sessions using SIP (Session Initiation Protocol). You can send a call to any SIP endpoint.
When dialing an SIP endpoint, the transport defaults to TLS. If the SIP destination does not support TLS, you can set the transport to UDP or TCP by setting the transport manually. For example: sip:alice@example.com;transport=udp
.
The <Sip>
noun supports all of the <Dial>
verb's attributes with one exception: callerId
is supported but not limited to a valid E.164 number. When using the <Sip>
noun, the callerId
attribute can be any alphanumeric string and include the following characters: +-_.,
but no whitespace.
Noun Attributes
Attribute | |
---|---|
url optional |
A specified URL for a document that runs on the callee's end after the dialed number answers but before the call is connected. This allows the caller to provide information to the dialed number, giving them the opportunity to decline the call, before they answer the call. See below for request parameters. |
method optional |
The method attribute specifies whether the request to action is a GET or a POST . Valid values are GET or POST , default value is POST . |
statusCallbackEvent optional |
The current status of the call. The call moves from initiated to ringing when the phone starts ringing. It moves from ringing to answered when the phone call is answered. Finally, it moves from answered to completed when the call is terminated. The status will be set to completed through the following reasons: busy, canceled, completed, failed, or no-answer. To specify multiple events, separate each one with a space. See below for the different call statuses. |
statusCallback optional |
The URL to make requests to for each statusCallbackEvent event. See below for request parameters. |
statusCallbackMethod optional |
The type of HTTP request to use when requesting a statusCallback . Default is POST . |
username optional |
Username for SIP authentication |
password optional |
Password for SIP authentication |
In addition to the standard request parameters, the following are parameters passed back to your application when SignalWire makes a request to the <Sip>
noun's url
attribute.
Parameter | |
---|---|
SipCallId string |
The SIP call ID header of the request made to the remote SIP infrastructure. |
SipHeader string |
The name or value of any X-headers returned in the 200 response to the SIP INVITE request. |
After a Dial attempt is made, SignalWire can make a request to the <Dial>
verb's action
attribute. In addition to the standard request parameters, the following are parameters passed back to your application when SignalWire makes the request.
Parameter | |
---|---|
DialSipCallId string |
The SIP call ID header of the request made to the remote SIP infrastructure. |
DialSipResponseCode string |
The SIP response code to the INVITE attempt. |
DialSipHeader_ string |
The name or value of any X-headers returned in the 200 response to the SIP INVITE request. |
The statusCallbackEvent
attribute has the following call status values:
Value | |
---|---|
initiated |
Dialing of a call has begun. |
ringing |
The call has begun ringing. |
answered |
The call has been answered. |
completed |
The call has been terminated. The status will be set to completed through the following reasons: busy, canceled, completed, failed, or no-answer. |
The statusCallback
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
CallbackSource string |
The source of the status callback. |
CallDuration integer |
The duration, in seconds, of the finished call. Only present on the completed event. |
Timestamp string |
The timestamp, in RFC 2822 format, of when the event occurred. |
<Sip> Examples
Dialing to a SIP Endpoint
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Sip>sip:alice@example.com</Sip>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.sip('sip:alice@example.com')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->sip('sip:alice@example.com');
echo $response;
?>
using System;
using Twilio.TwiML;
using Twilio.TwiML.Voice;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Sip(new Uri("sip:alice@example.com"));
response.Append(dial);
Console.WriteLine(response.ToString());
}
}
from signalwire.voice_response import VoiceResponse, Dial, Sip
response = VoiceResponse()
dial = Dial()
dial.sip('sip:alice@example.com')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.sip('sip:alice@example.com')
end
end
puts response.to_s
In this example, in order to connect to 'alice@example.com' we have to nest a <Sip>
within a <Dial>
.
Dialing to a SIP Endpoint With Authentication
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Sip username="admin" password="1234">sip:bob@example.com</Sip>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.sip({ username: 'admin', password: '1234' }, 'sip:bob@example.com')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->sip('sip:bob@example.com', array( 'username' => 'admin', 'password' => '1234' ));
echo $response;
?>
using System;
using Twilio.TwiML;
using Twilio.TwiML.Voice;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Sip(new Uri("sip:bob@example.com"), username: "admin",
password: "1234");
response.Append(dial);
Console.WriteLine(response.ToString());
}
}
from signalwire.voice_response import VoiceResponse, Dial, Sip
response = VoiceResponse()
dial = Dial()
dial.sip('sip:bob@example.com', username='admin', password='1234')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.sip('sip:bob@example.com', username:'admin', password:'1234')
end
end
puts response.to_s
Now, in order to connect to 'bob@example.com', you have to have the proper authentication credentials.
Passing Custom Headers
Pass custom headers to the SIP endpoint.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Sip>sip:charlie@example.com?customheader=foo&othercustomheader=bar</Sip>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.sip('sip:charlie@example.com?customheader=foo&othercustomheader=bar')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->sip('sip:charlie@example.com?customheader=foo&othercustomheader=bar');
echo $response;
?>
using System;
using Twilio.TwiML;
using Twilio.TwiML.Voice;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial
.Sip(new Uri("sip:charlie@example.com?customheader=foo&othercustomheader=bar"));
response.Append(dial);
Console.WriteLine(response.ToString());
}
}
from signalwire.voice_response import VoiceResponse, Dial, Sip
response = VoiceResponse()
dial = Dial()
dial.sip('sip:charlie@example.com?customheader=foo&othercustomheader=bar')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.sip('sip:charlie@example.com?customheader=foo&othercustomheader=bar')
end
end
puts response.to_s
Dialing a SIP Endpoint with Dial attributes
The Sip Noun supports of <Dial>
attributes and can be used together.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial
record="record-from-answer"
callerId="alice"
method="GET"
action="https://www.example.com/after_dial">
<Sip
url="https://www.example.com/whisper_audio"
statusCallbackEvent='ringing answered'
statusCallback='https://www.example.com/dial_events'>
sip:dan@example.com?customheader=foo
</Sip>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial({ record: 'record-from-answer', callerId: 'alice', method: 'GET', action: 'https://www.example.com/after_dial' })
dial.sip({ url: 'https://www.example.com/whisper_audio', statusCallbackEvent: 'ringing answered', statusCallback: 'https://www.example.com/dial_events' }, 'sip:dan@example.com?customheader=foo')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial( array( 'record' => 'record-from-answer', 'callerId' => 'alice', 'method' => 'GET', 'action' => 'https://www.example.com/after_dial' ));
$dial->sip('sip:dan@example.com?customheader=foo', array( 'url' => 'https://www.example.com/whisper_audio', 'statusCallbackEvent' => 'ringing answered', 'statusCallback' => 'https://www.example.com/dial_events' ));
echo $response;
?>
using System;
using Twilio.TwiML;
using Twilio.TwiML.Voice;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial(record: Dial.RecordEnum.RecordFromAnswer,
callerId: "alice", method: Twilio
.Http.HttpMethod.Get, action: new Uri("https://www.example.com/after_dial"));
dial.Sip(new Uri("sip:dan@example.com?customheader=foo"),
statusCallbackEvent: new []{Sip.EventEnum.Ringing, Sip.EventEnum.Answered}.ToList(),
statusCallback: new Uri("https://www.example.com/dial_events"),
url: new Uri("https://www.example.com/whisper_audio"));
response.Append(dial);
Console.WriteLine(response.ToString());
}
}
from signalwire.voice_response import VoiceResponse, Dial, Sip
response = VoiceResponse()
dial = Dial(record='record-from-answer', caller_id='alice', method='GET', action='https://www.example.com/after_dial')
dial.sip('sip:dan@example.com?customheader=foo', url='https://www.example.com/whisper_audio', status_callback_event='ringing answered', status_callback='https://www.example.com/dial_events')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial(record:'record-from-answer', caller_id:'alice', method:'GET', action:'https://www.example.com/after_dial') do |dial|
dial.sip('sip:dan@example.com?customheader=foo', url:'https://www.example.com/whisper_audio', status_callback_event:'ringing answered', status_callback:'https://www.example.com/dial_events')
end
end
puts response.to_s
Notes on Usage
- SIP INVITE message includes CallSid, AccountSid, and the API version; can also pass custom SIP headers in the INVITE message.
- You can have up to 10
<Sip>
s within a<Dial>
. - You cannot add other nouns in a
<Dial>
that contains a<Sip>
.
<Queue>
<Dial>
verb's <Queue>
noun specifies what queue to dial.
Noun Attributes
Attribute | |
---|---|
url optional |
A specified URL for a document that runs on the caller's end before the call is connected. This allows the caller to inform the dialed number that the call will be connected to an agent or that the call may be monitored or recorded. See below for request parameters. |
method optional |
The method attribute specifies whether the request to action is a GET or a POST . Valid values are GET or POST , default value is POST . |
The url
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
QueueSid string |
The unique identifier for the Queue. |
CallSid string |
The unique identifier for the dequeued call. |
QueueTime string |
The time, in seconds, spent waiting in a queue. |
DequeingCallSid string |
The unique identifier for the call dequeueing the caller. |
<Queue> Examples
Dialing a Queue
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Queue url="https://example.com/about_to_connect.xml">support</Queue>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial()
dial.queue({ url: 'https://example.com/about_to_connect.xml' }, 'support')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial();
$dial->queue('support', array( 'url' => 'https://example.com/about_to_connect.xml' ));
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial();
dial.Queue("support", url: new Uri("https://example.com/about_to_connect.xml"));
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Queue
response = VoiceResponse()
dial = Dial()
dial.queue('support', url='https://example.com/about_to_connect.xml')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial do |dial|
dial.queue('support', url: 'https://example.com/about_to_connect.xml')
end
end
puts response.to_s
This is an example of a caller in the 'support' queue waiting to be dequeued.
Bridging Out of a Queue
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>You will now be connected to an agent.</Say>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.say('You will now be connected to an agent.')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->say('You will now be connected to an agent.');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Say("You will now be connected to an agent.");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Say
response = VoiceResponse()
response.say('You will now be connected to an agent.')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.say(message: 'You will now be connected to an agent.')
end
puts response.to_s
Once a caller is first in line in the queue and ready to be bridged, they will be informed of the connection to an agent.
Examples
A Simple Dial
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>123-456-7890</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.dial('123-456-7890')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->dial('123-456-7890');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Dial("123-456-7890");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial
response = VoiceResponse()
response.dial('123-456-7890')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial('123-456-7890')
end
puts response.to_s
If the dialed number answers the call, the two parties can talk to each other until one of them hangs up the phone.
Dial a Number from a SignalWire Client
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial callerId="+18007778899">
<Number>+18004445566</Number>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial({ callerId: '+18007778899' })
dial.number('+18004445566')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial(array( 'callerId' => '+18007778899' ));
$dial->number('+18004445566');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial(callerId: "+18007778899");
dial.Number("+18004445566");
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Number
response = VoiceResponse()
dial = Dial(caller_id='+18007778899')
dial.number('+18004445566')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial(caller_id: '+18007778899') do |dial|
dial.number('+18004445566')
end
end
puts response.to_s
In order to dial from a SignalWire client, you need to make sure you are inputting a valid phone number. If the number in the callerID
is not valid, the call will fail.
Mono-Channel Recording
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial record="record-from-ringing"
recordingStatusCallback="https://example.com/recording_status">
<Number>+10123456789</Number>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial({ record: 'record-from-ringing', recordingStatusCallback: 'https://example.com/recording_status' })
dial.number('+10123456789')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial(array(
'record' => 'record-from-ringing',
'recordingStatusCallback' => 'https://example.com/recording_status' )
);
$dial->number('+10123456789');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial(record: "record-from-ringing",
recordingStatusCallback: new Uri("https://example.com/recording_status"));
dial.Number("+10123456789");
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Number
response = VoiceResponse()
dial = Dial(record='record-from-ringing', recording_status_callback='https://example.com/recording_status')
dial.number('+10123456789')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial(record: 'record-from-ringing', recording_status_callback: 'https://example.com/recording_status') do |dial|
dial.number('+10123456789')
end
end
puts response.to_s
With mono-channel recording, each participant in the call will be recorded on the same channel. The recording will then be stored in a single recording file. Since we have set record
to record-from-ringing, the recording will begin when the phone starts to ring.
Dual-Channel Recording for a Conference Call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial record="record-from-ringing-dual"
recordingStatusCallback="https://example.com/recording_status">
<Conference>teamcall</Conference>
</Dial>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
dial = response.dial({ record: 'record-from-ringing-dual', recordingStatusCallback: 'https://example.com/recording_status' })
dial.conference('teamcall')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$dial = $response->dial(array(
'record' => 'record-from-ringing-dual',
'recordingStatusCallback' => 'https://example.com/recording_status' )
);
$dial->conference('teamcall');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var dial = new Dial(record: "record-from-ringing-dual",
recordingStatusCallback: new Uri("https://example.com/recording_status"));
dial.Conference("teamcall");
response.Append(dial);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Conference
response = VoiceResponse()
dial = Dial(record='record-from-ringing-dual', recording_status_callback='https://example.com/recording_status')
dial.conference('teamcall')
response.append(dial)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial(record: 'record-from-ringing-dual', recording_status_callback: 'https://example.com/recording_status') do |dial|
dial.conference('teamcall')
end
end
puts response.to_s
This example connects the caller to the conference call, teamcall. With dual-channel recording, each participant in the call will be recorded in a separate channel. The recording will then be stored in a single recording file. Since we have set record
to record-from-ringing-dual, the recording will begin when the phone starts to ring.
<Enqueue>
The <Enqueue>
verb places a call in a specified call queue. If the specified queue does not exist, a new queue will be created and the call will be placed into that new queue. Calls can be dequeued through the <Dial>
verb or removed from the queue through the <Leave>
verb.
Verb Attributes
Attribute | |
---|---|
action optional |
The action attribute takes a absolute URL. When a call leaves the queue, a request to this URL is made. If a call is dequeued through the <Leave> verb, the URL is immediately requested. If the call has been bridged to another party via the <Dial> verb, then the HTTP request is made only after both parties have disconnected. If action is not provided, SignalWire will continue reading the next verb in the document. See below for specified request parameters. |
method optional |
Specifies whether the redirect is a GET or a POST . Default value is POST . |
waitUrl optional |
URL of the document to execute while the caller is in the queue. Default points to a playlist with classical music. waitUrl supports the following verbs: <Play> , <Say> , <Pause> , <Hangup> , <Redirect> , <Leave> , and <Gather> . See below for specified request parameters. |
waitUrlMethod optional |
Specifies whether the request to waitUrl is a GET or a POST . The default value is POST . |
The action
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
QueueResult string |
The result of the queued call. See below for all possible values. |
QueueSid string |
The unique ID of the queue. Only available if a call is successfully placed into a queue. |
QueueTime string |
The time a call was waiting in a queue. Only available if a call is successfully placed into a queue. |
The parameter QueueResult
has the following values:
Value | |
---|---|
bridged |
The call was bridged and removed from the queue. |
bridging-in-progress |
SignalWire is instructed to bridge the call. |
error |
An error occurred either through the <Enqueue> verb or through the document retrieved from the waitUrl . |
hangup |
The caller hung up while still in the queue. |
leave |
The caller left the queue through the <Leave> verb. |
redirected |
The call was redirected out of the queue, through a REST API request, while the caller was in the queue. |
redirected-from-bridged |
The queued and bridged session was transferred out. |
queue-full |
The queue was full, so the placement into the queue was not accepted. |
system-error |
SignalWire had a malfunction while placing a call into a queue. |
The waitUrl
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
QueuePosition integer |
The current position in the queue. |
QueueSid string |
The unique ID of the queue a caller is in. |
QueueTime integer |
The time a call was waiting in a queue. |
AvgQueueTime integer |
The average time, in seconds, that callers have been waiting in a queue. |
CurrentQueueSize integer |
The current number of callers in a queue. |
Nouns
The noun of a LaML verb is nested within the verb upon which the verb acts. <Enqueue>
has the following nouns:
Noun | |
---|---|
plain text |
The name of a specific queue. |
Nesting
No other verbs can be nested within <Enqueue>
and you cannot nest
<Enqueue>
within any other verbs.
Examples
A Simple Enqueue
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Enqueue waitUrl="https://example.com/hold-music.xml">support</Enqueue>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.enqueue({ waitUrl: 'https://example.com/hold-music.xml' }, 'support')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->enqueue('support', array( 'waitUrl' => 'https://example.com/hold-music.xml' ));
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Enqueue("support", waitUrl: new Uri("https://example.com/hold-music.xml"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Enqueue
response = VoiceResponse()
response.enqueue('support', wait_url='https://example.com/hold-music.xml')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.enqueue(name: 'support', wait_url: 'https://example.com/hold-music.xml')
end
puts response.to_s
While a caller is in the queue, SignalWire retrieves the LaML document 'hold-music.xml' and executes it.
Playing Wait Music
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>http://your-application.com/classical.mp3</Play>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.play('http://your-application.com/classical.mp3')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->play('http://your-application.com/classical.mp3');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Play(new Uri("http://your-application.com/classical.mp3"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Play
response = VoiceResponse()
response.play('http://your-application.com/classical.mp3')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.play(url: 'http://your-application.com/classical.mp3')
end
puts response.to_s
While callers in a queue are waiting, classical music is played.
<Gather>
The <Gather>
verb transcribes speech or collects digits during a call.
Verb Attributes
Attribute | |
---|---|
action optional |
The action attribute takes in an absolute URL. SignalWire will make a GET or POST request to this URL when entering of digits is completed. If there is no URL provided, SignalWire will re-request the URL that was previously used, which can cause an unwanted looping behavior. Be sure to provide the proper URL in order to avoid this outcome. See below for specified request parameters. |
actionOnEmptyResult optional |
Send a webhook to the action URL even if there is no input. By default, if no input is detected, the next LaML instruction is executed but by setting actionOnEmptyResult to true , a callback to the action URL will be sent to continue call flow. Valid values are true or false . Default is false . |
finishOnKey optional |
The set of digits, (0-9, *, #), that can end a recording. Default is # . |
hints optional |
A list of words and phrases, each a max of 100 characters, a caller is likely to say during a call. |
input optional |
The type of input received from a caller (i.e. speech or DTMF). Values can be dtmf , speech , or dtmf speech . Default is dtmf . |
language optional |
The language in which you expect your callers to speak. Default is en-US . |
method optional |
The method attribute specifies whether the request to action is a GET or a POST . Valid values are GET or POST , default value is POST . |
numDigits optional |
The number of digits you expect to be pressed by a caller. |
partialResultCallback optional |
The URL to request to during speech recognition. No URL is specified by default. |
partialResultCallbackMethod optional |
The type of HTTP request to use when requesting a partialResultCallback . Default is POST . |
profanityFilter optional |
Tells SignalWire whether or not to filter profane language when transcribing a call. Default is true . |
speechTimeout optional |
The set time, in seconds, that SignalWire will wait before ending speech recognition. If set to auto , SignalWire will automatically end speech recognition when there is a pause in speech. |
timeout optional |
The number of seconds of silence or inaction that denote the end of caller input. Default is 5 seconds . |
The action
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
Confidence string |
The score, between 0.0 and 1.0, that determines the accuracy of a transcription. |
SpeechResult string |
The transcribed result of the caller's speech. |
Digits string |
The buttons pressed by a caller. |
Nesting
The following verbs can be nested within a <Gather>
:
<Play>
: plays an audio file, that SignalWire fetches from the URL you configured, back to the caller.<Pause>
: waits silently for a distinctive number of seconds.<Say>
: reads supplied text back to the caller.
Examples
A Simple Gather
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather/>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.gather()
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->gather();
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Gather();
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Gather
response = VoiceResponse()
response.gather()
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.gather
end
puts response.to_s
SignalWire will collect any speech or digits pressed during a call.
Nesting Within a Gather
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather action="https://example.com/process_gather.php" method="GET">
<Say>
Please enter your account number,
followed by the pound sign.
</Say>
</Gather>
<Say>We did not receive any input. Goodbye!</Say>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
gather = response.gather({ action: 'https://example.com/process_gather.php', method: 'GET' })
gather.say('Please enter your account number, followed by the pound sign.')
response.say('We did not receive any input. Goodbye!')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$gather = $response->gather(array(
'action' => 'https://example.com/process_gather.php',
'method' => 'GET'
));
$gather->say('Please enter your account number, followed by the pound sign.');
$response->say('We did not receive any input. Goodbye!');
echo $response;
?>
using Twilio.TwiML;
using Twilio.Http;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var gather = new Gather(action: new Uri("https://example.com/process_gather.php"), method: HttpMethod.Get);
gather.Say("Please enter your account number, followed by the pound sign.");
response.Append(gather);
response.Say("We did not receive any input. Goodbye!");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Gather, Say
response = VoiceResponse()
gather = Gather(action='https://example.com/process_gather.php', method='GET')
gather.say('Please enter your account number, followed by the pound sign.')
response.append(gather)
response.say('We did not receive any input. Goodbye!')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.gather(action: 'https://example.com/process_gather.php', method: 'GET') do |gather|
gather.say(message: 'Please enter your account number, followed by the pound sign.')
end
response.say(message: 'We did not receive any input. Goodbye!')
end
puts response.to_s
You can use the <Say>
verb to prompt callers to enter the desired input. In this example, when a caller enters their account number, SignalWire will submit the result to the URL provided in the action
attribute. If the caller does not enter any digits, SignalWire will prompt the 'Goodbye' statement.
Gather DTMF or Speech
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Gather input="speech dtmf" timeout="5" numDigits="1">
<Say>Please press 3 or say account for account information.</Say>
</Gather>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
gather = response.gather({ input: 'speech dtmf', timeout: 5, numDigits: 1 })
gather.say('Please press 3 or say account for account information.')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$gather = $response->gather(array(
'input' => 'speech dtmf',
'timeout' => 5,
'numDigits' => 1
));
$gather->say('Please press 3 or say account for account information.');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var gather = new Gather(input: "speech dtmf", timeout: 5, numDigits: 1);
gather.Say("Please press 3 or say account for account information.");
response.Append(gather);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Gather, Say
response = VoiceResponse()
gather = Gather(input='speech dtmf', timeout=5, num_digits=1)
gather.say('Please press 3 or say account for account information.')
response.append(gather)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.gather(input: 'speech dtmf', timeout: 5, num_digits: 1) do |gather|
gather.say(message: 'Please press 3 or say account for account information.')
end
end
puts response.to_s
A caller can access their account information either through speech recognition or DTMF tones. SignalWire will wait 5 seconds before processing the information and sending the data.
Potential Issues
<Gather>
doesn't receive caller input when the caller is using a VoIP phone.
Solution: Some VoIP phones have trouble sending DTMF tones. Phones typically use compressed bandwidth-conserving audio protocols that can interfere with the transmission of the digit's signal.
The Digits
parameter is not sent to the <Gather>
URL.
Solution: Verify that your application is not responding to the action
URL with an HTTP 3xx redirect. SignalWire will follow this redirect but will not resend the Digits parameter.
<Hangup>
The <Hangup>
verb ends a call. While <Reject>
ed calls are never answered, calls that use the <Hangup>
verb for disconnection are still answered, becoming subject to billing.
Verb Attributes
The <Hangup>
verb does not support any attributes.
Nesting
No other verbs can be nested within <Hangup>
and you cannot nest <Hangup>
within any other verbs.
Examples
A Simple Hangup
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Hangup/>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.hangup()
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->hangup();
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Hangup();
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Hangup
response = VoiceResponse()
response.hangup()
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.hangup
end
puts response.to_s
SignalWire will answer the call then immediately hangup.
<Leave>
The <Leave>
verb transfers a call out of the queue containing that call. It then returns the flow of execution to verb following the <Enqueue>
that placed this call into the queue.
Verb Attributes
The <Leave>
verb does not support any attributes.
Examples
Leaving a Closed Queue
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Enqueue waitUrl="https://example.com/wait.xml">support</Enqueue>
<Say>Customer support is now closed. Please call back on the next business day. Thank you.</Say>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.enqueue({ waitUrl: 'https://example.com/hold-music.xml' }, 'support')
response.say('Customer support is now closed. Please call back on the next business day. Thank you.')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->enqueue('support', array( 'waitUrl' => 'https://example.com/wait.xml' ));
$response->say('Customer support is now closed. Please call back on the next business day. Thank you.');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Enqueue("support", waitUrl: new Uri("https://example.com/wait.xml"));
response.Say("Customer support is now closed. Please call back on the next business day. Thank you.");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Enqueue, Say
response = VoiceResponse()
response.enqueue('support', wait_url='https://example.com/wait.xml')
response.say('Customer support is now closed. Please call back on the next business day. Thank you.')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.enqueue(name: 'support', wait_url: 'https://example.com/wait.xml')
response.say(message: 'Customer support is now closed. Please call back on the next business day. Thank you.')
end
puts response.to_s
Callers who are waiting in the queue for customer support will automatically be directed out of the queue after closing hours. SignalWire will notify these callers that they have left the queue and will have to try calling back another day.
Playing Audio
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>http://your-application.com/music.mp3</Play>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.play('http://your-application.com/music.mp3')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->play('http://your-application.com/music.mp3');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Play(new Uri("http://your-application.com/music.mp3"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Play
response = VoiceResponse()
response.play('http://your-application.com/music.mp3')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.play(url: 'http://your-application.com/music.mp3')
end
puts response.to_s
SignalWire will play hold music for the callers in the queue until customer support hours are over.
Leave a Call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Leave />
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.leave()
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->leave();
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Leave();
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Leave
response = VoiceResponse()
response.leave()
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.leave
end
puts response.to_s
wait.xml will dequeue the callers after closing hours and prompt the <Say>
statement in the first example.
<Pause>
The <Pause>
verb waits silently for a distinctive number of seconds.
Verb Attributes
Attribute | |
---|---|
length optional |
The number of seconds SignalWire will pause silently before moving on. Defaults to 1s of wait time if no value is provided. |
Nesting
No other verbs can be nested within <Pause>
. However, <Pause>
can be nested within a <Gather>
.
Examples
A Simple Pause
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Please wait one moment while I check that for you.</Say>
<Pause length="8"/>
<Say>Yes, we are open Monday through Friday.</Say>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.say('Please wait one moment while I check that for you.')
response.pause({ length: 8 })
response.say('Yes, we are open Monday through Friday.')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->say('Please wait one moment while I check that for you.');
$response->pause(array( 'length' => 8 ));
$response->say('Yes, we are open Monday through Friday.');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Say("Please wait one moment while I check that for you.");
response.Pause(length: 8);
response.Say("Yes, we are open Monday through Friday.");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Say, Pause
response = VoiceResponse()
response.say('Please wait one moment while I check that for you.')
response.pause(length=8)
response.say('Yes, we are open Monday through Friday.')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.say(message: 'Please wait one moment while I check that for you.')
response.pause(length: 10)
response.say(message: 'Yes, we are open Monday through Friday.')
end
puts response.to_s
This illustrates the wait time between two statements.
Delaying a Response
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Pause length="3"/>
<Say>Hello, how can I help you?</Say>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.pause({ length: 3 })
response.say('Hello, how can I help you?')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->pause(array( 'length' => 3 ));
$response->say('Hello, how can I help you?');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Pause(length: 3);
response.Say("Hello, how can I help you?");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Say, Pause
response = VoiceResponse()
response.pause(length=3)
response.say('Hello, how can I help you?')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.pause(length: 3)
response.say(message: 'Hello, how can I help you?')
end
puts response.to_s
SignalWire waits 3 seconds before answering a call.
<Play>
The <Play>
verb plays an audio file, that SignalWire fetches from the URL you configured, back to the caller.
Verb Attributes
An example of an audio file set to loop 15 times.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play loop="15">https://your-application.com/audio.mp3</Play>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.play({ loop: 15 }, 'https://your-application.com/audio.mp3')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->play('https://your-application.com/audio.mp3', array( 'loop' => 15 ));
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Play(new Uri("https://your-application.com/audio.mp3"), loop: 15);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Play
response = VoiceResponse()
response.play('https://your-application.com/audio.mp3', loop=15)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.play(loop: 15, url: 'https://your-application.com/audio.mp3')
end
puts response.to_s
Attribute | |
---|---|
loop optional |
The loop attribute determines how many times an audio file is played. If no loop is specified, it will default to 1, which means the audio file will only play once. If loop is set to '0', <Play> will continue looping until the call has ended. |
digits optional |
The digits attribute allows you to play DTMF tones throughout a call. If pauses are required in between your DTMF tones, the character w can be used. w adds a pause of 0.5 seconds for each occurrence, so www would render a pause of 1.5 seconds. Note that this attribute simply plays tones into a call. To enter an extension when making a call, use the sendDigits attribute for the noun <Number> of the verb <Dial> . |
Nouns
The noun of a LaML verb is nested within the verb upon which the verb acts. <Play>
has the following noun:
Noun | |
---|---|
plain text |
The URL of the audio file that will be played to the caller. |
MIME Types
The following are the MIME types supported by SignalWire:
Type | |
---|---|
audio/mpeg |
mpeg layer 3 audio |
audio/wav |
wav format audio |
audio/wave |
wav format audio |
audio/x-wav |
wav format audio |
audio/aiff |
audio interchange file format |
audio/x-aifc |
audio interchange file format |
audio/x-aiff |
audio interchange file format |
audio/x-gsm |
GSM audio format |
audio/gsm |
GSM audio format |
audio/ulaw |
μ-law audio format |
Nesting
No other verbs can be nested within <Play>
. However, <Play>
can be nested within <Gather>
. In this case, the verb attribute digits
is not supported.
Examples
Play a Simple Audio File
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play>https://your-application.com/audio.mp3</Play>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.play('https://your-application.com/audio.mp3')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->play('https://your-application.com/audio.mp3');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Play(new Uri("https://your-application.com/audio.mp3"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Play
response = VoiceResponse()
response.play('https://your-application.com/audio.mp3')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.play(url: 'https://your-application.com/audio.mp3')
end
puts response.to_s
The simplest case for <Play>
: SignalWire downloads the specified audio file and plays it to the caller.
Use DTMF Tones in Calls
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Play digits="wwwww9"></Play>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.play({ digits: 'wwwww9' })
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->play(array( 'digits' => 'wwwww9' ));
echo $response;
?>
using Twilio.TwiML;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Play("", digits: "wwwww9");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Play
response = VoiceResponse()
response.play(digits='wwwww9')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.play(digits: 'wwwww9')
end
puts response.to_s
As described in the attributes section, the character w produces a 0.5 second pause. In this example, SignalWire will wait 2.5 seconds before playing the digit '9'.
Notes on Usage
- Audio files that are longer than 40 minutes should be split into smaller files, as it may result in a dropped call.
- Since it takes some time to download and cache files from your server, slight delays may occur the first time an audio file is played. In this case, SignalWire may play a tone during download.
- SignalWire attempts to cache files only when allowed by HTTP headers (ETag and Last-Modified). Always check for a new version of the file with a response of
Cache-Control: no-cache
. This enables your server to respond with a new version, or with a '304 Not Modified', which tells SignalWire to use the cached version. - The degradation that occurs when transcoding high bitrate, lossy encoded files, such as 128kbps MP3 files, can take a long time, resulting in audio that sounds worse than those in lossless 8kbps formats.
- SignalWire transcodes all audio files into a format that is identifiable by the telephone network. Telephones typically do not support high bitrate audio, so playback results in lower-quality audio.
<Record>
The <Record>
verb creates an audio file with the caller's voice and returns the URL to you. Text transcriptions of these recorded calls can also be produced.
Verb Attributes
Attribute | |
---|---|
action optional |
The action attribute takes in an absolute or relative URL. SignalWire will make a GET or POST request to this URL when recording is completed. The current document's URL will be requested if no action is provided. There is no way to return to any instructions listed after the <Record> verb. See below for specified request parameters. |
method optional |
The method attribute specifies whether the request to action is a GET or a POST . Valid values are GET or POST , default value is POST . |
timeout optional |
The timeout attribute specifies the number of seconds of silence that ends a recording. |
finishOnKey optional |
The set of digits, (0-9, *, #), that can end a recording. |
maxLength optional |
The maximum length, in seconds, of the recording. |
playBeep optional |
Whether or not a sound is played before the start of a recording. Default is true. |
trim optional |
Whether or not silence in the beginning and end of recordings are removed. Default value trim-silence follows this behavior. |
recordingStatusCallback optional |
The recordingStatusCallback attribute takes in an absolute or relative URL. SignalWire will make a GET or POST request to this URL when recording is accessible. See below for specified request parameters. |
recordingStatusCallbackEvent optional |
The different recording statuses. Possible values are completed , in-progress , and absent . To specify multiple events, separate with a space. Defaults to completed . |
recordingStatusCallbackMethod optional |
The type of HTTP request to use when requesting a recordingStatusCallback . Default is POST . |
storageUrl optional |
The storageUrl attribute accepts an absolute URL as the destination to send a recording to, if you prefer to host your own recordings and bypass SignalWire storage. |
storageUrlMethod optional |
Specifies which HTTP verb to use when sending the recording to the storageUrl . Available values are: POST and PUT. Defaults to POST. |
transcribe optional |
The transcribe attribute identifies whether to produce a text transcription of the recording. There is an additional charge for this service, so is turned off by default. |
transcribeCallback optional |
The ability to define a URL to which SignalWire will make a POST request to once the transcription is complete. See below for specified request parameters. |
* Please note that if no audio data is received, a recording will not be saved, a request will not be made to any Action url that is set, and the document will continue to be processed with the next verb after Record. This also applies when only silence is detected and 'trim-silence' is set, resulting in no actual audio content remaining to save.
The action
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
RecordingUrl string |
The URL of the recorded audio file. |
RecordingDuration integer |
The duration, in seconds, of the audio recording. |
Digits string |
The buttons pressed to end a recording. |
The recordingStatusCallback
request contains the following parameters:
Parameter | |
---|---|
AccountSid string |
The unique ID of the Account this call is associated with. |
CallSid string |
A unique identifier for the call. May be used to later retrieve this message from the REST API. |
RecordingSid string |
The unique identifier for the recording. |
RecordingUrl string |
The URL for the audio recording. |
RecordingStatus string |
The status of the recording. |
RecordingDuration integer |
The duration, in seconds, of the recording. |
RecordingChannels integer |
The number of channels in the recording. |
RecordingSource string |
The type of call that initiated the recording. |
The transcribeCallback
request contains the Standard Request Parameters as well as:
Parameter | |
---|---|
TranscriptionSid string |
The unique, 34 character ID of the transcription. |
TranscriptionText string |
The text of the transcription. |
TranscriptionStatus string |
The status of the transcription (completed or failed). |
TranscriptionUrl string |
The URL for the transcription's REST API resource. |
RecordingSid string |
The unique, 34 character identifier for the recording from which the transcription was generated from. |
RecordingUrl string |
The URL for the audio recording from which the transcription was generated from. |
Nesting
No other verbs can be nested within <Record>
and you cannot nest
<Record>
within any other verbs.
Examples
A Simple Recording
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Record/>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.record()
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->record();
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Record();
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Record
response = VoiceResponse()
response.record()
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.record
end
puts response.to_s
The caller will hear a 'beep' and the recording will begin.
Recording a Voicemail
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>
Please leave a message at the beep.
Press the pound key when finished.
</Say>
<Record
action="http://your-application.com/handleRecording.php"
method="GET"
maxLength="15"
finishOnKey="#"
/>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.say('Please leave a message at the beep. Press the pound key when finished.')
response.record({ action: 'http://your-application.com/handleRecording.php', method: 'GET', maxLength: 15, finishOnKey: '#' })
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->say('Please leave a message at the beep. Press the pound key when finished.');
$response->record(array(
'action' => 'http://your-application.com/handleRecording.php',
'method' => 'GET',
'maxLength' => 15,
'finishOnKey' => '#'
));
echo $response;
?>
using Twilio.TwiML;
using Twilio.Http;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Say("Please leave a message at the beep. Press the pound key when finished.");
response.Record(action: new Uri("http://your-application.com/handleRecording.php"),
method: HttpMethod.Get, maxLength: 15, finishOnKey: "#");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Record, Say
response = VoiceResponse()
response.say('Please leave a message at the beep. Press the pound key when finished.')
response.record(action='http://your-application.com/handleRecording.php', method='GET', max_length=15, finish_on_key='#')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.say(message: 'Please leave a message at the beep. Press the pound key when finished.')
response.record(action: 'http://your-application.com/handleRecording.php', method: 'GET', max_length: 15, finish_on_key: '#')
end
puts response.to_s
This prompt will play before the 'beep', asking the caller to leave a message. The caller can only leave a message that is 15s long.
Transcribing a Recording
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Record
transcribe="true"
transcribeCallback="http://your-application.com/handle_transcribe.php" />
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.record({ transcribe: true, transcribeCallback: 'http://your-application.com/handle_transcribe.php' })
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->record(array(
'transcribe' => true,
'transcribeCallback' => 'http://your-application.com/handle_transcribe.php'
));
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Record(transcribe: true,
transcribeCallback: new Uri("http://your-application.com/handle_transcribe.php"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Record
response = VoiceResponse()
response.record(transcribe=True, transcribe_callback='http://your-application.com/handle_transcribe.php')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.record(transcribe: true, transcribe_callback: 'http://your-application.com/handle_transcribe.php')
end
puts response.to_s
SignalWire will record the caller and transcribe the recording once it is complete. Then, SignalWire will make a POST
request to the
transcribeCallback
URL with the transcription as a parameter.
Notes on Usage
- SignalWire will trim leading and trailing silence from your audio files, causing the duration of calls to be less than the time spent recording.
<Redirect>
An example that redirects next LaML instruction to another call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Redirect>https://www.your-application.com/next-instructions</Redirect>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.redirect('https://www.your-application.com/next-instructions')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->redirect('https://www.your-application.com/next-instructions');
echo $response;
?>
using Twilio.TwiML;
using Twilio.Http;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Redirect(new Uri("https://www.your-application.com/next-instructions"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Redirect
response = VoiceResponse()
response.redirect('https://www.your-application.com/next-instructions')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.redirect('https://www.your-application.com/next-instructions')
end
puts response.to_s
The <Redirect>
verb transfers control from the current call to another. It is effectively an exit statement from the current call, as there is no way to return to any instructions listed after the
Verb Attributes
The following attribute is available for the verb <Redirect>
:
Attribute | |
---|---|
method optional |
Specifies whether the redirect is a GET or a POST . Default value is POST . |
Nouns
Noun | |
---|---|
plain text |
The URL, in plain text, of the call to execute. |
Nesting
No other verbs can be nested within <Redirect>
and you cannot nest <Redirect>
within any other verbs.
Examples
Redirect to absolute URL
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>310-123-0000</Dial>
<Redirect>http://www.your-application.com/next-instructions</Redirect>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.dial('310-123-0000')
response.redirect('http://www.your-application.com/next-instructions')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->dial('310-123-0000');
$response->redirect('http://www.your-application.com/next-instructions');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Dial("310-123-0000");
response.Redirect(new Uri("http://www.your-application.com/next-instructions"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Dial, Redirect
response = VoiceResponse()
response.dial('310-123-0000')
response.redirect('http://www.your-application.com/next-instructions')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.dial(number: '310-123-0000')
response.redirect('https://www.your-application.com/next-instructions')
end
puts response.to_s
SignalWire makes a request after the number has been dialed and transfers the call to the LaML received through the request.
<Reject>
The <Reject>
verb rejects a call to your SignalWire number. It is effectively an exit statement from the current document, as there is no way to return to any instructions listed after the <Reject>
verb. Rejected calls to your SignalWire numbers will still charge the initial minute to your account.
Verb Attributes
Attribute | |
---|---|
reason optional |
The reason attribute takes in the following values: busy and rejected. These values specify what message is to be played when SignalWire rejects a call. If this value is set to busy , the caller receives a busy signal and the call is terminated with the status busy . If this value is set to rejected , the caller receives a standard "This number is not in service" response and the call is terminated with the status no answer . Default value is rejected . |
Nesting
No other verbs can be nested within <Reject>
and you cannot nest <Reject>
within any other verbs.
Examples
A Simple Rejection of a Call
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Reject />
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.reject()
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->reject();
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Reject();
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Reject
response = VoiceResponse()
response.reject()
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.reject
end
puts response.to_s
SignalWire will reject the call and the caller will receive a standard "This number is not in service" response.
Busy Signal Rejection
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Reject reason="busy" />
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.reject({ reason: 'busy' })
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->reject(array( 'reason' => 'busy' ));
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Reject(reason: "busy");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Reject
response = VoiceResponse()
response.reject(reason='busy')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.reject(reason: busy)
end
puts response.to_s
SignalWire will reject the call and the caller will receive a busy signal.
<Say>
The <Say>
verb reads the supplied text back to the caller. It is useful for text that is difficult to pre-record. The gender and language in which the text will be read is customizable.
Verb Attributes
Attribute | |
---|---|
voice optional |
The attribute voice supports 3 values: man, woman, and alice. Default is woman for most languages. alice is deprecated and provided for backward compatibility. See below for language specifications on each of these voices. |
loop optional |
The attribute loop specifies the number of times a text is to be repeated. If loop is set to 0, the text will be continuously repeated until the call is terminated. Default behavior is one repetition. |
language optional |
The attribute language allows you to specify the dialect (language and locale) of voice . See below for all language specifications. |
The following languages are permitted:
Value | |
---|---|
language default: en |
arb [Arabic, Modern Standard] ar-AR [Arabic, Modern Standard] cy-GB [Welsh, UK] da-DK [Danish, Denmark] de [German, Germany] de-DE [German, Germany] en [English, United States] en-AU [English, Australia] en-CA [English, Canada] en-GB [English, UK] en-GB-WLS [English, Wales] en-IN [English, India] en-US [English, United States] es [Spanish, United States] es-ES [Spanish, Spain] es-MX [Spanish, Mexico] es-US [Spanish, United States] fr [French, France] fr-CA [French, Canada] fr-FR [French, France] hi-IN [Hindi, India] is-IS [Icelandic, Iceland] it [Italian, Italy] it-IT [Italian, Italy] ja-JP [Japanese, Japan] ko-KR [Korean, Korea] morse [Morse Code, Dit Dah] nb-NO [Norwegian, Norway] nl-NL [Dutch, Netherlands] pl-PL [Polish, Poland] pt-BR [Portuguese, Brazil] pt-PT [Portuguese, Portugal] ro-RO [Romanian, Romania] ru-RU [Russian, Russia] sv-SE [Swedish, Sweden] tr-TR [Turkish, Turkey] cmn-CN [Chinese, Mandarin] zh-CN [Chinese, Mandarin] |
Nouns
The noun of a LaML verb is nested within the verb upon which the verb acts. <Say>
has the following noun:
Noun | |
---|---|
plain text limit: 4,096 unicode characters |
The text that will be read to the caller. |
SSML
Speech Synthesis Markup Language (SSML) is an XML-based markup language that provides a standard way to mark up text for synthesized speech.
SSML is usually wrapped within <speak>
tags. But, when using SSML with the <Say>
verb, you can ignore those <speak>
tags. The rest of the SSML tags will be placed inside the <Say>
verb.
Below are the supported SSML tags.
Tag | |
---|---|
<break> |
A pause in speech. Set the length of the pause with the time attribute. Maximum pause time is 10s. Include the unit s or ms when setting a time . The strength attribute can also be used for pauses. See below for possible values. |
<emphasis> |
Emphasize words or phrases. This tag changes the rate and volume of speech. More emphasis generates louder and slower speech while less emphasis generates quieter and faster speech. Emphasis can be modified with the level attribute. See below for possible values. |
<lang> |
Specify another language for specific words or phrases. Set the language with the xml:lang attribute. Possible languages are: en-US , en-GB , en-IN , en-AU , en-CA , de-DE , es-ES , it-IT , ja-JP , fr-FR (English, German, Spanish, Italian, Japanese, French). |
<p> |
Add a pause between paragraphs. |
<phoneme> |
Phonetic pronunciation for specified words or phrases. Set the phonetic alphabet to use with the alphabet attribute. See below for possible values. In addition, you can use the ph attribute to set the phonetic pronunciation to speak. See here for a list of supported symbols. |
<prosody> |
Modify the volume , pitch , and rate of the tagged speech. |
<s> |
Add a pause between sentences. |
<say-as> |
Describe how text should be interpreted. See below for all the possible values of the interpret-as attribute. |
<sub> |
Pronounce the specified word or phrase as a different word or phrase. Specify the pronunciation to substitute with the alias attribute. |
The strength
attribute has the following values. Default is medium
.
Value | |
---|---|
none |
No pause. Can be used to remove a pause that would normally occur. |
x-weak |
No pause. |
weak |
Treat adjacent words as if separated by a single comma. |
medium |
Treat adjacent words as if separated by a single comma. |
strong |
Sentence break. |
x-strong |
Paragraph break. |
The level
attribute has the following values. Default is moderate
.
Value | |
---|---|
strong |
Increase the volume and slow down the speaking rate. Speech is louder and slower. |
moderate |
Increase the volume and slow down the speaking rate, but not as much as strong . |
moderate |
Decrease the volume and speed up the speaking rate. Speech is softer and faster. |
The alphabet
attribute has the following values.
Value | |
---|---|
ipa |
The International Phonetic Alphabet (IPA). |
x-sampa |
The Extended Speech Assessment Methods Phonetic Alphabet (X-SAMPA). |
The volume
attribute has the following values. Set the volume with one of the values below. Then, you can specify a percentage to increase or decrease the volume of the speech. See here for more information.
Value | |
---|---|
silent |
No volume. |
x-soft |
Lowest volume. |
soft |
Lower volume. |
medium |
Normal volume. |
loud |
Louder volume. |
x-loud |
Loudest volume. |
The pitch
attribute has the following values. Set the pitch with one of the values below. Then, you can specify a percentage to increase or decrease the pitch of the speech. See here for more information.
Value | |
---|---|
x-low |
Lowest pitch. |
low |
Lower pitch. |
medium |
Normal pitch. |
high |
Higher pitch. |
x-high |
Highest pitch. |
The rate
attribute has the following values. Set the rate with one of the values below. Then, you can specify a percentage to increase or decrease the speed of the speech. See here for more information.
Value | |
---|---|
x-slow |
Slowest rate. |
slow |
Slower rate. |
medium |
Normal rate. |
fast |
Faster rate. |
x-fast |
Fastest rate. |
The interpret-as
attribute has the following values.
Value | |
---|---|
characters |
Spell out each letter. |
spell-out |
Spell out each letter. |
cardinal |
Interpret value as cardinal number. |
number |
Interpret value as cardinal number. |
ordinal |
Interpret value as ordinal number. |
digits |
Spell each digit separately. |
fraction |
Interpret value as fraction. |
unit |
Interpret value as measurement. |
date |
Interpret value as a date. Use format attribute to indicate format of date: mdy , dmy , ymd , md , dm , ym , my , d , m , y . |
time |
Interpret as a duration of minutes and seconds. |
telephone |
Interpret as telephone number. |
address |
Interpret as part of a street address. |
interjection |
Interpret as an interjection. |
expletive |
"Bleep" out content in tag. |
Example
<Response>
<Say>
Welcome to SignalWire
<break strength="x-weak" time="100ms"/>
<emphasis level="moderate">Emphasized words</emphasis>
<p>Words in a paragraph</p>
<phoneme alphabet="x-sampa" ph="pɪˈkɑːn">Phonetic pronunciation</phoneme>
<prosody pitch="-10%" rate="85%" volume="-6dB">Words to speak</prosody>
<s>Words in a sentence.</s>
<say-as interpret-as="spell-out">Words</say-as>
<sub alias="alias">Words to be substituted</sub>
</Say>
</Response>
Here is an example of how to use some of the SSML tags within the Say
verb.
Nesting
No other verbs can be nested within <Say>
. However, <Say>
can be nested within <Gather>
.
Examples
A Simple Message to be Read
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say>Hello World.</Say>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.say('Hello World.')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->say('Hello World.');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Say("Hello World.");
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Say
response = VoiceResponse()
response.say('Hello World.')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.say(message: 'Hello World.')
end
puts response.to_s
'Hello World' will be read once in a male voice.
Repetition of a Message in a Foreign Language
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Say voice="alice" language="fr-CA" loop="5">Bonjour.</Say>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.say({ voice: 'alice', language: 'fr-CA', loop: 5 }, 'Bonjour.')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->say('Bonjour', array(
'voice' => 'alice',
'language' => 'fr-CA',
'loop' => 5
));
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Say("Bonjour.", voice: "alice", language: "fr-CA", loop: 5);
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import VoiceResponse, Say
response = VoiceResponse()
response.say('Bonjour.', voice='alice', language='fr-CA', loop=5)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.say(message: 'Bonjour.', voice: 'alice', language: 'fr-CA', loop: 5)
end
puts response.to_s
'Hello' will be repeated 5 times in Canadian French.
Notes on Usage
- There is a 4,096 Unicode character limit on the text
- Numbers are spoken, or read, based on context. For example, '234' is read as "two hundred thirty-four", whereas '2 3 4' is read as "two three four".
- Short pauses in spoken text are accomplished by inserting punctuations, i.e. commas and periods, in the written text. For longer pauses, place text in a separate
<Say>
verbs and place a<Pause>
verb in between them. - Dates, times, money amounts, and abbreviations may not follow intuitive pronunciations. Test these situations to ensure they are pronounced to your liking.
<Stream>
The <Stream>
instruction makes it possible to send raw audio streams from a running phone call over WebSockets in near real time, to a specified URL. The audio frames themselves are base64 encoded, embedded in a json string, together with other information like
sequence number and timestamp. The feature can be used with Speech-To-Text systems and others.
Attributes
An example on how to use Stream.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Start>
<Stream url="wss://your-application.com/audiostream" />
</Start>
</Response>
This LAML will instruct Signalwire to make a copy of the audio frames of the current call and send them in near real-time over WebSocket to wss://your-application.com/audiostream.
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
const start = response.start();
start.stream({
name: 'Example Audio Stream',
url: 'wss://your-application.com/audiostream'
});
console.log(response.toString());
<?
use SignalWire\LaML;
$response = new LaML;
$start = $response->start();
$stream = $start->stream(['url' => 'wss://your-application.com/audiostream']);
$stream->parameter(['name' => 'FirstName', 'value' => 'Jane']);
$stream->parameter(['name' => 'LastName', 'value' => 'Doe']);
echo $response;
?>
using System;
using Twilio.TwiML;
using Twilio.TwiML.Voice;
class Example
{
static void Main()
{
var response = new VoiceResponse();
var start = new Start();
start.Stream(name: "Example Audio Stream", url: "wss://your-application.com/audiostream");
response.Append(start);
Console.WriteLine(response.ToString());
}
}
from twilio.twiml.voice_response import Parameter, VoiceResponse, Start, Stream
response = VoiceResponse()
start = Start()
stream = Stream(url='wss://your-application.com/audiostream')
stream.parameter(name='FirstName', value='Jane')
stream.parameter(name='LastName', value='Doe')
start.append(stream)
response.append(start)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new
response.start do |start|
start.stream(url: 'wss://your-application.com/audiostream') do |stream|
stream.parameter(name: 'FirstName', value: 'Jane')
stream.parameter(name: 'LastName', value: 'Doe')
end
end
puts response
Attribute | |
---|---|
url |
Absolute or relative URL. A WebSocket connection to the url will be established and audio will start flowing towards the Websocket server. The only supported protocol is wss . For security reasons ws is NOT supported. |
name optional |
Unique name for the Stream, per Call. It is used to stop a Stream by name. |
track optional |
This attribute can be one of: inbound_track , outbound_track , both_tracks . Defaults to inbound_track . For both_tracks there will be both inbound_track and outbound_track events. |
statusCallback optional |
Absolute or relative URL. SignalWire will make a HTTP GET or POST request to this URL when a Stream is started, stopped or there is an error. |
statusCallbackMethod optional |
GET or POST. The type of HTTP request to use when requesting a statusCallback. Default is POST. |
For a statusCallback
, SignalWire will send a request with the following parameters:
Parameter | |
---|---|
AccountSid string |
The unique ID of the Account this call is associated with. |
CallSid string |
A unique identifier for the call. May be used to later retrieve this message from the REST API. |
StreamSid string |
The unique identifier for this Stream. |
StreamName string |
If defined, this is the unique name of the Stream. Defaults to the StreamSid. |
StreamEvent string |
One of stream-started , stream-stopped , or stream-error . |
StreamError string |
If an error has occurred, this will contain a detailed error message. |
Timestamp string |
The time of the event in ISO 8601 format. |
Custom Parameters
To pass parameters towards the wss
server is possible to include additional key value pairs. It can be done by using the nested Start
message, as json.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Start>
<Stream url="wss://your-application.com/audiostream" >
<Parameter name="Cookie" value ="948f9938-299a-d43e-0df4-af3a7eccb0ac"/>
<Parameter name="Type" value ="SIP" />
</Stream>
</Start>
</Response>
Stopping a Stream
It is possible to stop a stream at any time by name. For instance by naming the Stream "mystream", you can later use the unique name of "mystream" to stop the stream.
<Start>
<Stream name="mystream" url="wss://mystream.ngrok.io/audiostream" />
</Start>
<Stop>
<Stream name="mystream" />
</Stop>
WebSocket Messages
There are 4 separate types of events that occur during the Stream's life cycle.
These events are represented via WebSocket Messages: Connected
, Start
, Media
and Stop
.
Each message sent is a JSON string.
The type of event which is occurring can be identified by using the event
property of every JSON object.
Connected Message
The first message sent once a WebSocket connection is established is the Connected event. This message describes the protocol to expect in the following messages.
Event | |
---|---|
event | The string value of "connected" |
protocol | Defines the protocol for the WebSocket connections lifetime. eg: "Call" |
version | Semantic version of the protocol. |
Example Connected Message
{
"event": "connected",
"protocol": "Call",
"version": "0.2.0"
}
Start Message
This message contains important information about the Stream and is sent immediately after the Connected
message.
It is only sent once at the start of the Stream.
Event | |
---|---|
event | The string value of start |
sequenceNumber | Number used to keep track of message sending order. First message starts with number "1" and then is incremented. |
start | An object containing Stream metadata |
start.streamSid | The unique identifier of the Stream. |
start.accountSid | The Account identifier that created the Stream. |
start.callSid | The Call identifier from where the Stream was started. |
start.tracks | An array of values that indicates what media flows to expect in subsequent messages. Values are one of "inbound" or "outbound" or both. |
start.customParameters | An object that represents the Custom Parameters that where set when defining the Stream. |
start.mediaFormat | An object containing the format of the payload in the Media Messages. |
start.mediaFormat.encoding | The encoding of the data in the upcoming payload. Default is "audio/x-mulaw". |
start.mediaFormat.sampleRate | The Sample Rate in Hertz of the upcoming audio data. Default value is 8000, which is the rate of PCMU. |
start.mediaFormat.channels | The number of channels in the input audio data. Default value is 1. For both_tracks it will be 2. |
Example Start Message
{
"event": "start",
"sequenceNumber": "2",
"start": {
"streamSid": "c0c7d59b-df06-435e-afbc-9217ce318390",
"accountSid": "123abc",
"callSid": "a30d16a5-0368-4104-afbf-14247e76a63d",
"tracks": [
"inbound",
"outbound"
],
"customParameters": {
"FirstName": "Jane",
"LastName": "Doe",
"RemoteParty": "Bob",
},
"mediaFormat": {
"encoding": "audio/x-mulaw",
"sampleRate": 8000,
"channels": 1
}
}
}
Media Message
This message type encapsulates the raw audio data.
Event | |
---|---|
event | The string value of media |
sequenceNumber | Number used to keep track of message sending order. First message starts with number "1" and then is incremented for each message. |
media | An object containing media metadata and payload. |
media.track | One of the strings inbound or outbound . |
media.chunk | The chunk for the message. The first message will begin with number "1" and increment with each subsequent message. |
media.timestamp | Presentation Timestamp in Milliseconds from the start of the stream. |
media.payload | Raw audio encoded in base64. |
Example Media Messages
Outbound
{
"event": "media",
"sequenceNumber": "3",
"media": {
"track": "outbound",
"chunk": "1",
"payload": "iY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//jw=="
}
}
Inbound
{
"event": "media",
"sequenceNumber": "4",
"media": {
"track": "inbound",
"chunk": "1",
"timestamp": "5",
"payload": "/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JD/+PiY//DwkP/4+Jj/8PCQ//j4mP/w8JDw=="
}
}
Stop Message
A stop message will be sent when the Stream is either stopped or the Call has ended.
Example Stop Message
{
"event": "stop",
"sequenceNumber": "5"
}
Event | |
---|---|
event | The string value of stop |
sequenceNumber | Number used to keep track of message sending order. First message starts with number "1" and then is incremented for each message. |
Notes on Usage
- The url does not support query string parameters. To pass custom key value pairs to the WebSocket, make use of Custom Parameters instead.
- There is a one to one mapping of a stream to a websocket connection, therefore there will be at most one call being streamed over a single websocket connection. Information will be provided so that you can handle handle multiple inbound connections and manage the association between the unique stream identifier (StreamSid) and the connection.
- On any given call there are inbound and outbound tracks,
inbound
represents the audio Signalwire receives from the call,outbound
represents the audio generated by Signalwire for the Call.
Messaging LaML
Messaging LaML is a set of actions defined in an XML document you can use to tell SignalWire what to do when you receive an incoming SMS or MMS message.
Overview
When an SMS or MMS message is sent to one of your SignalWire phone numbers, SignalWire looks up the Messaging LaML document from URL you configured, and reads the instructions you provided to determine what to do.
Messaging LaML allows you to dynamically control what happens, responding with specific instructions based on the caller, time of day, incoming message, and much more.
Request For LaML
SignalWire makes an HTTP request to your configured endpoint just like a regular web form submission (POST) or page load (GET). Including contextual information about the message in the request to your endpoint, allows you to respond dynamically and fluidly to the message to meet the needs of your application.
You can configure the endpoint URL and HTTP Method in your phone number settings panel on your SignalWire dashboard, or via the REST API.
Request Parameters
SignalWire sends the following parameters, as either URL query parameters or POST parameters, to your endpoint when it receives a message:
Parameter | |
---|---|
MessageSid string | A unique identifier for the message. May be used to later retrieve this message from the REST API. |
AccountSid string | The unique ID of the Account this message is associated with. |
From string | The phone number that sent this message, in E.164 format. |
To string | The phone number of the message recipient, in E.164 format. |
Body string | The text body of the message. |
NumMedia integer | The number of media items associated with the message. |
MediaUrl{X} string only if media present |
The URL to the media received in the message. URLs are publicly available but unguessable. Each media entry has its own entry, where X is a zero-based index of the media. Example: MediaUrl0 |
MediaContentType{X} string only if media present |
The content-type of the media stored at MediaUrl{X}, where X is a zero-based index of the media. Example: MediaContentType0 |
Responding to SignalWire
An example LaML document that sends two messages back to the sender when a message is received.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>Hello from SignalWire!</Message>
<Message>Thanks for your message.</Message>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.MessagingResponse()
response.message('Hello from SignalWire!')
response.message('Thanks for your message.')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->message('Hello from SignalWire!');
$response->message('Thanks for your message.');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new MessagingResponse();
response.Message("Hello from SignalWire!");
response.Message("Thanks for your message.")
Console.WriteLine(response.ToString());;
}
}
from twilio.twiml.messaging_response import Message, MessagingResponse
response = MessagingResponse()
response.message('Hello from SignalWire!')
response.message('Thanks for your message.')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::MessagingResponse.new do |response|
response.message(body: 'Hello from SignalWire!')
response.message(body: 'Thanks for your message.')
end
puts response.to_s
When a message comes into one of your SignalWire phone numbers, SignalWire makes an HTTP request to the URL endpoint you configured for that number. Your response to that request instructs SignalWire on what to do next.
Responses to the HTTP request are in LaML. SignalWire starts at the top of your LaML document and executes your LaML commands in order, from top to bottom.
Status Callbacks
SignalWire can send your application callbacks at various lifecycle stages of your message. Status callbacks do not allow you change the application execution directly, so callbacks do not have to respond with LaML, but they allow your application to get updates as a message is happening.
You should respond to any callbacks with a 200 OK
or 204 No Content
, otherwise you will see failures in your application log on SignalWire.
MIME Types
The following are the MIME types supported by SignalWire:
Type | |
---|---|
audio/mp4 |
mpeg layer 4 audio |
audio/mpeg |
mpeg layer 3 audio |
audio/mpeg3 |
mpeg layer 3 audio |
audio/ogg |
ogg audio |
audio/vorbis |
audio compression format |
audio/vnd.wav |
wav format audio |
audio/ac3 |
codec format audio |
audio/amr |
codec format audio |
audio/midi |
musical instrument digital interface format |
image/jpeg |
jpeg format image |
image/gif |
graphics interchange format |
image/png |
portable network graphics format |
image/bmp |
bitmap image format |
text/plain |
text file format |
text/calendar |
text file format |
text/vcard |
text file format |
text/x-vcard |
text file format |
video/mpeg |
mpeg video format |
video/mp4 |
mpeg layer 4 video format |
video/quicktime |
quicktime video |
video/h264 |
video compression format |
video/3gp |
media container format |
<Message>
An example message that responds to the sender.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>Hello from SignalWire!</Message>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.MessagingResponse()
response.message('Hello from SignalWire!')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->message('Hello from SignalWire!');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new MessagingResponse();
response.Message("Hello from SignalWire!");
Console.WriteLine(response.ToString());;
}
}
from twilio.twiml.messaging_response import Message, MessagingResponse
response = MessagingResponse()
response.message('Hello from SignalWire!')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::MessagingResponse.new do |response|
response.message(body: 'Hello from SignalWire!')
end
puts response.to_s
The <Message>
verb sends an SMS or MMS message to a phone number.
Verb Attributes
An example message with further instructions returned from the action request.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message action="https://your-application.com/followup"
method="GET">
Hello from SignalWire!
</Message>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.MessagingResponse()
response.message({ action: 'https://your-application.com/followup', method: 'GET' }, 'Hello from SignalWire!')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->message('Hello from SignalWire!', array(
'action' => 'https://your-application.com/followup',
'method' => 'GET'
));
echo $response;
?>
using Twilio.TwiML;
using Twilio.Http;
using System;
class Example
{
static void Main()
{
var response = new MessagingResponse();
response.Message("Hello from SignalWire",
action: new Uri("https://your-application.com/followup"), method: HttpMethod.Get);
Console.WriteLine(response.ToString());;
}
}
from twilio.twiml.messaging_response import Message, MessagingResponse
response = MessagingResponse()
response.message('Hello from SignalWire!', action='https://your-application.com/followup', method="GET")
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::MessagingResponse.new do |response|
response.message(action: 'https://your-application.com/followup', method: 'GET', message: 'Hello from SignalWire!')
end
puts response.to_s
Attribute | |
---|---|
to optional |
The to attribute takes a valid phone number in E.164 format as an argument. The message is sent to this phone number. If no to is specified, the message is sent as a reply to the incoming message sender. |
from optional |
The from attribute takes a valid phone number in E.164 format or short code. If no from is specified, it defaults to the number that received the message. You can only specify from phone numbers or short codes that you have purchased from SignalWire and which are capable of messaging. |
action optional |
The action attribute takes a URL endpoint that is expected to return a LaML document to override control flow. The endpoint receives a callback with the standard message request parameters as well as MessageStatus and ErrorCode and expect a valid LaML document in return. The next instructions to be executed are the verbs returned in response to the action endpoint request.For example, any verbs following a <Message> verb with its action attribute set are unreachable, as flow control will be passed onto the response from the action request. |
method optional |
The method attribute specifies whether the request to action is a GET or a POST . Valid values are GET or POST , default value is POST . |
Message Status
The MessageStatus
parameter is sent with requests to the action
endpoint or to statusCallback URLs. It determines whether the message was successfully sent or if there were problem with delivery.
Valid message statuses are: queued
, sending
, sent
, failed
, delivered
Nouns
An example Message verb using nested nouns
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>
<Body>Hello from SignalWire!</Body>
<Media>https://link.to/your-media-file</Media>
</Message>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.MessagingResponse()
message = response.message()
message.body('Hello from SignalWire!')
message.media('https://link.to/your-media-file')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$message = $response->message('');
$message->body('Hello from SignalWire!');
$message->media('https://link.to/your-media-file');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Messaging;
using System;
class Example
{
static void Main()
{
var response = new MessagingResponse();
var message = new Message();
message.Body("Hello from SignalWire!");
message.Media(new Uri("https://link.to/your-media-file"));
response.Append(message);
Console.WriteLine(response.ToString());;
}
}
from twilio.twiml.messaging_response import Message, Media, Body, MessagingResponse
response = MessagingResponse()
message = Message()
message.body('Hello from SignalWire!')
message.media('https://link.to/your-media-file')
response.append(message)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::MessagingResponse.new do |response|
response.message do |message|
message.body('Hello from SignalWire!')
message.media('https://link.to/your-media-file')
end
end
puts response.to_s
The noun of a LaML verb is nested within the verb upon which the verb acts. <Message>
has the following nouns:
Noun | |
---|---|
plain text |
The text of the message you want to send. |
<Body> |
The text of the message you want to send. If more than one <Body> noun is present, the text will be concatenated together into a single string. The maximum body size allowed is 1600 characters. |
<Media> |
The URL of media to include in the message. If you wish to send multiple media in a single message, use multiple <Media> nouns. You can have a maximum of 10 media URLs per message. |
Nesting
No other verbs can be nested within <Message>
and you cannot nest <Message>
within any other verbs.
Examples
Send a simple SMS
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>Hello from SignalWire!</Message>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.MessagingResponse()
response.message('Hello from SignalWire!')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->message('Hello from SignalWire!');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new MessagingResponse();
response.Message("Hello from SignalWire!");
Console.WriteLine(response.ToString());;
}
}
from twilio.twiml.messaging_response import Message, MessagingResponse
response = MessagingResponse()
response.message('Hello from SignalWire!')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::MessagingResponse.new do |response|
response.message(body: 'Hello from SignalWire!')
end
puts response.to_s
The simplest case for <Message>
: SignalWire responds to an inbound message with a "hello" message, from the number that received the message.
Send an image with your message (MMS)
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message>
<Body>Hello from SignalWire!</Body>
<Media>https://link.to/your-media-file</Media>
</Message>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.MessagingResponse()
message = response.message()
message.body('Hello from SignalWire!')
message.media('https://link.to/your-media-file')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$message = $response->message('');
$message->body('Hello from SignalWire!');
$message->media('https://link.to/your-media-file');
echo $response;
?>
using Twilio.TwiML;
using Twilio.TwiML.Messaging;
using System;
class Example
{
static void Main()
{
var response = new MessagingResponse();
var message = new Message();
message.Body("Hello from SignalWire!");
message.Media(new Uri("https://link.to/your-media-file"));
response.Append(message);
Console.WriteLine(response.ToString());;
}
}
from twilio.twiml.messaging_response import Message, Media, Body, MessagingResponse
response = MessagingResponse()
message = Message()
message.body('Hello from SignalWire!')
message.media('https://link.to/your-media-file')
response.append(message)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::MessagingResponse.new do |response|
response.message do |message|
message.body('Hello from SignalWire!')
message.media('https://link.to/your-media-file')
end
end
puts response.to_s
Add a picture to the message by specifying a URL with a nested <Media>
noun. The <Body>
noun is optional if you are sending media and you do not want to send text with your media in the message.
Send a Message and Respond Based on Status
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Message action="https://your-application.com/followup"
method="GET">
Hello from SignalWire!
</Message>
<Message>I am unreachable!</Message>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.MessagingResponse()
response.message({ action: 'https://your-application.com/followup', method: 'GET' }, 'Hello from SignalWire!')
response.message('I am unreachable!')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->message('Hello from SignalWire!', array(
'action' => 'https://your-application.com/followup',
'method' => 'GET'
));
$response->message('I am unreachable!');
echo $response;
?>
using Twilio.TwiML;
using Twilio.Http;
using System;
class Example
{
static void Main()
{
var response = new MessagingResponse();
response.Message("Hello from SignalWire!",
action: new Uri("https://your-application.com/followup"), method: HttpMethod.Get);
response.Message("I am unreachable!");
Console.WriteLine(response.ToString());;
}
}
from twilio.twiml.messaging_response import Message, MessagingResponse
response = MessagingResponse()
response.message('Hello from SignalWire!', action='https://your-application.com/followup', method="GET")
response.message('I am unreachable!')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::MessagingResponse.new do |response|
response.message(action: 'https://your-application.com/followup', method: 'GET', message: 'Hello from SignalWire!')
response.message(body: 'I am unreachable!')
end
puts response.to_s
This example allows us to follow up with further actions based on whether the message is sent or not. The URL https://your-application.com/followup
receives a GET
request with the message's parameters and includes the MessageStatus
, either invalid
, sending
or failed
.
The LaML document returned from your application determines what to do next. You could do nothing, or if the MessageStatus
was failed, you could alert the user with a different <Message>
.
With the action
attribute is present, the remaining verbs in the document are unreachable because control is passed off to the response rather than continuing on in the document.
See Also
Send messages without waiting for an inbound message by using our LaML REST API to create a message.
<Redirect>
An example message that redirects next LaML instruction to another document
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Redirect>https://your-application.com/next-instructions</Redirect>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.redirect('https://your-application.com/next-instructions')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->redirect('https://your-application.com/next-instructions');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Redirect(new Uri("https://your-application.com/next-instructions"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import Redirect, VoiceResponse
response = VoiceResponse()
response.redirect('https://your-application.com/next-instructions')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.redirect('https://your-application.com/next-instructions')
end
puts response.to_s
The <Redirect>
verb transfers control from the current document to another. It is effectively an exit statement from the current document, as there is no way to return to any instructions listed after the <Redirect>
verb.
Verb Attributes
The following attribute is available for the verb <Redirect>
:
Attribute | |
---|---|
method optional |
Specifies whether the redirect is a GET or a POST . Default value is POST . |
Nouns
The following item is accepted as a noun for the <Redirect>
verb:
Noun | |
---|---|
URL | The URL, in plain text, of the document to execute. |
Nesting
No other verbs can be nested within <Redirect>
and you cannot nest <Redirect>
within any other verbs.
Examples
Redirect to absolute URL
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Redirect>http://www.somesite.com/NextDoc.xml</Redirect>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.VoiceResponse()
response.redirect('http://www.somesite.com/NextDoc.xml')
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->redirect('http://www.somesite.com/NextDoc.xml');
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new VoiceResponse();
response.Redirect(new Uri("http://www.somesite.com/NextDoc.xml"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.voice_response import Redirect, VoiceResponse
response = VoiceResponse()
response.redirect('http://www.somesite.com/NextDoc.xml')
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::VoiceResponse.new do |response|
response.redirect('http://www.somesite.com/NextDoc.xml')
end
puts response.to_s
To continue processing this message using the instructions in another document, specify the absolute URL of that document as the noun to the <Redirect>
verb.
Tutorials
Coming Soon!
Fax LaML
Fax LaML is a set of actions defined in an XML document you can use to tell SignalWire what to do when you receive an incoming fax.
Overview
When a fax is sent to one of your SignalWire phone numbers, SignalWire looks up the Fax LaML document from the URL you configured, and reads the instructions you provided to determine what to do.
Fax LaML allows you to control what SignalWire will do when you receive an incoming fax.
Request for LaML
SignalWire makes an HTTP request to your configured endpoint just like a regular web form submission (POST) or page load (GET). The request includes contextual information about the fax, allowing you to respond dynamically and fluidly to the fax to meet the needs of your application.
You can configure the endpoint URL and HTTP Method in your phone number settings panel on your SignalWire dashboard, or via the REST API.
Request Parameters
SignalWire sends the following parameters, as either URL query parameters or POST parameters, to your endpoint when it receives a fax:
Parameter | |
---|---|
FaxSid string |
A unique identifier for the fax. |
AccountSid string |
The account that the fax was sent from. |
To string |
The number or SIP URI the fax will be sent to. |
From string |
The number or SIP From the fax was sent from. |
ApiVersion string |
The version of the SignalWire API. |
Responding to SignalWire
An example of a LaML document that receives an incoming fax.
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Receive action="/fax/received"/>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.FaxResponse()
response.receive({ action: "/fax/received" })
console.log(response.toString())
using Twilio.TwiML;
using Twilio.TwiML.Fax;
using System;
class Example
{
static void Main()
{
var response = new FaxResponse();
response.Receive(action: "/fax/received"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.fax_response import FaxResponse, Receive
response = FaxResponse()
response.receive(action="/fax/received")
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::FaxResponse.new do |response|
response.receive(action: "/fax/received")
end
puts response.to_s
<?php
use SignalWire\LaML;
$response = new LaML;
$response->receive(array( 'action' => '/fax/received' ));
echo $response;
?>
When a fax comes into one of your SignalWire phone numbers, SignalWire makes an HTTP request to the URL endpoint you configured for that number. Your response to that request instructs SignalWire on what to do next.
Responses to the HTTP request are in LaML. SignalWire starts at the top of your LaML document and executes your LaML commands in order, from top to bottom.
<Receive>
The <Receive>
verb tells SignalWire to receive an incoming fax, which results in the creation of a new Fax instance resource.
Verb Attributes
Attribute | |
---|---|
action optional |
The URL to request when a fax has failed or has been received. |
method optional |
The method attribute specifies whether the request to action is a GET or a POST . Valid values are GET or POST , default value is POST . |
mediaType optional |
The type of media used to store fax media. Valid values are application/pdf or image/tiff . Default is application/pdf . |
pageSize optional |
The size to interpret incoming pages as. Valid values are letter , legal , or a4 . Default is letter . |
storeMedia optional |
Whether or not to store incoming media in the fax media store. Values are true or false . Default is true . See below for more information. |
Action Callback
If the verb attribute action
is specified, the action callback will include the Standard Request Parameters plus the following optional parameters:
Parameter | |
---|---|
RemoteStationId optional |
The transmitting subscriber identification (TSID) reported by the fax machine that sent in the fax. |
FaxStatus optional |
The status of the fax. |
NumPages optional |
The number of pages received from a successful fax. |
MediaUrl optional |
The media URL to request to retrieve incoming media. The URL will expire after 2 hours. However, new URLs can be retrieved from the created Fax instance resource. |
ErrorCode optional |
The error code provides more information on a failed fax. |
ErrorMessage optional |
The message explaining the reason for fax failure. |
How to Prevent Media Storage
- To prevent media storage, set
storeMedia
tofalse
. - An
action
callback with a POSTmethod
must be specified. - The media file will be in the
Media
parameter, instead ofMediaUrl
. - The media will be permanently deleted on the SignalWire side once it is successfully delivered.
- A 2xx HTTP response is required from your server to immediately delete incoming media. If no 2xx is received, SignalWire will attempt to resend the callback with the media every 2.5 minutes for 2 hours. After the 2 hours, the media will be deleted.
- SignalWire saves metadata records of all received faxes. Use the REST API to delete this record.
Examples
Receive a Fax
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Receive action="/fax/received"/>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.FaxResponse()
response.receive({ action: "/fax/received" })
console.log(response.toString())
using Twilio.TwiML;
using Twilio.TwiML.Fax;
using System;
class Example
{
static void Main()
{
var response = new FaxResponse();
response.Receive(action: "/fax/received"));
Console.WriteLine(response.ToString());;
}
}
from signalwire.fax_response import FaxResponse, Receive
response = FaxResponse()
response.receive(action="/fax/received")
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::FaxResponse.new do |response|
response.receive(action: "/fax/received")
end
puts response.to_s
<?php
use SignalWire\LaML;
$response = new LaML;
$response->receive(array( 'action' => '/fax/received' ));
echo $response;
?>
SignalWire will receive the incoming fax and provide a URL endpoint.
Store Fax Image
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Receive mediaType="image/tiff" storeMedia="true"></Receive>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.FaxResponse()
response.receive({ mediaType: "image/tiff", storeMedia: true })
console.log(response.toString())
using Twilio.TwiML;
using Twilio.TwiML.Fax;
using System;
class Example
{
static void Main()
{
var response = new FaxResponse();
response.Receive(mediaType: "image/tiff", storeMedia: true));
Console.WriteLine(response.ToString());;
}
}
from signalwire.fax_response import FaxResponse, Receive
response = FaxResponse()
response.receive(media_type="image/tiff", store_media=True)
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::FaxResponse.new do |response|
response.receive(media_type: "image/tiff", store_media: true)
end
puts response.to_s
<?php
use SignalWire\LaML;
$response = new LaML;
$response->receive(array( 'mediaType' => 'image/tiff', 'storeMedia': true ));
echo $response;
?>
This example shows that the media from the incoming fax will be stored on SignalWire's server in TIFF format.
<Reject>
The <Reject>
verb tells SignalWire to reject an incoming fax, which results in a status of canceled
.
Verb Attributes
The <Reject>
verb does not have any attributes that modify its behavior.
Examples
Fax Reject
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Reject/>
</Response>
const { RestClient } = require('@signalwire/node')
const response = new RestClient.LaML.FaxResponse()
response.reject()
console.log(response.toString())
<?php
use SignalWire\LaML;
$response = new LaML;
$response->reject();
echo $response;
?>
using Twilio.TwiML;
using System;
class Example
{
static void Main()
{
var response = new FaxResponse();
response.Reject();
Console.WriteLine(response.ToString());;
}
}
from signalwire.fax_response import FaxResponse, Reject
response = FaxResponse()
response.reject()
print(response)
require 'signalwire/sdk'
response = Signalwire::Sdk::FaxResponse.new do |response|
response.reject
end
puts response.to_s
SignalWire will reject the incoming fax.