VoiceTel

Support / VoiceML examples / Build outbound notification calls with VoiceML

Build outbound notification calls with VoiceML.

A fictional high school’s Dean of Students calls home about an absence. One API request places the call; answering-machine detection decides whether to leave a voicemail or talk to a person; and a person can confirm the message or be put through to the attendance office. The call flow is two documents published on voiceml.org, with no application server.

Free trial Machine detection reference

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

Components of the attendance calls
Piece Where it lives What it does
API requestYour terminal, a script, or a scheduled jobPlaces each call, with machine detection on.
Notice documentvoiceml.org, /r/ URLRuns when the call is answered. Leaves a voicemail, or asks a person to reply.
Response documentvoiceml.org, /r/ URLThe action of the reply <Gather>. Thanks the person or connects them to the office.
Attendance officeAny phone numberRings when a person presses 2.

Before you start

  1. A VoiceML account with a phone number, to place the calls from. See VoiceML or start a free trial.
  2. The Account SID and API key, for the API request.
  3. 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:

What each AnsweredBy value does
AnsweredBy What happens
humanThe menu: press 1 to confirm, or 2 for the attendance office.
Starts with machineThe voicemail message, then the call ends.
faxThe call ends.
unknownThe 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

References to Ferris Bueller’s Day Off in the call flow
Where Reference
The callerEdward Rooney, Dean of Students.
The voicemailNine 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>’s action at 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

Trusted by