Custom code (TwiML)

Overview

A custom code extension hands the call to a web address of your own. We fetch that address, and whatever TwiML it returns is what the caller hears next. When your code is finished the call comes back and continues where you tell it to.

This is the escape hatch for developers. Everything a normal hotline needs is already a building block, so reach for this only when you need behavior the built-in extensions do not cover, such as answers that depend on live data from your own system.

In the sidebar it lives under Advanced, listed as Twimls. Everywhere a destination is picked, and on My Hotline, it is called Custom code.


How It Works

  1. The caller reaches the custom code extension.
  2. We send the call to your TwiML URL with a GET request. The call really moves there; we do not proxy it.
  3. Your server answers with TwiML, and the caller hears whatever it says.
  4. When your TwiML sends the call back to us, the Afterwards route decides where the caller goes next.

Your code is responsible for the caller from the moment we hand the call over. If your address is unreachable or returns something that is not valid TwiML, the call stops there.


Settings


Routing

Route When it fires
Afterwards Your TwiML finishes and sends the call back to us

Set it on the form, or from the extension's ⚙ settings on My Hotline. Point it at your main menu so callers land somewhere sensible when your code is done. Leave it empty and the call ends there.


Code in the hotline (a TwiML bin)

You do not need a server. Choose In the hotline as the source and paste the TwiML into the editor. The hotline keeps it, fills in the values of each call, and runs it. The call never leaves the hotline, so the call trace keeps recording.

<Response>
{{#if From == 18455551234}}
  <Say>Welcome back, {{caller_name}}.</Say>
  <Dial><Number>18455550000</Number></Dial>
{{#elseif Digits == 1}}
  <Redirect>{{return_url}}</Redirect>
{{#else}}
  <Gather action="{{self_url}}" numDigits="1">
    <Say>Press 1 to continue on the hotline.</Say>
  </Gather>
{{/if}}
</Response>

Variables

Variable Meaning
{{From}} / {{To}} The caller's number and the number they dialed, digits only
{{Digits}} What the caller pressed in a <Gather> whose action is {{self_url}}
{{CallSid}} The call id
{{caller_name}} / {{contact_labels}} Filled when the number matches one of your contacts
{{hotline_name}} The name of your hotline
{{return_url}} Continue with this extension's Afterwards route
{{self_url}} Run this code again, which is how a <Gather> reports its digits back to it

Values are escaped for XML, so a contact name with special characters cannot break the code.

Conditions

{{#if …}}, {{#elseif …}}, {{#else}} and {{/if}}, nested as you need. Compare with ==, !=, contains, starts_with and ends_with, combine with and, or, not and parentheses. Values with spaces go in quotes. Phone numbers compare loosely, so From == "+1 (845) 555-1234" and From == 18455551234 both match a caller shown as 18455551234. The syntax is the one Telnyx TeXML uses, so their examples run unchanged.

The editor checks the code when you save: it must render, be valid XML with a <Response> root, and use only these verbs: Play, Say, Gather, Record, Dial, Pause, Redirect, Pay, Conference, Hangup. A mistake is reported with the line, never discovered by a caller.

Coming back into the hotline

Your TwiML can hand the call back whenever it likes with a <Redirect> to the extension's return link, shown on the extension's page as Link for custom code. Every extension has such a link, so you can send the call to a specific menu, audio player or message box, not only back to where it came from:

<Response>
  <Say>Thanks, back to the hotline.</Say>
  <Redirect>https://hotlines.callmagic.app/public/go/5f1c…</Redirect>
</Response>

What the call trace shows

The call trace records every step the hotline handles. The moment the call is handed to your code it logs "custom code" with your host name, and everything up to that point is saved at once. What your code does afterwards is not traced, since those requests go to your server. If your code sends the call back through a return link, the trace continues from there with "entered via link".

What it costs

A custom code extension is a $20 a month add-on, one per extension, bought under Advanced options on the Plans & Add-ons page. The base plans include no advanced options, so buy one for each custom code extension you need. See Billing.


Writing the TwiML

Most standard Twilio TwiML verbs work. The platform also understands a handful of non-standard attributes, mainly for conferences and for interactive playback. They are all listed in Custom TwiML.

If you are building something that reads or changes the hotline itself rather than handling a single call, the Hotline API is usually the better tool.


Tips