CTRLK

Shared components

Calls Markup Language

|

View as Markdown

Calls Markup Language (Calls ML or CML) is a voice feature designed for developers and available through the API only. You can use Calls ML to create any application to handle inbound and outbound calls. Your application implements the voice scenario logic and uses the Calls Markup Language to control and run actions in calls and conferences.

Differences between Calls API and Calls Markup Language

The event-driven model of Calls API relies on a continuous, real-time conversational loop between the voice platform and the developer's back end. For each discrete occurrence during a call, the platform dispatches an asynchronous webhook event. These events include a call being answered, a DTMF key being pressed, or an audio file finishing playback. The developer's server must then process this event and issue a corresponding API request to dictate the next action.

In contrast, Calls ML simplifies this interaction by using a declarative document (JSON) containing a sequential set of instructions (for example, speak text, record audio, dial a number). Instead of a continuous back-and-forth for each micro-action, the voice platform requests this instruction sheet at important execution milestones. It then parses and runs the specified sequence autonomously without needing constant round-trips to the developer's back end.

These two methods optimize for different developer experiences and technical scenarios:

  • Event-driven method with Calls API: Best suited for highly dynamic, complex, and stateful applications. It offers maximum flexibility and granular, real-time control over the call session. This makes it the ideal choice for solutions such as advanced contact centers (CCaaS), live agent routing, real-time AI voice assistants, or workflows that require repeated mid-call database lookups and state mutations. The tradeoff is a higher developer overhead, as the back end must maintain call state and handle high volumes of asynchronous webhooks.
  • Markup language method with Calls Markup Language: Optimizes for developer velocity, simplicity, and low latency. By abstracting the underlying state machine into a lightweight, readable script, it provides a highly deterministic and low-boilerplate developer experience. This is ideal for linear or standard call flows, such as basic interactive voice response (IVR) menus, automated phone alerts, simple anonymous call forwarding, or voicemail dropping. It reduces server infrastructure requirements and accelerates time-to-market for mainstream voice applications.

CML actions

The Calls Markup Language is composed of individual actions that give instructions to the Infobip voice platform. The following table lists the actions available through Calls Markup Language.

ActionDescription
playPlay an audio file from a URL.
sayPlay text-to-speech content.
captureDtmfCollect digits with an optional barge-in prompt.
dialBridge to a phone, SIP, WebRTC, Viber, or WhatsApp endpoint.
recordRecord the call leg.
startRecording / stopRecordingFine-grained recording control.
pauseWait a specified number of seconds.
fetchLoad the next CML script from a URL.
hangupEnd the call.
NOTE

More actions are planned, including support for conferencing, streaming, speech capture, and call real-time transcription.

For the complete reference to all Calls Markup Language actions, see the API documentation.

Create an outbound call with CML

To start an outbound call driven by CML, send a request to the /markuplanguage/1/create endpoint with the call details and the URLs that Infobip uses during the call.

json
1POST /markuplanguage/1/create HTTP/1.1
2Host: {INFOBIP_BASE_URL}
3Authorization: App {INFOBIP_API_KEY}
4Content-Type: application/json
5 
6{
7 "callback": {
8 "url": "https://example.com/cml/answer",
9 "errorUrl": "https://example.com/cml/error",
10 "method": "POST"
11 },
12 "endpoint": {
13 "type": "PHONE",
14 "phoneNumber": "441234567890"
15 },
16 "notifyUrl": "https://example.com/cml/notify",
17 "from": "442012345678"
18}

The request body includes the following fields:

  • callback.url: URL of the webhook that serves the first set of markup language instructions when a call is answered.
  • callback.errorUrl: URL invoked when the url is unreachable. A failover script is expected in response.
  • callback.method: HTTP method (GET or POST) to communicate with your webhooks.
  • notifyUrl: URL of the webhook where Infobip sends a post-call notification with a summary of the call.

After you submit the request:

  1. Infobip calls the defined endpoint.
  2. When the destination endpoint answers the call, Infobip notifies your callback url with the context of the outbound call and expects a set of CML actions in return.

If the callback url is unreachable or returns a malformed CML script, the Infobip platform sends an error notification to the errorUrl, which can reply with a new set of CML actions.

