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">
<Say>Press 1 for sales, 2 for support.</Say>
</Gather>
<Say>We didn't get that. Goodbye.</Say>
<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";
import { VoyloResponse } from "@voylo/sdk";
const app = express();
app.use(express.urlencoded({ extended: false }));
app.post("/voice", (req, res) => {
const r = new VoyloResponse();
const g = r.gather({ numDigits: 1, action: "/voice/menu" });
g.say("Welcome. Press 1 for our AI agent, 2 for billing.");
res.type("application/xml").send(r.toString());
});
app.post("/voice/menu", (req, res) => {
const r = new VoyloResponse();
if (req.body.Digits === "1") r.dial("sip:agent@sip.elevenlabs.io");
else r.say("Connecting you to billing.").dial("+97142345678");
res.type("application/xml").send(r.toString());
});Recipes
Ring multiple numbers + screening
<Dial action="/after" timeout="25" confirmSound="https://cdn/accept.wav"> <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
<Say>Please leave a message after the tone.</Say> <Record action="/voicemail" maxLength="120" playBeep="true"/>
Building & validating
Use the Node or Python SDK to build documents (they always produce valid XML), or validate by hand against POST /v1/voyloml/validate. The console's Application editor validates live.
Full per-verb attribute reference: VoyloML reference →