VoiceXML is still the open standard behind many enterprise IVRs, and it is still a sound choice when your team wants full control in code. A low-code visual builder is faster for common call flows and lets non-developers make changes. This guide explains what VoiceXML is today, shows a short annotated example, and gives you a simple way to decide which approach fits each IVR project.
What is VoiceXML and is it still used?
VoiceXML (VXML) is a W3C markup language for building phone applications that speak prompts, collect keypad (DTMF) or speech input, and route calls. It is still used: the current versions are VoiceXML 2.0 and VoiceXML 2.1, which W3C published as a Recommendation on 19 June 2007 and designed to be fully backwards-compatible with 2.0.
VoiceXML works like the web, but for the phone. A voice browser on the IVR platform fetches a VXML document over HTTP, plays prompts with text-to-speech or recorded audio, listens for input, and follows the next link. Your application server can be written in any language, because its only job is to return valid VoiceXML.
That design is why VXML has lasted. Business logic stays in your own web stack, the call-handling layer follows a published standard, and a well-written application can move between compliant platforms with less rework than a proprietary one.
What does a simple VoiceXML menu look like?
A basic menu needs a prompt, the choices a caller can make, and handlers for silence and unrecognized input. The example below uses the <menu> and <choice> elements from VoiceXML 2.x.
<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml">
<!-- 1. A menu is shorthand for a form with one field and a set of choices -->
<menu id="main">
<prompt>
For billing, press 1 or say billing.
For technical support, press 2 or say support.
</prompt>
<!-- 2. Each choice maps a key press and a spoken phrase to a destination -->
<choice dtmf="1" next="#billing">billing</choice>
<choice dtmf="2" next="#support">support</choice>
<!-- 3. Handle silence and unrecognized input, then replay the prompt -->
<noinput>Sorry, I didn't hear you. <reprompt/></noinput>
<nomatch>Sorry, I didn't catch that. <reprompt/></nomatch>
</menu>
<!-- 4. Each destination is a dialog in the same document -->
<form id="billing">
<block>
<prompt>Connecting you to billing.</prompt>
<goto next="billing.vxml"/>
</block>
</form>
<form id="support">
<block>
<prompt>Connecting you to support.</prompt>
<goto next="support.vxml"/>
</block>
</form>
</vxml>
Here is what each part does:
<menu>presents choices. The Plum DEV<menu>reference describes it as shorthand for a form with a single field that transitions based on the caller's choice.<choice>links a DTMF key (dtmf="1") and the spoken text inside the tag ("billing") to a target (next="#billing"). The platform builds the speech grammar from that text.<noinput>and<nomatch>catch silence and invalid input.<reprompt/>plays the menu prompt again, so callers get another try instead of a dead end.<form>and<block>hold the next step. In production,billing.vxmlwould usually be a URL on your application server that returns the next document, often with data from your CRM or billing system.
In real projects, developers rarely write static files like this. A PHP, Python, C# or Node service generates the VXML on each request, inserting account data, choosing prompts, and logging events. The Plum DEV tutorial walks through that pattern step by step.
What is low-code IVR?
Low-code IVR means building call flows on a visual canvas: you drag modules such as Menu, Prompt, Input and Transfer onto a workspace and connect them to set the path a call follows. The builder handles the underlying markup, hosting and versioning for you.
The same menu above takes a few minutes in a visual builder. You add a Menu module, type the prompt, add one row per option, and connect each row to its next step. Speech input is usually a setting on the module rather than a grammar you write.
Low-code tools also ship with templates for common jobs such as payments, account balance and appointment reminders, so teams start from a working flow instead of a blank file.
Code vs low-code: how do they compare?
Use code when you need full control or have complex logic. Use low-code when speed, templates and changes by non-developers matter more. Most enterprises end up using both.
| Factor | Code (VoiceXML) | Low-code visual builder |
|---|---|---|
| Who builds and maintains it | Developers who know XML, HTTP and a server-side language | CX, operations or IT staff, with developers for integrations |
| Speed to first working flow | Slower; you write prompts, grammars and error handling | Faster; drag modules or start from a template |
| Flexibility | Anything the standard and your server code allow | Limited to available modules, plus scripting where supported |
| Complex logic and integrations | Natural fit; logic lives in your own code | Handled through built-in connectors or webhooks |
| Making routine changes | Code change, review and deploy | Edit the flow and publish a new revision |
| Version control and testing | Your existing Git, CI and code review process | The builder's revision history and test deployments |
| Portability | High, because VXML is an open W3C standard | Usually tied to the vendor's builder |
| Best for | Custom, high-complexity or regulated apps; existing VXML estates | Standard self-service flows and teams that change prompts often |
When should you code your IVR?
Code your IVR when the call flow is a core product, the logic is complex, or you already have VoiceXML applications. Specific signs:
- You have existing VXML. Porting working code to a compliant platform is usually faster than rebuilding it.
- Logic is heavy. Multi-step authentication, dynamic menus per caller, or many back-end calls are easier to express and test in code.
- You need your engineering workflow. Code review, automated tests and CI/CD apply directly to the services that generate your VXML.
- Portability matters. An open standard reduces lock-in if you change platforms later.
When should you go low-code?
Go low-code when the flow follows a common pattern, the people closest to the caller need to change it, or you need to launch quickly. Typical cases include payment collection, balance inquiries, card activation, outbound reminders and post-call surveys.
A useful test comes from a 2021 Plum Voice post on the build vs buy decision: if commercial software already covers about 60% or more of your requirements, buying usually beats building. Apply the same thinking to each flow. If a template covers most of it, start there and code only the gaps.
Can you combine code and low-code?
Yes, and for most teams that is the best answer. Business teams own the routine flows in a visual builder, and developers write code for the parts that need it, such as a custom authentication step or a complex integration. The key is a platform where both live together, so you do not run two separate IVR systems.
A practical split looks like this:
- Map every flow and mark which parts are standard and which are custom.
- Build standard flows from templates in the visual builder.
- Write the custom steps in code and call them from the visual flow.
- Give each team ownership of its part, with shared testing before release.
How Plum Voice handles this
Plum Voice offers both paths on one platform. Plum DEV is a VoiceXML platform where developers generate VXML from the language of their choice, such as PHP, Python, C# or Node, and test it in scratchpads with a built-in validator. Plum Fuse is a drag-and-drop, low-code builder with 37+ prebuilt templates, including Payment Processing, Account Inquiry and Card Activation. Fuse users can drop into DEV for complex scripts, so a single application can mix both.
To plan the flow itself before you build, see our guide to IVR call flow design best practices. To check it before launch, read how to test and monitor an IVR.