Answer an inbound call with CML

Before serving any inbound call, declare in a configuration object where Infobip retrieves the first set of markup language instructions when receiving a call on your voice number. You can create and manage Calls Markup Language configurations with the API or using the Infobip portal.

The configuration includes the following fields:

  • markupUrl: URL of the webhook that serves the first set of markup language instructions when a call is received.
  • errorUrl: URL invoked when the markupUrl is unreachable or the returned CML from the markupUrl is invalid. A failover script is expected in response.
  • notifyUrl: URL of the webhook where Infobip sends a post-call notification with a summary of the call.
  • httpMethod: HTTP method used for all the callbacks in this list. Can be POST or GET.

After your CML configuration is declared, associate it with your voice number. To link an Infobip DID number to a CML configuration, set up a voice action on your DID number:

  • API: Create a voice setup on your Infobip number with the action type VOICE_FORWARD_TO_MARKUP_LANGUAGE and include your CML configurationId.
  • Web interface:
    1. Go to the Numbers application and select your number.
    2. Select the Voice tab.
    3. Create an inbound configuration where the Forward action is Forward to Markup Language and select the CML configuration to use.

Package multiple CML actions in a script

CML actions provided by your callback webhooks must be included in a script object, whether the script contains a single action or multiple actions. A script object is a JSON array of CML instructions.

The following example CML script plays text-to-speech content, plays an audio file, then hangs up the call.

json
1{
2 "script": [
3 {
4 "action": "say",
5 "text": "Hello! This is Smile Dental calling to remind you of your appointment tomorrow at 10 AM.",
6 "language": "en",
7 "voicePreferences": { "voiceGender": "FEMALE", "voiceName": "Joanna" }
8 },
9 {
10 "action": "play",
11 "content": {
12 "type": "URL",
13 "fileUrl": "https://example.com/content/generic.mp3"
14 }
15 },
16 { "action": "hangup" }
17 ]
18}

Execution flow and control transfer

Actions in a markup script run in sequence, but some actions (fetch, captureDtmf, dial) can transfer control to a new markup script. This causes any subsequent actions defined in the initial script to be skipped.

In the following example, the second say action is never executed because the fetch action transfers control to a new script.

json
1{
2 "script": [
3 {
4 "action": "say",
5 "text": "Hello! This is Smile Dental calling to remind you of your appointment tomorrow at 10 AM.",
6 "language": "en",
7 "voicePreferences": {
8 "voiceGender": "FEMALE",
9 "voiceName": "Joanna"
10 }
11 },
12 {
13 "action": "fetch",
14 "url": "https://example.com/cml/next",
15 "method": "POST"
16 },
17 {
18 "action": "say",
19 "text": "Thank you for your call.",
20 "language": "en",
21 "voicePreferences": {
22 "voiceGender": "FEMALE",
23 "voiceName": "Joanna"
24 }
25 }
26 ]
27}

If the fetch action fails (webhook not available or malformed CML script returned), the Infobip platform sends the error to your errorUrl (on the CML configuration or as defined in the action). If the errorUrl does not return a correct CML script, the call is hung up.

DTMF capture exception

The captureDtmf action is an exception to the control transfer behavior. Consider the following script:

json
1{
2 "script": [
3 {
4 "action": "say",
5 "text": "Hello! This is Smile Dental calling to remind you of your appointment tomorrow at 10 AM.",
6 "language": "en",
7 "voicePreferences": {
8 "voiceGender": "FEMALE",
9 "voiceName": "Joanna"
10 }
11 },
12 {
13 "action": "captureDtmf",
14 "maxLength": 1,
15 "timeout": 6,
16 "terminator": "#",
17 "callback": {
18 "url": "https://example.com/cml/dtmf",
19 "method": "POST"
20 },
21 "say": {
22 "action": "say",
23 "text": "Press 1 to confirm, 2 to reschedule, or 9 to talk to a receptionist.",
24 "language": "en"
25 }
26 },
27 {
28 "action": "hangup"
29 }
30 ]
31}

If the end user does not respond to the DTMF prompt during the defined timeout period and the captureDtmf action does not use the callOnEmpty flag, then the next action in the script runs (in this case, hangup).