Applications & VoyloML

An Application is call-control logic you attach to a number. When a call comes in, Voylo runs your VoyloML — a Twilio/Plivo-style XML language — on the call: play audio, gather input, dial agents or PSTN numbers, record, conference, and more. Two ways to provide it:

1. Static XML

Store a fixed document on the Application. Same response every call. Good for simple, deterministic flows.

<Response>
  <Gather numDigits="1" timeout="6" action="https://you.example/ivr">
    <Play>https://cdn.example.com/prompts/menu.wav</Play>
  </Gather>
  <Play>https://cdn.example.com/prompts/no-input.wav</Play>
  <Hangup/>
</Response>

2. Dynamic (webhook)

Point Voylo at your URL. On each call (and each action callback) Voylo POSTs the call state and runs the VoyloML you return. This is the loop that lets your backend drive the call in real time.

The request

application/x-www-form-urlencoded, expecting an XML body back. Always included: CallSid From To Direction CallStatus. Verb-specific params arrive on that verb's action: Digits/SpeechResult (Gather), RecordingUrl (Record), DialStatus/AnsweredBy (Dial).

Example: dynamic IVR (Express)

import express from "express";

const app = express();
app.use(express.urlencoded({ extended: false }));

app.post("/voice", (req, res) => {
  res.type("application/xml").send(`
    <Response>
      <Gather numDigits="1" action="/voice/menu">
        <Play>https://cdn.example.com/prompts/welcome.wav</Play>
      </Gather>
    </Response>`);
});

app.post("/voice/menu", (req, res) => {
  const xml = req.body.Digits === "1"
    ? `<Response><Dial>sip:agent@sip.elevenlabs.io</Dial></Response>`
    : `<Response>
         <Play>https://cdn.example.com/prompts/billing.wav</Play>
         <Dial>+97142345678</Dial>
       </Response>`;
  res.type("application/xml").send(xml);
});

Recipes

Ring multiple numbers

<Dial action="/after" timeout="25">
  <Number>+97150xxxxxxx</Number>
  <Number sendDigits="wwww1">+2010xxxxxxx</Number>  <!-- both ring; first to answer wins -->
</Dial>

Conference

<Conference maxMembers="20" record="true" waitSound="https://cdn/hold.mp3">sales-room</Conference>

Voicemail with a beep

<Play>https://cdn.example.com/prompts/leave-message.wav</Play>
<Record action="/voicemail" maxLength="120" playBeep="true"/>

Building & validating

Validate documents against POST /v1/voyloml/validatebefore you ship, or let the console's Application editor validate them live as you type.

Full per-verb attribute reference: VoyloML reference →