What the call does
-
One request per call
A single REST API request places the call and names the document to run when it is answered.
-
Person or voicemail
Answering-machine detection reports who answered as
AnsweredBy, before the document runs. -
A message after the beep
On voicemail, the document waits for the greeting to end, then leaves the full message.
-
A reply on the keypad
A person can press 1 to confirm, or 2 to be connected to the attendance office.
How the pieces fit
| Piece | Where it lives | What it does |
|---|---|---|
| API request | Your terminal, a script, or a scheduled job | Places each call, with machine detection on. |
| Notice document | voiceml.org, /r/ URL | Runs when the call is answered. Leaves a voicemail, or asks a person to reply. |
| Response document | voiceml.org, /r/ URL | The action of the reply <Gather>. Thanks the person or connects them to the office. |
| Attendance office | Any phone number | Rings when a person presses 2. |
Before you start
- A VoiceML account with a phone number, to place the calls from. See VoiceML or start a free trial.
- The Account SID and API key, for the API request.
- Consent from the people you call. Automated and prerecorded calls need the recipient’s prior express consent. See compliance and abuse prevention before you place calls to anyone but yourself.
The numbers in these documents and the request are fictional. They use the 555-0100 to 555-0199 range, which is set aside for fiction. Test by calling your own phone first.
Step 1: Publish the response document
Replace the attendance office’s number with your own, then publish it at voiceml.org. It contains Liquid tags, so it is published to an /r/ URL. Keep the URL exactly as returned, key included, and don’t post it publicly.
response.xml
<Response>
{% case Digits %}
{% when "1" %}
<Say>Thank you for confirming. Goodbye.</Say>
<Hangup/>
{% when "2" %}
<Say>Connecting you to the attendance office.</Say>
<Dial timeout="25" ringTone="us">
<Number>+13125550140</Number>
</Dial>
<Say>The attendance office is not available. Please call back during school hours. Goodbye.</Say>
<Hangup/>
{% else %}
<Say>That is not a valid option. Please call the attendance office. Goodbye.</Say>
<Hangup/>
{% endcase %}
</Response>
Step 2: Publish the notice document
Replace RESPONSE_URL with the /r/ URL from step 1, then publish.
notice.xml
<Response>
{% if AnsweredBy contains "machine" %}
<!-- Voicemail answered. With DetectMessageEnd, this plays after the greeting ends. -->
<Say>Hello, this is Edward Rooney, Dean of Students, calling about an absence from school today.</Say>
<Say>So far this semester, that is nine absences. Please call the attendance office to discuss it. Thank you.</Say>
<Hangup/>
{% elsif AnsweredBy == "fax" %}
<Hangup/>
{% else %}
<!-- A person answered, or detection couldn't tell -->
<Gather input="dtmf" numDigits="1" action="RESPONSE_URL" method="POST" timeout="8">
<Say>Hello, this is Edward Rooney, Dean of Students, calling about an absence from school today.</Say>
<Say>To confirm you received this message, press 1. To speak with the attendance office now, press 2.</Say>
</Gather>
<Say>We did not receive a response. Please call the attendance office. Goodbye.</Say>
<Hangup/>
{% endif %}
</Response>
Step 3: Place a call
Send this request with your Account SID, API key, phone numbers, and the notice document’s /r/ URL in place of NOTICE_URL. From must be a number on your account or a caller ID verified on it; any other number is refused with error 21210. Start with your own mobile as To.
Place the call
ACCOUNT_SID="AC..."
API_KEY="..."
curl -u "$ACCOUNT_SID:$API_KEY" \
-d "To=+13125550199" \
-d "From=+13125550100" \
-d "Url=NOTICE_URL" \
-d "MachineDetection=DetectMessageEnd" \
https://voiceml.voicetel.com/2010-04-01/Accounts/$ACCOUNT_SID/Calls
Answer it to hear the menu and press 1 or 2. Place it again and let it go to voicemail to hear the message left after your greeting.
How detection picks the message
With MachineDetection in the request, the call waits for a verdict before running the document, and the verdict arrives with the request for NOTICE_URL as AnsweredBy. The notice document branches on it:
AnsweredBy |
What happens |
|---|---|
human | The menu: press 1 to confirm, or 2 for the attendance office. |
Starts with machine | The voicemail message, then the call ends. |
fax | The call ends. |
unknown | The menu, so a person who wasn’t recognized still hears it. |
MachineDetection=DetectMessageEnd waits for the voicemail greeting to finish before reporting a machine, so the message starts after the beep instead of over the greeting. MachineDetection=Enable reports sooner and suits calls that hang up on machines. The detection thresholds and timeout are the same settings as the <Number> noun’s machine detection.
Where the movie turns up
| Where | Reference |
|---|---|
| The caller | Edward Rooney, Dean of Students. |
| The voicemail | Nine absences so far this semester. |
Limits of this design
- Every call says the same thing. A voiceml.org document can’t receive values of your own, such as a student’s name, so a personal message needs one document per message, or a server.
- Replies aren’t recorded. Pressing 1 is acknowledged on the call, but nothing stores it. To keep a list of who confirmed, point the
<Gather>’sactionat your own server. - One request places one call. Calling a list means sending one request per number, from a script or scheduler.
- Detection can be wrong. A person who answers with a long greeting can be taken for voicemail, and a short voicemail greeting for a person. The voicemail message is written to make sense either way.
Credits
- Edward Rooney and Ferris’s nine absences come from Ferris Bueller’s Day Off (1986), written and directed by John Hughes and distributed by Paramount Pictures. Matthew Broderick plays Ferris Bueller, and Jeffrey Jones plays Edward R. Rooney, the Dean of Students.
- The school, its calls, and its phone numbers are fictional in this example. VoiceTel is not affiliated with the film or its rights holders.
- References: the machine detection settings, the direct HTTP test call on the migration guide, and the voiceml.org publishing and integration guide.

