# Controlling Calls (SVAML v2)

SVAML (Sinch Voice API Markup Language) v2 is a powerful command language for controlling call flows. It consists of a list of commands sent to the API to manage calls, either as part of call setup or dynamically during a call.

### Command Structure

- SVAML commands are sent as a JSON array of objects, each representing an action to be performed on the call.
- Each command has a type (e.g., `dial`, `message`, etc.) and may include parameters specific to it as well as related event handlers.
- Commands can be nested or chained, allowing for complex call flows (e.g., gather input, then play audio, then dial out).
- Commands can be sent as part of the initial call setup or in response to events (e.g., call answered).


A SVAML command has the following basic structure:

```json
{
  "command": "command_type",
  "parameter1": "command_specific_parameter_value",
  "parameter2": "command_specific_parameter_value",
  "events": [
    {
      "on_event_name": [
        {
          "command": "another_command_type",
          "parameter": "another_value"
        }
      ]
    }
  ]
}
```

## Common Command Types

```json Payload application/json
{
  "commands": [
    {
      "command": "dial",
      "callName": "origin",
      "from": {
        "type": "PHONE",
        "phone": {
          "number": "+15551234567"
        }
      },
      "to": {
        "type": "PHONE",
        "phone": {
          "number": "+15559876543"
        }
      },
      "dialTimeoutDurationSeconds": 30,
      "maxCallDurationSeconds": 3600,
      "events": {
        "onAnswer": [
          {
            "command": "messages",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Hello, your call is now connected.",
                  "voiceName": "Emma"
                }
              }
            ]
          }
        ],
        "onHangup": [
          {
            "command": "hangup"
          }
        ]
      }
    }
  ]
}
```

```json
{
  "$ref": "#/components/schemas/svamlCommands",
  "components": {
    "schemas": {
      "svamlCommands": {
        "type": "array",
        "title": "SVAML Commands",
        "description": "An ordered list of SVAML v2 (Sinch Voice Application Markup Language) commands that describe a call flow. Commands are executed sequentially in the order they are defined.\n\n**Blocking vs. non-blocking:** Some commands block execution until they complete (`pause`, `webhook`, `menu`, `gotoMenu`), while others return immediately and run in parallel (`dial`, `messages`, `amd`, `answer`, `hangup`, `startRecording`, `stopRecording`, `bridgeCall`, `stopMessages`). Each command's description specifies its behavior.\n\n**Nesting scope:** Commands that appear inside event handlers (e.g., `dial.events.onAnswer`, `messages.events.onFinish`) form independent sequences and execute in their own context — they are not continuations of the parent sequence.",
        "items": {
          "$ref": "#/components/schemas/svamlCommand"
        }
      },
      "amdEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "AMD Events",
        "description": "SVAML commands to execute based on the answering machine detection result. These events define different call flows depending on whether a human, machine, beep, or unknown entity answers the call.",
        "properties": {
          "onHuman": {
            "description": "SVAML commands to be executed when a human is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onMachine": {
            "description": "SVAML commands to be executed when a machine is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBeep": {
            "description": "SVAML commands to be executed when a beep is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onUnknown": {
            "description": "SVAML commands to be executed when an unknown event is detected",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "amd": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answering Machine Detection",
        "description": "AMD (Answering Machine Detection) command to detect what answered the call. Possible outcomes are: human, machine, beep, or unknown.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while detection runs in parallel. Results are delivered via the `events` property.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "amd",
            "description": "Command to run Answering Machine Detection on the call"
          },
          "events": {
            "$ref": "#/components/schemas/amdEvents"
          }
        },
        "examples": [
          {
            "command": "amd",
            "events": {
              "onHuman": [
                {
                  "command": "pause",
                  "durationMilliseconds": 1000
                },
                {
                  "command": "bridgeCall",
                  "bridgeName": "my-bridge"
                }
              ],
              "onBeep": [
                {
                  "command": "messages",
                  "messagesName": "my-amd-messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Hello, this is a test message",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "phoneNumber": {
        "title": "Phone Number",
        "type": "string",
        "pattern": "^\\+[1-9]\\d{1,14}$",
        "minLength": 3,
        "maxLength": 16,
        "description": "E.164 Phone number",
        "examples": [
          "+4673522488"
        ]
      },
      "phone": {
        "type": "object",
        "additionalProperties": false,
        "title": "Phone",
        "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN).",
        "required": [
          "type",
          "phone"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PHONE",
            "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN). The number must be in E.164 format."
          },
          "phone": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "number"
            ],
            "properties": {
              "number": {
                "$ref": "#/components/schemas/phoneNumber"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PHONE",
            "phone": {
              "number": "+4673522488"
            }
          }
        ]
      },
      "sipFrom": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Origin",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Indicates the call originated from a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the originating endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "pattern": "^sips?:",
                "maxLength": 192
              },
              "displayName": {
                "type": "string",
                "description": "Display name presented to the called party as the caller identity. Transmitted as the display name part of the SIP `From` header (for example, `Alice <sip:alice@example.com>`).",
                "maxLength": 64,
                "example": "Alice"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "displayName": "Alice"
            }
          }
        ]
      },
      "from": {
        "description": "Call origin - Phone Number or SIP endpoint",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sipFrom"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sipFrom"
          }
        }
      },
      "sipCallHeaders": {
        "type": "array",
        "description": "Custom SIP headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[-A-Za-z0-9.!%*_+`'~]+$",
              "description": "Name of the SIP header.",
              "example": "X-Correlation-Id"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "description": "Value of the SIP header.",
              "example": "12345"
            }
          }
        },
        "examples": [
          [
            {
              "key": "X-Correlation-Id",
              "value": "12345"
            },
            {
              "key": "X-Call-Routing",
              "value": "forwarded"
            }
          ]
        ]
      },
      "sip": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Endpoint",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Routes the call to a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the destination endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "maxLength": 256,
                "pattern": "^sips?:"
              },
              "transport": {
                "type": "string",
                "description": "Transport protocol to use for the SIP signalling channel.\n\nIf omitted, the platform selects a default based on the URI scheme: `UDP` for `sip:` and `TLS` for `sips:`. Setting this explicitly overrides that default — for example, to force `TCP` for a `sip:` URI or to use `TLS` without switching to the `sips:` scheme.",
                "enum": [
                  "UDP",
                  "TCP",
                  "TLS"
                ],
                "x-enumDescriptions": {
                  "UDP": "Connectionless transport. Lowest overhead; suitable for most standard SIP deployments.",
                  "TCP": "Connection-oriented transport. More reliable for large SIP messages or NAT traversal scenarios.",
                  "TLS": "Encrypted transport. Provides confidentiality and integrity for SIP signalling."
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/sipCallHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "transport": "TCP",
              "callHeaders": [
                {
                  "key": "X-Correlation-Id",
                  "value": "12345"
                },
                {
                  "key": "X-Call-Routing",
                  "value": "forwarded"
                }
              ]
            }
          }
        ]
      },
      "callHeaders": {
        "type": "array",
        "description": "Custom headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]+$",
              "description": "Name of the header.",
              "example": "headerKey"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]*$",
              "description": "Value of the header.",
              "example": "headerValue"
            }
          }
        },
        "examples": [
          [
            {
              "key": "headerKey",
              "value": "headerValue"
            },
            {
              "key": "anotherKey",
              "value": "anotherValue"
            }
          ]
        ]
      },
      "stream": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stream",
        "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing.",
        "required": [
          "type",
          "stream"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "STREAM",
            "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing."
          },
          "stream": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "WebSocket endpoint that will accept the incoming connection for real-time audio streaming. Must be a valid WebSocket URL using either `ws://` or `wss://` (recommended). The URL must be reachable from the public internet and capable of handling the negotiated stream protocol.",
                "example": "wss://example.com"
              },
              "streamOptions": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "description": "Defines the version of the stream protocol.",
                    "default": 1,
                    "example": 1
                  },
                  "codec": {
                    "type": "string",
                    "const": "PCM",
                    "description": "Defines the audio codec/format used for the stream audio payload.\n\nCurrently, only `PCM` is supported (uncompressed raw audio). Use `sampleRate` to configure the sampling rate for the stream."
                  },
                  "sampleRate": {
                    "type": "integer",
                    "description": "Defines the audio sampling rate (Hz) used for the stream.\n\nFor calls that traverse the PSTN, audio is typically sampled at 8 kHz, so using a higher value will not improve perceived quality. \nHigher sample rates can be useful for non-PSTN scenarios (for example, SIP/streaming paths), but will increase bandwidth usage and processing load.",
                    "enum": [
                      8000,
                      16000,
                      24000,
                      44100,
                      48000,
                      96000
                    ],
                    "x-enumDescriptions": {
                      "8000": "8 kHz (standard for PSTN calls)",
                      "16000": "16 kHz (wideband audio)",
                      "24000": "24 kHz (super-wideband audio)",
                      "44100": "44.1 kHz (CD quality audio)",
                      "48000": "48 kHz (professional audio quality)",
                      "96000": "96 kHz (high-resolution audio)"
                    },
                    "default": 8000,
                    "example": 16000
                  }
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            },
            "examples": [
              {
                "endpoint": "wss://example.com",
                "streamOptions": {
                  "version": 1,
                  "codec": "PCM",
                  "sampleRate": 8000
                },
                "callHeaders": [
                  {
                    "key": "my-key",
                    "value": "my-key-value"
                  }
                ]
              }
            ]
          }
        },
        "examples": [
          {
            "type": "STREAM",
            "stream": {
              "endpoint": "wss://example.com",
              "streamOptions": {
                "version": 1,
                "codec": "PCM",
                "sampleRate": 16000
              },
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "voiceRelay": {
        "type": "object",
        "additionalProperties": false,
        "title": "Voice Relay",
        "description": "Routes the call through the Voice Relay service, enabling real-time speech-to-text (STT) and text-to-speech (TTS) via a WebSocket connection to the application backend.",
        "required": [
          "type",
          "voiceRelay"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "VOICE_RELAY",
            "description": "Connects to the Voice Relay service to enable STT and TTS services..."
          },
          "voiceRelay": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint",
              "ttsVoice",
              "sttLanguage"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "format": "uri",
                "description": "URL to the server that will accept the web-socket request",
                "example": "wss://acme.com/agent"
              },
              "enableInterruptions": {
                "type": "boolean",
                "description": "Allow \"barge-in\" during text-to-speech (TTS) playback.\n\nWhen `true`, TTS playback is interrupted as soon as inbound speech is detected, unless the currently playing content is marked as uninterruptible.\n\nWhen `false`, TTS playback continues uninterrupted, but an interruption signal is still sent over the WebSocket so the client application can choose to stop playback manually if needed.",
                "default": true,
                "example": true
              },
              "ttsVoice": {
                "type": "string",
                "description": "Name of the voice to be used when synthesizing speech. \n\nThis is the default voice used, if no override voice is provided in the web-socket TTS message.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              },
              "sttLanguage": {
                "type": "string",
                "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$",
                "description": "BCP-47 language tag used for speech-to-text transcription of the inbound audio.\n\nThis value determines which language model is used for transcription.",
                "example": "en-US"
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "VOICE_RELAY",
            "voiceRelay": {
              "endpoint": "wss://acme.com/agent",
              "enableInterruptions": true,
              "ttsVoice": "Emma",
              "sttLanguage": "en-US",
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "to": {
        "title": "To",
        "description": "Call destination - Phone Number or Stream URI",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sip"
          },
          {
            "$ref": "#/components/schemas/stream"
          },
          {
            "$ref": "#/components/schemas/voiceRelay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sip",
            "STREAM": "#/components/schemas/stream",
            "VOICE_RELAY": "#/components/schemas/voiceRelay"
          }
        }
      },
      "callEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Call Events Webhook",
        "description": "Webhook to handle call events, used when callBehaviors are set to WEBHOOK",
        "properties": {
          "onAnswer": {
            "description": "SVAML commands to be executed when the call is answered",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBusy": {
            "description": "SVAML commands to be executed when the call is busy",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onReject": {
            "description": "SVAML commands to be executed when the call is rejected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onTimeout": {
            "description": "SVAML commands to be executed when the call is timed out",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onHangup": {
            "description": "SVAML commands to be executed when the call is hung up",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "SVAML commands to be executed when the call fails",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "dial": {
        "type": "object",
        "additionalProperties": false,
        "title": "Dial",
        "description": "Initiates a new outbound call leg within the current session.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while the call is being established in parallel. Call lifecycle events (answer, busy, reject, timeout, hangup, failure) are handled via the `events` property.\n\nThe `from` and `to` endpoint types should ideally match. If they differ, the platform attempts to convert the `from` value to be compatible with the `to` type. For example, PSTN supports only E.164 phone numbers, so a SIP address such as `sip:46701234567@acme.se` can be converted to an E.164 number. If the `from` value cannot be converted, it defaults to null (anonymous).",
        "required": [
          "command",
          "to"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "dial",
            "description": "Command to initiate a new call"
          },
          "callName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "outgoing",
            "description": "Identifier for this call leg within the session. Must be unique across all active call legs in the session.\n\nOther commands (e.g., `hangup`) can reference this name to target this specific leg."
          },
          "from": {
            "$ref": "#/components/schemas/from"
          },
          "to": {
            "$ref": "#/components/schemas/to"
          },
          "dialTimeoutDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "description": "Maximum time in seconds to wait for the call to be answered. If the timeout expires without an answer, the `onTimeout` event is triggered.",
            "example": 15
          },
          "maxCallDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 14400,
            "description": "Maximum duration of the call in seconds. The call is terminated automatically when this limit is reached.",
            "example": 3600
          },
          "events": {
            "$ref": "#/components/schemas/callEvents"
          }
        },
        "examples": [
          {
            "command": "dial",
            "callName": "destination",
            "from": {
              "type": "PHONE",
              "phone": {
                "number": "+15551234567"
              }
            },
            "to": {
              "type": "PHONE",
              "phone": {
                "number": "+15559876543"
              }
            },
            "dialTimeoutDurationSeconds": 30,
            "maxCallDurationSeconds": 3600,
            "events": {
              "onAnswer": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Your call has connected.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "messageSay": {
        "type": "object",
        "title": "Say Message",
        "description": "A text-to-speech (TTS) message item. The platform synthesizes the provided text into speech and plays it on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "say"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SAY",
            "description": "Text-to-speech message to be played during the call."
          },
          "say": {
            "type": "object",
            "additionalProperties": false,
            "title": "Say",
            "required": [
              "text",
              "voiceName"
            ],
            "properties": {
              "text": {
                "type": "string",
                "description": "The text to be synthesized into speech.\n\nIf `format` is `TEXT` (default), provide plain text.\nIf `format` is `SSML`, provide a valid SSML document (for example, `<speak>...</speak>`).",
                "maxLength": 600,
                "example": "Hello world"
              },
              "format": {
                "type": "string",
                "description": "Format of the message",
                "enum": [
                  "TEXT",
                  "SSML"
                ],
                "x-enumDescriptions": {
                  "TEXT": "Plain text format for the message.",
                  "SSML": "Speech Synthesis Markup Language format for advanced text-to-speech control."
                },
                "default": "TEXT"
              },
              "voiceName": {
                "type": "string",
                "description": "The name of the voice to use for text-to-speech synthesis.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SAY",
            "say": {
              "text": "Hello, this is a test message",
              "voiceName": "Emma"
            }
          },
          {
            "type": "SAY",
            "say": {
              "text": "<speak><prosody volume=\"-6dB\">Hello, this is a test message</prosody></speak>",
              "format": "SSML",
              "voiceName": "Brian"
            }
          }
        ]
      },
      "messagePlay": {
        "type": "object",
        "title": "Play Message",
        "description": "An audio file playback message item. The platform fetches and plays the audio file at the provided URL on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "play"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PLAY",
            "description": "Audio file playback during the call."
          },
          "play": {
            "type": "object",
            "additionalProperties": false,
            "title": "Play",
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "description": "URL of the media to send"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PLAY",
            "play": {
              "url": "https://example.com/media.mp3"
            }
          }
        ]
      },
      "message": {
        "type": "object",
        "title": "Message",
        "description": "A single message item. The required payload depends on `type`.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/messageSay"
          },
          {
            "$ref": "#/components/schemas/messagePlay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "SAY": "#/components/schemas/messageSay",
            "PLAY": "#/components/schemas/messagePlay"
          }
        }
      },
      "typesOfMessages": {
        "type": "array",
        "title": "Message List",
        "description": "Ordered list of messages to play.",
        "minItems": 1,
        "maxItems": 10,
        "items": {
          "$ref": "#/components/schemas/message"
        }
      },
      "messageEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Message Events",
        "description": "SVAML commands to execute based on message playback outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when all messages in the sequence have finished playing.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "messages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Messages",
        "description": "Plays one or more messages on the call. Multiple messages in the array are played sequentially in order.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while messages play in parallel. \nPlayback outcomes are handled via the `events` property. The `onFinish` event can be used to run a command after all messages complete.",
        "required": [
          "command",
          "messages"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "messages",
            "description": "Command to play a message on the channel"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message for identification and reference within the call session.\n\nThis name is used to uniquely identify the message and must be unique within the current call session.\nThis name can be referenced in other commands (e.g., `stopMessages`) to control this specific message.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-messages"
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          },
          "events": {
            "$ref": "#/components/schemas/messageEvents"
          }
        },
        "examples": [
          {
            "command": "messages",
            "messagesName": "greeting-sequence",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Hello! Your call is being connected.",
                  "voiceName": "Emma"
                }
              },
              {
                "type": "PLAY",
                "play": {
                  "url": "https://example.com/audio/hold-music.mp3"
                }
              },
              {
                "type": "SAY",
                "say": {
                  "text": "<speak><prosody volume=\"-6dB\">Thank you for waiting.</prosody></speak>",
                  "format": "SSML",
                  "voiceName": "Emma"
                }
              }
            ]
          }
        ]
      },
      "stopMessages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Messages",
        "description": "Stops a message sequence previously started by a `messages` command. Use `messagesName` to target a specific sequence and `flags` to control whether only the current message or all queued messages are cancelled. \n\nThis is a non-blocking command.",
        "required": [
          "command",
          "messagesName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopMessages",
            "description": "Command to stop playing messages"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message sequence to stop, as set by `messagesName` in the `messages` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$"
          },
          "flags": {
            "type": "string",
            "description": "Controls how much of the sequence is stopped — only the currently playing message or all remaining queued messages.",
            "default": "ALL_FROM_NOW_ON",
            "enum": [
              "ONLY_PLAYING",
              "ALL_FROM_NOW_ON"
            ],
            "x-enumDescriptions": {
              "ONLY_PLAYING": "Stops only the currently playing message. Queued messages will continue to play.",
              "ALL_FROM_NOW_ON": "Stops the currently playing message and cancels all queued messages."
            }
          }
        },
        "examples": [
          {
            "command": "stopMessages",
            "messagesName": "my-messages",
            "flags": "ONLY_PLAYING"
          }
        ]
      },
      "webhookFallbackUrl": {
        "title": "Webhook Fallback URL",
        "type": "string",
        "format": "uri",
        "description": "Fallback webhook URL used when the primary webhook URL fails.\n\nA failed request is re-sent to this URL immediately. After repeated consecutive failures of the primary URL, requests are sent only here until the primary URL recovers.\n\nSee *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "examples": [
          "https://example.com/fallback"
        ]
      },
      "webhook": {
        "type": "object",
        "additionalProperties": false,
        "title": "Webhook",
        "description": "Triggers a mid-call webhook to the application backend, allowing it to return a new set of SVAML commands that control the remainder of the call flow.\n\nThis is a blocking command — execution pauses until a response is received from the webhook endpoint. The next command in the sequence runs only after the backend responds. Webhook requests use a 5-second timeout. If a `fallbackUrl` is provided, a failed request is re-sent to it — see *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "required": [
          "command",
          "webhookName",
          "url"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "webhook",
            "description": "Command to trigger a mid-call webhook"
          },
          "webhookName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^\\S+$",
            "description": "Name for this webhook event. When triggered, the webhook request's `event` property will contain this name prepended with `call.webhook.`.\n\nFor example, if `webhookName` is set to `\"my.custom.event\"`, the event will be delivered as `\"call.webhook.my.custom.event\"`."
          },
          "url": {
            "type": "string",
            "description": "URL of the webhook endpoint to send the mid-call event to.",
            "format": "uri"
          },
          "fallbackUrl": {
            "$ref": "#/components/schemas/webhookFallbackUrl"
          }
        },
        "examples": [
          {
            "command": "webhook",
            "webhookName": "my.custom.event",
            "url": "https://example.com/webhook",
            "fallbackUrl": "https://example.com/fallback"
          }
        ]
      },
      "hangup": {
        "type": "object",
        "additionalProperties": false,
        "description": "Ends a call leg. This is a non-blocking command — execution continues to the next command in the sequence even though the call has been ended. The `onHangup` event is triggered for the call leg that was ended.\n\nAny subsequent commands that target the ended call leg (such as `messages` or other media commands) are valid but will not be executed. Commands that operate independently — such as initiating a new call with `dial` — will execute normally. This makes it possible, for example, to end one call and immediately start another within the same sequence.",
        "title": "Hangup",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "hangup",
            "description": "Hangup call"
          },
          "callName": {
            "type": "string",
            "description": "Name of the call leg to end, as set by `callName` in the `dial` command.\n\nIf omitted, the current call leg is ended.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "origin"
          }
        },
        "examples": [
          {
            "command": "hangup",
            "callName": "origin"
          }
        ]
      },
      "answer": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answer",
        "description": "Answers an inbound call leg. This is a non-blocking command — execution continues to the next command in the sequence immediately after the answer is initiated.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "answer",
            "description": "Answer call"
          }
        },
        "examples": [
          {
            "command": "answer"
          }
        ]
      },
      "pause": {
        "type": "object",
        "additionalProperties": false,
        "title": "Pause",
        "description": "Delays execution of the next command in the sequence for a specified duration. This is a blocking command — no further commands execute until the pause completes.\n\nThe pause does not affect call audio; the call remains connected and audio continues uninterrupted.",
        "required": [
          "command",
          "durationMilliseconds"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "pause",
            "description": "Pause execution."
          },
          "durationMilliseconds": {
            "type": "integer",
            "minimum": 1,
            "description": "Duration of the pause in milliseconds.",
            "example": 1000
          }
        },
        "examples": [
          {
            "command": "pause",
            "durationMilliseconds": 1500
          }
        ]
      },
      "recordingFormat": {
        "title": "Recording Format",
        "description": "Audio format for this recording.",
        "type": "string",
        "enum": [
          "MP3",
          "WAV"
        ],
        "x-enumDescriptions": {
          "MP3": "MPEG Audio Layer III compressed audio format.",
          "WAV": "Waveform Audio File Format, uncompressed audio."
        },
        "default": "MP3",
        "examples": [
          "MP3"
        ]
      },
      "recordingType": {
        "title": "Recording Type",
        "description": "The type of recording to perform.",
        "type": "string",
        "enum": [
          "COMBINED",
          "INBOUND",
          "OUTBOUND"
        ],
        "x-enumDescriptions": {
          "COMBINED": "Record inbound and outbound voice streams.",
          "INBOUND": "Record inbound voice stream only.",
          "OUTBOUND": "Record outbound voice stream only."
        },
        "default": "COMBINED"
      },
      "recordingDestination": {
        "title": "Recording Destination",
        "type": "string",
        "description": "Select target service to receive recorded and transcribed files",
        "enum": [
          "AWS",
          "GCP",
          "AZURE"
        ],
        "x-enumDescriptions": {
          "AWS": "Store recordings in Amazon Web Services S3 bucket. Use `s3` as schema for the URL.",
          "GCP": "Store recordings in Google Cloud Platform Storage. Use `gs` as schema for the URL.",
          "AZURE": "Store recordings in Microsoft Azure Blob Storage.  Use `azure` as schema for the URL."
        },
        "default": "AWS",
        "examples": [
          "AWS"
        ]
      },
      "transcriptionOptions": {
        "title": "Transcription Options",
        "description": "Configuration for automatic speech-to-text transcription of the recording.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "isEnabled"
        ],
        "properties": {
          "isEnabled": {
            "type": "boolean",
            "description": "If true, the recording will be transcribed to text.",
            "example": true
          },
          "locale": {
            "type": "string",
            "description": "Language code in BCP-47 format.",
            "default": "en-US",
            "example": "en-US"
          }
        }
      },
      "recordingOptions": {
        "title": "Recording Options",
        "type": "object",
        "additionalProperties": false,
        "description": "Recording options for this recording.",
        "required": [
          "destination",
          "destinationUrl",
          "credentials"
        ],
        "properties": {
          "format": {
            "$ref": "#/components/schemas/recordingFormat"
          },
          "recordingType": {
            "$ref": "#/components/schemas/recordingType"
          },
          "destination": {
            "$ref": "#/components/schemas/recordingDestination"
          },
          "destinationUrl": {
            "type": "string",
            "description": "Destination URL for the recording.",
            "example": "s3://voice-recordings-prod/calls"
          },
          "credentials": {
            "type": "string",
            "description": "Credentials to third party storage.",
            "example": "accessKeyId:secretAccessKey:eu-central-1"
          },
          "transcriptionOptions": {
            "$ref": "#/components/schemas/transcriptionOptions"
          }
        }
      },
      "recordingEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Recording Events",
        "description": "SVAML commands to execute based on recording lifecycle outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when the recording is successfully stopped. Note that this does not mean that the file is delivered to the configured destination yet.\n",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "Commands to execute if the recording fails to start. If omitted, failures are silently ignored and the call flow continues.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "startRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Start Recording",
        "required": [
          "command",
          "recordingOptions"
        ],
        "description": "Starts recording the call. This is a non-blocking command — execution continues to the next command in the sequence immediately after recording begins.",
        "properties": {
          "command": {
            "type": "string",
            "const": "startRecording",
            "description": "Command to start recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Identifier for this recording within the session. Must be unique across active recordings in the session.\n\nOther commands (e.g., `stopRecording`) reference this name to target a specific recording.\n\nSetting the recording name is useful for stopping the recording using the `stopRecording` command. If name is not set, recording can only be stopped when the call is disconnected.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          },
          "recordingOptions": {
            "$ref": "#/components/schemas/recordingOptions"
          },
          "events": {
            "$ref": "#/components/schemas/recordingEvents"
          }
        },
        "examples": [
          {
            "command": "startRecording",
            "recordingName": "customer-support-recording",
            "recordingOptions": {
              "format": "MP3",
              "recordingType": "COMBINED",
              "destination": "AWS",
              "destinationUrl": "s3://voice-recordings-prod/calls",
              "credentials": "accessKeyId:secretAccessKey:eu-central-1",
              "transcriptionOptions": {
                "isEnabled": true,
                "locale": "en-US"
              }
            },
            "events": {
              "onFinish": [
                {
                  "command": "hangup"
                }
              ],
              "onFailure": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Recording could not be started for this call.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "stopRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Recording",
        "description": "Stops a recording previously started by a `startRecording` command. This is a non-blocking command — execution continues to the next command in the sequence immediately after the stop is initiated.",
        "required": [
          "command",
          "recordingName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopRecording",
            "description": "Command to stop recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Name of the recording to stop, as set by `recordingName` in the `startRecording` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          }
        }
      },
      "bridgeCall": {
        "type": "object",
        "additionalProperties": false,
        "title": "Add call to bridge",
        "description": "Adds the current call to a bridge, enabling bidirectional audio communication with other calls in the same session. This is a non-blocking command — execution continues to the next command in the sequence immediately after the call joins the bridge.\n\nBridges are created automatically when referenced by name. If a bridge with the specified name already exists, the call joins that bridge; otherwise, a new bridge is created.",
        "required": [
          "command",
          "bridgeName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "bridgeCall",
            "description": "Command to add the call to a bridge"
          },
          "bridgeName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "description": "Name of the bridge to join. If no bridge with this name exists in the session, a new one is created automatically."
          }
        },
        "examples": [
          {
            "command": "bridgeCall",
            "bridgeName": "my_bridge"
          }
        ]
      },
      "menuPrompt": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Prompt",
        "description": "Prompt configuration for menu playback, including prompt messages and barge-in behavior.",
        "required": [
          "messages"
        ],
        "properties": {
          "allowBargeIn": {
            "type": "boolean",
            "description": "Controls whether input can interrupt prompt playback.\n\nWhen enabled, playback stops as soon as input is detected and the input is evaluated immediately if matching conditions are met.\n\nWhen disabled, input is still collected during playback and evaluated after playback finishes.",
            "default": true
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          }
        }
      },
      "menuItem": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Item",
        "description": "Defines a single menu step, including prompts, input handling rules, input-to-command matches, and failure handling.\n\nEach collected input is matched against the values in the `matches` property.\nIf no match succeeds, the `onFail` commands are executed.\n\nIf neither `matches` nor `onFail` is defined and the service call behavior is set to `WEBHOOK`, a webhook request is sent including the collected input.",
        "properties": {
          "prompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when this menu starts.\n\nThis prompt is also used as the repeat prompt when repeatPrompt is not defined for the menu."
          },
          "repeatPrompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when the menu is repeated.\n\nRepeats occur when input times out or when the provided input does not match any menu match item."
          },
          "inputTimeoutDurationSeconds": {
            "type": "integer",
            "description": "Maximum number of seconds to wait for user input before the input attempt times out.",
            "minimum": 1,
            "maximum": 60,
            "default": 5,
            "example": 10
          },
          "repeatCount": {
            "type": "integer",
            "description": "Maximum number of times the menu is repeated.\n\nA repeat occurs when input times out or when the provided input does not match any menu match item.",
            "minimum": 0,
            "maximum": 10,
            "default": 2,
            "example": 3
          },
          "minimumInputLength": {
            "type": "integer",
            "description": "Minimum number of input characters required before the menu evaluates the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 3
          },
          "maximumInputLength": {
            "type": "integer",
            "description": "Maximum number of input characters that triggers the menu to evaluate the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 10
          },
          "terminatingSequence": {
            "type": "string",
            "pattern": "^[0-9*#]+$",
            "description": "Character sequence that signals the end of input and triggers immediate evaluation.\n\nUseful when variable-length input is allowed and shorter valid options should be submitted without waiting for timeout or maximum length.\n\nThe terminating sequence value is included in the evaluated input.",
            "maxLength": 10
          },
          "inputMethods": {
            "type": "array",
            "description": "Input methods accepted for this menu when collecting user input.",
            "default": [
              "DTMF"
            ],
            "items": {
              "type": "string",
              "enum": [
                "DTMF"
              ],
              "x-enumDescriptions": {
                "DTMF": "Collect input from keypad tones (Dual-Tone Multi-Frequency)."
              }
            }
          },
          "matches": {
            "type": "object",
            "description": "Items matched against the collected input. Maximum number of allowed match expressions is 50.\n\nDefined as a dictionary where each property name is a literal or a regular expression string.\n\nValues are evaluated in the order they are defined.",
            "maxProperties": 50,
            "propertyNames": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "description": "A regular expression or literal string to match against the collected user input. Must not be empty.\n\nProperty keys are evaluated sequentially in the order defined. The first key that matches the input will trigger its associated SVAML commands.\n\n**Note**: Use `\\\\*` to match the DTMF star tone (*)."
            },
            "additionalProperties": {
              "$ref": "#/components/schemas/svamlCommands"
            }
          },
          "onFail": {
            "$ref": "#/components/schemas/svamlCommands",
            "description": "SVAML commands executed when the menu fails to collect a matching input.\n\nThis handler runs after the repeat limit is reached without any input matching a menu match item."
          }
        }
      },
      "menu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Run menus",
        "description": "Defines a set of named menus and executes them starting from startMenu. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\nEach menu item configures prompts, input collection, timeout handling, and repeat behavior.",
        "required": [
          "command",
          "startMenu",
          "menus"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "menu",
            "description": "Executes menu-based input collection using the configured menu definitions."
          },
          "startMenu": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "description": "Name of the menu to execute first. Must match a key in menus."
          },
          "menus": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "maxLength": 16
            },
            "description": "Map of menu definitions keyed by menu name.",
            "additionalProperties": {
              "$ref": "#/components/schemas/menuItem"
            }
          }
        },
        "examples": [
          {
            "command": "menu",
            "startMenu": "main",
            "menus": {
              "main": {
                "prompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "repeatPrompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Invalid option. Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "inputTimeoutDurationSeconds": 5,
                "repeatCount": 2,
                "minimumInputLength": 1,
                "maximumInputLength": 1,
                "inputMethods": [
                  "DTMF"
                ],
                "matches": {
                  "1": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to sales.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "sales",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15551234567"
                        }
                      }
                    }
                  ],
                  "2": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to support.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "support",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15557654321"
                        }
                      }
                    }
                  ]
                },
                "onFail": [
                  {
                    "command": "messages",
                    "messages": [
                      {
                        "type": "SAY",
                        "say": {
                          "text": "Sorry, no valid selection was received.",
                          "voiceName": "Emma"
                        }
                      }
                    ]
                  },
                  {
                    "command": "hangup"
                  }
                ]
              }
            }
          }
        ]
      },
      "gotoMenu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Goto Menu",
        "description": "Switches execution to another menu within the current menu context. The menu name must be a menu defined in the `menu` command. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\n**Important**: this command can only be called within a menu execution context.",
        "required": [
          "command",
          "menuName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "gotoMenu",
            "description": "Switch execution to another menu within the current menu context."
          },
          "menuName": {
            "type": "string",
            "description": "Name of the target menu to execute next. Must match a key in menus.",
            "minLength": 1,
            "maxLength": 16
          }
        }
      },
      "svamlCommand": {
        "title": "SVAML Command",
        "type": "object",
        "description": "A single SVAML (Sinch Voice Application Markup Language) command that controls call behavior.\n\nThe `command` property acts as a discriminator and determines which command schema applies. When multiple commands appear in a `svamlCommands` array, they execute sequentially in order.\n\n**Available commands:**\n- `dial` — Initiate an outbound call leg within the session.\n- `messages` — Play one or more TTS or audio messages on the call.\n- `stopMessages` — Stop a currently playing message sequence.\n- `webhook` — Trigger a mid-call webhook to the application backend for dynamic call control.\n- `amd` — Detect whether the call was answered by a human or an answering machine.\n- `hangup` — End the call or a specific call leg within the session.\n- `answer` — Explicitly answer an incoming call leg before executing further commands.\n- `pause` — Delay script execution without affecting call audio.\n- `startRecording` — Begin recording the call.\n- `stopRecording` — Stop an active call recording.\n- `bridgeCall` — Add the call to a named bridge for multi-party audio.\n- `menu` — Run menu-based input collection and route the call based on collected input.\n- `gotoMenu` — Switch execution to another named menu within the current menu context.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/amd"
          },
          {
            "$ref": "#/components/schemas/dial"
          },
          {
            "$ref": "#/components/schemas/messages"
          },
          {
            "$ref": "#/components/schemas/stopMessages"
          },
          {
            "$ref": "#/components/schemas/webhook"
          },
          {
            "$ref": "#/components/schemas/hangup"
          },
          {
            "$ref": "#/components/schemas/answer"
          },
          {
            "$ref": "#/components/schemas/pause"
          },
          {
            "$ref": "#/components/schemas/startRecording"
          },
          {
            "$ref": "#/components/schemas/stopRecording"
          },
          {
            "$ref": "#/components/schemas/bridgeCall"
          },
          {
            "$ref": "#/components/schemas/menu"
          },
          {
            "$ref": "#/components/schemas/gotoMenu"
          }
        ],
        "discriminator": {
          "propertyName": "command",
          "mapping": {
            "amd": "#/components/schemas/amd",
            "dial": "#/components/schemas/dial",
            "messages": "#/components/schemas/messages",
            "stopMessages": "#/components/schemas/stopMessages",
            "webhook": "#/components/schemas/webhook",
            "hangup": "#/components/schemas/hangup",
            "answer": "#/components/schemas/answer",
            "pause": "#/components/schemas/pause",
            "startRecording": "#/components/schemas/startRecording",
            "stopRecording": "#/components/schemas/stopRecording",
            "bridgeCall": "#/components/schemas/bridgeCall",
            "menu": "#/components/schemas/menu",
            "gotoMenu": "#/components/schemas/gotoMenu"
          }
        }
      }
    }
  }
}
```

### `answer`

Accept an incoming call.

```json
{
  "command": "answer"
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/answer",
  "components": {
    "schemas": {
      "answer": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answer",
        "description": "Answers an inbound call leg. This is a non-blocking command — execution continues to the next command in the sequence immediately after the answer is initiated.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "answer",
            "description": "Answer call"
          }
        },
        "examples": [
          {
            "command": "answer"
          }
        ]
      }
    }
  }
}
```

### `dial`

Initiate outbound calls to phone numbers, SIP endpoints, streams, or conferences.

```json
{
  "command": "dial",
  "callName": "destination",
  "from": {
    "type": "PHONE",
    "phone": {
      "number": "+15551234567"
    }
  },
  "to": {
    "type": "PHONE",
    "phone": {
      "number": "+15559876543"
    }
  },
  "dialTimeoutDurationSeconds": 30,
  "maxCallDurationSeconds": 3600,
  "events": {
    "onAnswer": [
      {
        "command": "messages",
        "messages": [
          {
            "type": "SAY",
            "say": {
              "text": "Your call has connected.",
              "voiceName": "Emma"
            }
          }
        ]
      }
    ]
  }
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/dial",
  "components": {
    "schemas": {
      "phoneNumber": {
        "title": "Phone Number",
        "type": "string",
        "pattern": "^\\+[1-9]\\d{1,14}$",
        "minLength": 3,
        "maxLength": 16,
        "description": "E.164 Phone number",
        "examples": [
          "+4673522488"
        ]
      },
      "phone": {
        "type": "object",
        "additionalProperties": false,
        "title": "Phone",
        "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN).",
        "required": [
          "type",
          "phone"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PHONE",
            "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN). The number must be in E.164 format."
          },
          "phone": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "number"
            ],
            "properties": {
              "number": {
                "$ref": "#/components/schemas/phoneNumber"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PHONE",
            "phone": {
              "number": "+4673522488"
            }
          }
        ]
      },
      "sipFrom": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Origin",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Indicates the call originated from a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the originating endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "pattern": "^sips?:",
                "maxLength": 192
              },
              "displayName": {
                "type": "string",
                "description": "Display name presented to the called party as the caller identity. Transmitted as the display name part of the SIP `From` header (for example, `Alice <sip:alice@example.com>`).",
                "maxLength": 64,
                "example": "Alice"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "displayName": "Alice"
            }
          }
        ]
      },
      "from": {
        "description": "Call origin - Phone Number or SIP endpoint",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sipFrom"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sipFrom"
          }
        }
      },
      "sipCallHeaders": {
        "type": "array",
        "description": "Custom SIP headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[-A-Za-z0-9.!%*_+`'~]+$",
              "description": "Name of the SIP header.",
              "example": "X-Correlation-Id"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "description": "Value of the SIP header.",
              "example": "12345"
            }
          }
        },
        "examples": [
          [
            {
              "key": "X-Correlation-Id",
              "value": "12345"
            },
            {
              "key": "X-Call-Routing",
              "value": "forwarded"
            }
          ]
        ]
      },
      "sip": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Endpoint",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Routes the call to a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the destination endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "maxLength": 256,
                "pattern": "^sips?:"
              },
              "transport": {
                "type": "string",
                "description": "Transport protocol to use for the SIP signalling channel.\n\nIf omitted, the platform selects a default based on the URI scheme: `UDP` for `sip:` and `TLS` for `sips:`. Setting this explicitly overrides that default — for example, to force `TCP` for a `sip:` URI or to use `TLS` without switching to the `sips:` scheme.",
                "enum": [
                  "UDP",
                  "TCP",
                  "TLS"
                ],
                "x-enumDescriptions": {
                  "UDP": "Connectionless transport. Lowest overhead; suitable for most standard SIP deployments.",
                  "TCP": "Connection-oriented transport. More reliable for large SIP messages or NAT traversal scenarios.",
                  "TLS": "Encrypted transport. Provides confidentiality and integrity for SIP signalling."
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/sipCallHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "transport": "TCP",
              "callHeaders": [
                {
                  "key": "X-Correlation-Id",
                  "value": "12345"
                },
                {
                  "key": "X-Call-Routing",
                  "value": "forwarded"
                }
              ]
            }
          }
        ]
      },
      "callHeaders": {
        "type": "array",
        "description": "Custom headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]+$",
              "description": "Name of the header.",
              "example": "headerKey"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]*$",
              "description": "Value of the header.",
              "example": "headerValue"
            }
          }
        },
        "examples": [
          [
            {
              "key": "headerKey",
              "value": "headerValue"
            },
            {
              "key": "anotherKey",
              "value": "anotherValue"
            }
          ]
        ]
      },
      "stream": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stream",
        "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing.",
        "required": [
          "type",
          "stream"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "STREAM",
            "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing."
          },
          "stream": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "WebSocket endpoint that will accept the incoming connection for real-time audio streaming. Must be a valid WebSocket URL using either `ws://` or `wss://` (recommended). The URL must be reachable from the public internet and capable of handling the negotiated stream protocol.",
                "example": "wss://example.com"
              },
              "streamOptions": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "description": "Defines the version of the stream protocol.",
                    "default": 1,
                    "example": 1
                  },
                  "codec": {
                    "type": "string",
                    "const": "PCM",
                    "description": "Defines the audio codec/format used for the stream audio payload.\n\nCurrently, only `PCM` is supported (uncompressed raw audio). Use `sampleRate` to configure the sampling rate for the stream."
                  },
                  "sampleRate": {
                    "type": "integer",
                    "description": "Defines the audio sampling rate (Hz) used for the stream.\n\nFor calls that traverse the PSTN, audio is typically sampled at 8 kHz, so using a higher value will not improve perceived quality. \nHigher sample rates can be useful for non-PSTN scenarios (for example, SIP/streaming paths), but will increase bandwidth usage and processing load.",
                    "enum": [
                      8000,
                      16000,
                      24000,
                      44100,
                      48000,
                      96000
                    ],
                    "x-enumDescriptions": {
                      "8000": "8 kHz (standard for PSTN calls)",
                      "16000": "16 kHz (wideband audio)",
                      "24000": "24 kHz (super-wideband audio)",
                      "44100": "44.1 kHz (CD quality audio)",
                      "48000": "48 kHz (professional audio quality)",
                      "96000": "96 kHz (high-resolution audio)"
                    },
                    "default": 8000,
                    "example": 16000
                  }
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            },
            "examples": [
              {
                "endpoint": "wss://example.com",
                "streamOptions": {
                  "version": 1,
                  "codec": "PCM",
                  "sampleRate": 8000
                },
                "callHeaders": [
                  {
                    "key": "my-key",
                    "value": "my-key-value"
                  }
                ]
              }
            ]
          }
        },
        "examples": [
          {
            "type": "STREAM",
            "stream": {
              "endpoint": "wss://example.com",
              "streamOptions": {
                "version": 1,
                "codec": "PCM",
                "sampleRate": 16000
              },
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "voiceRelay": {
        "type": "object",
        "additionalProperties": false,
        "title": "Voice Relay",
        "description": "Routes the call through the Voice Relay service, enabling real-time speech-to-text (STT) and text-to-speech (TTS) via a WebSocket connection to the application backend.",
        "required": [
          "type",
          "voiceRelay"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "VOICE_RELAY",
            "description": "Connects to the Voice Relay service to enable STT and TTS services..."
          },
          "voiceRelay": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint",
              "ttsVoice",
              "sttLanguage"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "format": "uri",
                "description": "URL to the server that will accept the web-socket request",
                "example": "wss://acme.com/agent"
              },
              "enableInterruptions": {
                "type": "boolean",
                "description": "Allow \"barge-in\" during text-to-speech (TTS) playback.\n\nWhen `true`, TTS playback is interrupted as soon as inbound speech is detected, unless the currently playing content is marked as uninterruptible.\n\nWhen `false`, TTS playback continues uninterrupted, but an interruption signal is still sent over the WebSocket so the client application can choose to stop playback manually if needed.",
                "default": true,
                "example": true
              },
              "ttsVoice": {
                "type": "string",
                "description": "Name of the voice to be used when synthesizing speech. \n\nThis is the default voice used, if no override voice is provided in the web-socket TTS message.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              },
              "sttLanguage": {
                "type": "string",
                "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$",
                "description": "BCP-47 language tag used for speech-to-text transcription of the inbound audio.\n\nThis value determines which language model is used for transcription.",
                "example": "en-US"
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "VOICE_RELAY",
            "voiceRelay": {
              "endpoint": "wss://acme.com/agent",
              "enableInterruptions": true,
              "ttsVoice": "Emma",
              "sttLanguage": "en-US",
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "to": {
        "title": "To",
        "description": "Call destination - Phone Number or Stream URI",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sip"
          },
          {
            "$ref": "#/components/schemas/stream"
          },
          {
            "$ref": "#/components/schemas/voiceRelay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sip",
            "STREAM": "#/components/schemas/stream",
            "VOICE_RELAY": "#/components/schemas/voiceRelay"
          }
        }
      },
      "svamlCommands": {
        "type": "array",
        "title": "SVAML Commands",
        "description": "An ordered list of SVAML v2 (Sinch Voice Application Markup Language) commands that describe a call flow. Commands are executed sequentially in the order they are defined.\n\n**Blocking vs. non-blocking:** Some commands block execution until they complete (`pause`, `webhook`, `menu`, `gotoMenu`), while others return immediately and run in parallel (`dial`, `messages`, `amd`, `answer`, `hangup`, `startRecording`, `stopRecording`, `bridgeCall`, `stopMessages`). Each command's description specifies its behavior.\n\n**Nesting scope:** Commands that appear inside event handlers (e.g., `dial.events.onAnswer`, `messages.events.onFinish`) form independent sequences and execute in their own context — they are not continuations of the parent sequence.",
        "items": {
          "$ref": "#/components/schemas/svamlCommand"
        }
      },
      "amdEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "AMD Events",
        "description": "SVAML commands to execute based on the answering machine detection result. These events define different call flows depending on whether a human, machine, beep, or unknown entity answers the call.",
        "properties": {
          "onHuman": {
            "description": "SVAML commands to be executed when a human is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onMachine": {
            "description": "SVAML commands to be executed when a machine is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBeep": {
            "description": "SVAML commands to be executed when a beep is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onUnknown": {
            "description": "SVAML commands to be executed when an unknown event is detected",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "amd": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answering Machine Detection",
        "description": "AMD (Answering Machine Detection) command to detect what answered the call. Possible outcomes are: human, machine, beep, or unknown.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while detection runs in parallel. Results are delivered via the `events` property.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "amd",
            "description": "Command to run Answering Machine Detection on the call"
          },
          "events": {
            "$ref": "#/components/schemas/amdEvents"
          }
        },
        "examples": [
          {
            "command": "amd",
            "events": {
              "onHuman": [
                {
                  "command": "pause",
                  "durationMilliseconds": 1000
                },
                {
                  "command": "bridgeCall",
                  "bridgeName": "my-bridge"
                }
              ],
              "onBeep": [
                {
                  "command": "messages",
                  "messagesName": "my-amd-messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Hello, this is a test message",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "dial": {
        "type": "object",
        "additionalProperties": false,
        "title": "Dial",
        "description": "Initiates a new outbound call leg within the current session.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while the call is being established in parallel. Call lifecycle events (answer, busy, reject, timeout, hangup, failure) are handled via the `events` property.\n\nThe `from` and `to` endpoint types should ideally match. If they differ, the platform attempts to convert the `from` value to be compatible with the `to` type. For example, PSTN supports only E.164 phone numbers, so a SIP address such as `sip:46701234567@acme.se` can be converted to an E.164 number. If the `from` value cannot be converted, it defaults to null (anonymous).",
        "required": [
          "command",
          "to"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "dial",
            "description": "Command to initiate a new call"
          },
          "callName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "outgoing",
            "description": "Identifier for this call leg within the session. Must be unique across all active call legs in the session.\n\nOther commands (e.g., `hangup`) can reference this name to target this specific leg."
          },
          "from": {
            "$ref": "#/components/schemas/from"
          },
          "to": {
            "$ref": "#/components/schemas/to"
          },
          "dialTimeoutDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "description": "Maximum time in seconds to wait for the call to be answered. If the timeout expires without an answer, the `onTimeout` event is triggered.",
            "example": 15
          },
          "maxCallDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 14400,
            "description": "Maximum duration of the call in seconds. The call is terminated automatically when this limit is reached.",
            "example": 3600
          },
          "events": {
            "$ref": "#/components/schemas/callEvents"
          }
        },
        "examples": [
          {
            "command": "dial",
            "callName": "destination",
            "from": {
              "type": "PHONE",
              "phone": {
                "number": "+15551234567"
              }
            },
            "to": {
              "type": "PHONE",
              "phone": {
                "number": "+15559876543"
              }
            },
            "dialTimeoutDurationSeconds": 30,
            "maxCallDurationSeconds": 3600,
            "events": {
              "onAnswer": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Your call has connected.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "messageSay": {
        "type": "object",
        "title": "Say Message",
        "description": "A text-to-speech (TTS) message item. The platform synthesizes the provided text into speech and plays it on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "say"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SAY",
            "description": "Text-to-speech message to be played during the call."
          },
          "say": {
            "type": "object",
            "additionalProperties": false,
            "title": "Say",
            "required": [
              "text",
              "voiceName"
            ],
            "properties": {
              "text": {
                "type": "string",
                "description": "The text to be synthesized into speech.\n\nIf `format` is `TEXT` (default), provide plain text.\nIf `format` is `SSML`, provide a valid SSML document (for example, `<speak>...</speak>`).",
                "maxLength": 600,
                "example": "Hello world"
              },
              "format": {
                "type": "string",
                "description": "Format of the message",
                "enum": [
                  "TEXT",
                  "SSML"
                ],
                "x-enumDescriptions": {
                  "TEXT": "Plain text format for the message.",
                  "SSML": "Speech Synthesis Markup Language format for advanced text-to-speech control."
                },
                "default": "TEXT"
              },
              "voiceName": {
                "type": "string",
                "description": "The name of the voice to use for text-to-speech synthesis.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SAY",
            "say": {
              "text": "Hello, this is a test message",
              "voiceName": "Emma"
            }
          },
          {
            "type": "SAY",
            "say": {
              "text": "<speak><prosody volume=\"-6dB\">Hello, this is a test message</prosody></speak>",
              "format": "SSML",
              "voiceName": "Brian"
            }
          }
        ]
      },
      "messagePlay": {
        "type": "object",
        "title": "Play Message",
        "description": "An audio file playback message item. The platform fetches and plays the audio file at the provided URL on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "play"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PLAY",
            "description": "Audio file playback during the call."
          },
          "play": {
            "type": "object",
            "additionalProperties": false,
            "title": "Play",
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "description": "URL of the media to send"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PLAY",
            "play": {
              "url": "https://example.com/media.mp3"
            }
          }
        ]
      },
      "message": {
        "type": "object",
        "title": "Message",
        "description": "A single message item. The required payload depends on `type`.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/messageSay"
          },
          {
            "$ref": "#/components/schemas/messagePlay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "SAY": "#/components/schemas/messageSay",
            "PLAY": "#/components/schemas/messagePlay"
          }
        }
      },
      "typesOfMessages": {
        "type": "array",
        "title": "Message List",
        "description": "Ordered list of messages to play.",
        "minItems": 1,
        "maxItems": 10,
        "items": {
          "$ref": "#/components/schemas/message"
        }
      },
      "messageEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Message Events",
        "description": "SVAML commands to execute based on message playback outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when all messages in the sequence have finished playing.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "messages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Messages",
        "description": "Plays one or more messages on the call. Multiple messages in the array are played sequentially in order.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while messages play in parallel. \nPlayback outcomes are handled via the `events` property. The `onFinish` event can be used to run a command after all messages complete.",
        "required": [
          "command",
          "messages"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "messages",
            "description": "Command to play a message on the channel"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message for identification and reference within the call session.\n\nThis name is used to uniquely identify the message and must be unique within the current call session.\nThis name can be referenced in other commands (e.g., `stopMessages`) to control this specific message.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-messages"
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          },
          "events": {
            "$ref": "#/components/schemas/messageEvents"
          }
        },
        "examples": [
          {
            "command": "messages",
            "messagesName": "greeting-sequence",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Hello! Your call is being connected.",
                  "voiceName": "Emma"
                }
              },
              {
                "type": "PLAY",
                "play": {
                  "url": "https://example.com/audio/hold-music.mp3"
                }
              },
              {
                "type": "SAY",
                "say": {
                  "text": "<speak><prosody volume=\"-6dB\">Thank you for waiting.</prosody></speak>",
                  "format": "SSML",
                  "voiceName": "Emma"
                }
              }
            ]
          }
        ]
      },
      "stopMessages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Messages",
        "description": "Stops a message sequence previously started by a `messages` command. Use `messagesName` to target a specific sequence and `flags` to control whether only the current message or all queued messages are cancelled. \n\nThis is a non-blocking command.",
        "required": [
          "command",
          "messagesName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopMessages",
            "description": "Command to stop playing messages"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message sequence to stop, as set by `messagesName` in the `messages` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$"
          },
          "flags": {
            "type": "string",
            "description": "Controls how much of the sequence is stopped — only the currently playing message or all remaining queued messages.",
            "default": "ALL_FROM_NOW_ON",
            "enum": [
              "ONLY_PLAYING",
              "ALL_FROM_NOW_ON"
            ],
            "x-enumDescriptions": {
              "ONLY_PLAYING": "Stops only the currently playing message. Queued messages will continue to play.",
              "ALL_FROM_NOW_ON": "Stops the currently playing message and cancels all queued messages."
            }
          }
        },
        "examples": [
          {
            "command": "stopMessages",
            "messagesName": "my-messages",
            "flags": "ONLY_PLAYING"
          }
        ]
      },
      "webhookFallbackUrl": {
        "title": "Webhook Fallback URL",
        "type": "string",
        "format": "uri",
        "description": "Fallback webhook URL used when the primary webhook URL fails.\n\nA failed request is re-sent to this URL immediately. After repeated consecutive failures of the primary URL, requests are sent only here until the primary URL recovers.\n\nSee *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "examples": [
          "https://example.com/fallback"
        ]
      },
      "webhook": {
        "type": "object",
        "additionalProperties": false,
        "title": "Webhook",
        "description": "Triggers a mid-call webhook to the application backend, allowing it to return a new set of SVAML commands that control the remainder of the call flow.\n\nThis is a blocking command — execution pauses until a response is received from the webhook endpoint. The next command in the sequence runs only after the backend responds. Webhook requests use a 5-second timeout. If a `fallbackUrl` is provided, a failed request is re-sent to it — see *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "required": [
          "command",
          "webhookName",
          "url"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "webhook",
            "description": "Command to trigger a mid-call webhook"
          },
          "webhookName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^\\S+$",
            "description": "Name for this webhook event. When triggered, the webhook request's `event` property will contain this name prepended with `call.webhook.`.\n\nFor example, if `webhookName` is set to `\"my.custom.event\"`, the event will be delivered as `\"call.webhook.my.custom.event\"`."
          },
          "url": {
            "type": "string",
            "description": "URL of the webhook endpoint to send the mid-call event to.",
            "format": "uri"
          },
          "fallbackUrl": {
            "$ref": "#/components/schemas/webhookFallbackUrl"
          }
        },
        "examples": [
          {
            "command": "webhook",
            "webhookName": "my.custom.event",
            "url": "https://example.com/webhook",
            "fallbackUrl": "https://example.com/fallback"
          }
        ]
      },
      "hangup": {
        "type": "object",
        "additionalProperties": false,
        "description": "Ends a call leg. This is a non-blocking command — execution continues to the next command in the sequence even though the call has been ended. The `onHangup` event is triggered for the call leg that was ended.\n\nAny subsequent commands that target the ended call leg (such as `messages` or other media commands) are valid but will not be executed. Commands that operate independently — such as initiating a new call with `dial` — will execute normally. This makes it possible, for example, to end one call and immediately start another within the same sequence.",
        "title": "Hangup",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "hangup",
            "description": "Hangup call"
          },
          "callName": {
            "type": "string",
            "description": "Name of the call leg to end, as set by `callName` in the `dial` command.\n\nIf omitted, the current call leg is ended.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "origin"
          }
        },
        "examples": [
          {
            "command": "hangup",
            "callName": "origin"
          }
        ]
      },
      "answer": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answer",
        "description": "Answers an inbound call leg. This is a non-blocking command — execution continues to the next command in the sequence immediately after the answer is initiated.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "answer",
            "description": "Answer call"
          }
        },
        "examples": [
          {
            "command": "answer"
          }
        ]
      },
      "pause": {
        "type": "object",
        "additionalProperties": false,
        "title": "Pause",
        "description": "Delays execution of the next command in the sequence for a specified duration. This is a blocking command — no further commands execute until the pause completes.\n\nThe pause does not affect call audio; the call remains connected and audio continues uninterrupted.",
        "required": [
          "command",
          "durationMilliseconds"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "pause",
            "description": "Pause execution."
          },
          "durationMilliseconds": {
            "type": "integer",
            "minimum": 1,
            "description": "Duration of the pause in milliseconds.",
            "example": 1000
          }
        },
        "examples": [
          {
            "command": "pause",
            "durationMilliseconds": 1500
          }
        ]
      },
      "recordingFormat": {
        "title": "Recording Format",
        "description": "Audio format for this recording.",
        "type": "string",
        "enum": [
          "MP3",
          "WAV"
        ],
        "x-enumDescriptions": {
          "MP3": "MPEG Audio Layer III compressed audio format.",
          "WAV": "Waveform Audio File Format, uncompressed audio."
        },
        "default": "MP3",
        "examples": [
          "MP3"
        ]
      },
      "recordingType": {
        "title": "Recording Type",
        "description": "The type of recording to perform.",
        "type": "string",
        "enum": [
          "COMBINED",
          "INBOUND",
          "OUTBOUND"
        ],
        "x-enumDescriptions": {
          "COMBINED": "Record inbound and outbound voice streams.",
          "INBOUND": "Record inbound voice stream only.",
          "OUTBOUND": "Record outbound voice stream only."
        },
        "default": "COMBINED"
      },
      "recordingDestination": {
        "title": "Recording Destination",
        "type": "string",
        "description": "Select target service to receive recorded and transcribed files",
        "enum": [
          "AWS",
          "GCP",
          "AZURE"
        ],
        "x-enumDescriptions": {
          "AWS": "Store recordings in Amazon Web Services S3 bucket. Use `s3` as schema for the URL.",
          "GCP": "Store recordings in Google Cloud Platform Storage. Use `gs` as schema for the URL.",
          "AZURE": "Store recordings in Microsoft Azure Blob Storage.  Use `azure` as schema for the URL."
        },
        "default": "AWS",
        "examples": [
          "AWS"
        ]
      },
      "transcriptionOptions": {
        "title": "Transcription Options",
        "description": "Configuration for automatic speech-to-text transcription of the recording.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "isEnabled"
        ],
        "properties": {
          "isEnabled": {
            "type": "boolean",
            "description": "If true, the recording will be transcribed to text.",
            "example": true
          },
          "locale": {
            "type": "string",
            "description": "Language code in BCP-47 format.",
            "default": "en-US",
            "example": "en-US"
          }
        }
      },
      "recordingOptions": {
        "title": "Recording Options",
        "type": "object",
        "additionalProperties": false,
        "description": "Recording options for this recording.",
        "required": [
          "destination",
          "destinationUrl",
          "credentials"
        ],
        "properties": {
          "format": {
            "$ref": "#/components/schemas/recordingFormat"
          },
          "recordingType": {
            "$ref": "#/components/schemas/recordingType"
          },
          "destination": {
            "$ref": "#/components/schemas/recordingDestination"
          },
          "destinationUrl": {
            "type": "string",
            "description": "Destination URL for the recording.",
            "example": "s3://voice-recordings-prod/calls"
          },
          "credentials": {
            "type": "string",
            "description": "Credentials to third party storage.",
            "example": "accessKeyId:secretAccessKey:eu-central-1"
          },
          "transcriptionOptions": {
            "$ref": "#/components/schemas/transcriptionOptions"
          }
        }
      },
      "recordingEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Recording Events",
        "description": "SVAML commands to execute based on recording lifecycle outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when the recording is successfully stopped. Note that this does not mean that the file is delivered to the configured destination yet.\n",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "Commands to execute if the recording fails to start. If omitted, failures are silently ignored and the call flow continues.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "startRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Start Recording",
        "required": [
          "command",
          "recordingOptions"
        ],
        "description": "Starts recording the call. This is a non-blocking command — execution continues to the next command in the sequence immediately after recording begins.",
        "properties": {
          "command": {
            "type": "string",
            "const": "startRecording",
            "description": "Command to start recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Identifier for this recording within the session. Must be unique across active recordings in the session.\n\nOther commands (e.g., `stopRecording`) reference this name to target a specific recording.\n\nSetting the recording name is useful for stopping the recording using the `stopRecording` command. If name is not set, recording can only be stopped when the call is disconnected.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          },
          "recordingOptions": {
            "$ref": "#/components/schemas/recordingOptions"
          },
          "events": {
            "$ref": "#/components/schemas/recordingEvents"
          }
        },
        "examples": [
          {
            "command": "startRecording",
            "recordingName": "customer-support-recording",
            "recordingOptions": {
              "format": "MP3",
              "recordingType": "COMBINED",
              "destination": "AWS",
              "destinationUrl": "s3://voice-recordings-prod/calls",
              "credentials": "accessKeyId:secretAccessKey:eu-central-1",
              "transcriptionOptions": {
                "isEnabled": true,
                "locale": "en-US"
              }
            },
            "events": {
              "onFinish": [
                {
                  "command": "hangup"
                }
              ],
              "onFailure": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Recording could not be started for this call.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "stopRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Recording",
        "description": "Stops a recording previously started by a `startRecording` command. This is a non-blocking command — execution continues to the next command in the sequence immediately after the stop is initiated.",
        "required": [
          "command",
          "recordingName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopRecording",
            "description": "Command to stop recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Name of the recording to stop, as set by `recordingName` in the `startRecording` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          }
        }
      },
      "bridgeCall": {
        "type": "object",
        "additionalProperties": false,
        "title": "Add call to bridge",
        "description": "Adds the current call to a bridge, enabling bidirectional audio communication with other calls in the same session. This is a non-blocking command — execution continues to the next command in the sequence immediately after the call joins the bridge.\n\nBridges are created automatically when referenced by name. If a bridge with the specified name already exists, the call joins that bridge; otherwise, a new bridge is created.",
        "required": [
          "command",
          "bridgeName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "bridgeCall",
            "description": "Command to add the call to a bridge"
          },
          "bridgeName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "description": "Name of the bridge to join. If no bridge with this name exists in the session, a new one is created automatically."
          }
        },
        "examples": [
          {
            "command": "bridgeCall",
            "bridgeName": "my_bridge"
          }
        ]
      },
      "menuPrompt": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Prompt",
        "description": "Prompt configuration for menu playback, including prompt messages and barge-in behavior.",
        "required": [
          "messages"
        ],
        "properties": {
          "allowBargeIn": {
            "type": "boolean",
            "description": "Controls whether input can interrupt prompt playback.\n\nWhen enabled, playback stops as soon as input is detected and the input is evaluated immediately if matching conditions are met.\n\nWhen disabled, input is still collected during playback and evaluated after playback finishes.",
            "default": true
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          }
        }
      },
      "menuItem": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Item",
        "description": "Defines a single menu step, including prompts, input handling rules, input-to-command matches, and failure handling.\n\nEach collected input is matched against the values in the `matches` property.\nIf no match succeeds, the `onFail` commands are executed.\n\nIf neither `matches` nor `onFail` is defined and the service call behavior is set to `WEBHOOK`, a webhook request is sent including the collected input.",
        "properties": {
          "prompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when this menu starts.\n\nThis prompt is also used as the repeat prompt when repeatPrompt is not defined for the menu."
          },
          "repeatPrompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when the menu is repeated.\n\nRepeats occur when input times out or when the provided input does not match any menu match item."
          },
          "inputTimeoutDurationSeconds": {
            "type": "integer",
            "description": "Maximum number of seconds to wait for user input before the input attempt times out.",
            "minimum": 1,
            "maximum": 60,
            "default": 5,
            "example": 10
          },
          "repeatCount": {
            "type": "integer",
            "description": "Maximum number of times the menu is repeated.\n\nA repeat occurs when input times out or when the provided input does not match any menu match item.",
            "minimum": 0,
            "maximum": 10,
            "default": 2,
            "example": 3
          },
          "minimumInputLength": {
            "type": "integer",
            "description": "Minimum number of input characters required before the menu evaluates the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 3
          },
          "maximumInputLength": {
            "type": "integer",
            "description": "Maximum number of input characters that triggers the menu to evaluate the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 10
          },
          "terminatingSequence": {
            "type": "string",
            "pattern": "^[0-9*#]+$",
            "description": "Character sequence that signals the end of input and triggers immediate evaluation.\n\nUseful when variable-length input is allowed and shorter valid options should be submitted without waiting for timeout or maximum length.\n\nThe terminating sequence value is included in the evaluated input.",
            "maxLength": 10
          },
          "inputMethods": {
            "type": "array",
            "description": "Input methods accepted for this menu when collecting user input.",
            "default": [
              "DTMF"
            ],
            "items": {
              "type": "string",
              "enum": [
                "DTMF"
              ],
              "x-enumDescriptions": {
                "DTMF": "Collect input from keypad tones (Dual-Tone Multi-Frequency)."
              }
            }
          },
          "matches": {
            "type": "object",
            "description": "Items matched against the collected input. Maximum number of allowed match expressions is 50.\n\nDefined as a dictionary where each property name is a literal or a regular expression string.\n\nValues are evaluated in the order they are defined.",
            "maxProperties": 50,
            "propertyNames": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "description": "A regular expression or literal string to match against the collected user input. Must not be empty.\n\nProperty keys are evaluated sequentially in the order defined. The first key that matches the input will trigger its associated SVAML commands.\n\n**Note**: Use `\\\\*` to match the DTMF star tone (*)."
            },
            "additionalProperties": {
              "$ref": "#/components/schemas/svamlCommands"
            }
          },
          "onFail": {
            "$ref": "#/components/schemas/svamlCommands",
            "description": "SVAML commands executed when the menu fails to collect a matching input.\n\nThis handler runs after the repeat limit is reached without any input matching a menu match item."
          }
        }
      },
      "menu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Run menus",
        "description": "Defines a set of named menus and executes them starting from startMenu. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\nEach menu item configures prompts, input collection, timeout handling, and repeat behavior.",
        "required": [
          "command",
          "startMenu",
          "menus"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "menu",
            "description": "Executes menu-based input collection using the configured menu definitions."
          },
          "startMenu": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "description": "Name of the menu to execute first. Must match a key in menus."
          },
          "menus": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "maxLength": 16
            },
            "description": "Map of menu definitions keyed by menu name.",
            "additionalProperties": {
              "$ref": "#/components/schemas/menuItem"
            }
          }
        },
        "examples": [
          {
            "command": "menu",
            "startMenu": "main",
            "menus": {
              "main": {
                "prompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "repeatPrompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Invalid option. Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "inputTimeoutDurationSeconds": 5,
                "repeatCount": 2,
                "minimumInputLength": 1,
                "maximumInputLength": 1,
                "inputMethods": [
                  "DTMF"
                ],
                "matches": {
                  "1": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to sales.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "sales",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15551234567"
                        }
                      }
                    }
                  ],
                  "2": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to support.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "support",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15557654321"
                        }
                      }
                    }
                  ]
                },
                "onFail": [
                  {
                    "command": "messages",
                    "messages": [
                      {
                        "type": "SAY",
                        "say": {
                          "text": "Sorry, no valid selection was received.",
                          "voiceName": "Emma"
                        }
                      }
                    ]
                  },
                  {
                    "command": "hangup"
                  }
                ]
              }
            }
          }
        ]
      },
      "gotoMenu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Goto Menu",
        "description": "Switches execution to another menu within the current menu context. The menu name must be a menu defined in the `menu` command. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\n**Important**: this command can only be called within a menu execution context.",
        "required": [
          "command",
          "menuName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "gotoMenu",
            "description": "Switch execution to another menu within the current menu context."
          },
          "menuName": {
            "type": "string",
            "description": "Name of the target menu to execute next. Must match a key in menus.",
            "minLength": 1,
            "maxLength": 16
          }
        }
      },
      "svamlCommand": {
        "title": "SVAML Command",
        "type": "object",
        "description": "A single SVAML (Sinch Voice Application Markup Language) command that controls call behavior.\n\nThe `command` property acts as a discriminator and determines which command schema applies. When multiple commands appear in a `svamlCommands` array, they execute sequentially in order.\n\n**Available commands:**\n- `dial` — Initiate an outbound call leg within the session.\n- `messages` — Play one or more TTS or audio messages on the call.\n- `stopMessages` — Stop a currently playing message sequence.\n- `webhook` — Trigger a mid-call webhook to the application backend for dynamic call control.\n- `amd` — Detect whether the call was answered by a human or an answering machine.\n- `hangup` — End the call or a specific call leg within the session.\n- `answer` — Explicitly answer an incoming call leg before executing further commands.\n- `pause` — Delay script execution without affecting call audio.\n- `startRecording` — Begin recording the call.\n- `stopRecording` — Stop an active call recording.\n- `bridgeCall` — Add the call to a named bridge for multi-party audio.\n- `menu` — Run menu-based input collection and route the call based on collected input.\n- `gotoMenu` — Switch execution to another named menu within the current menu context.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/amd"
          },
          {
            "$ref": "#/components/schemas/dial"
          },
          {
            "$ref": "#/components/schemas/messages"
          },
          {
            "$ref": "#/components/schemas/stopMessages"
          },
          {
            "$ref": "#/components/schemas/webhook"
          },
          {
            "$ref": "#/components/schemas/hangup"
          },
          {
            "$ref": "#/components/schemas/answer"
          },
          {
            "$ref": "#/components/schemas/pause"
          },
          {
            "$ref": "#/components/schemas/startRecording"
          },
          {
            "$ref": "#/components/schemas/stopRecording"
          },
          {
            "$ref": "#/components/schemas/bridgeCall"
          },
          {
            "$ref": "#/components/schemas/menu"
          },
          {
            "$ref": "#/components/schemas/gotoMenu"
          }
        ],
        "discriminator": {
          "propertyName": "command",
          "mapping": {
            "amd": "#/components/schemas/amd",
            "dial": "#/components/schemas/dial",
            "messages": "#/components/schemas/messages",
            "stopMessages": "#/components/schemas/stopMessages",
            "webhook": "#/components/schemas/webhook",
            "hangup": "#/components/schemas/hangup",
            "answer": "#/components/schemas/answer",
            "pause": "#/components/schemas/pause",
            "startRecording": "#/components/schemas/startRecording",
            "stopRecording": "#/components/schemas/stopRecording",
            "bridgeCall": "#/components/schemas/bridgeCall",
            "menu": "#/components/schemas/menu",
            "gotoMenu": "#/components/schemas/gotoMenu"
          }
        }
      },
      "callEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Call Events Webhook",
        "description": "Webhook to handle call events, used when callBehaviors are set to WEBHOOK",
        "properties": {
          "onAnswer": {
            "description": "SVAML commands to be executed when the call is answered",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBusy": {
            "description": "SVAML commands to be executed when the call is busy",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onReject": {
            "description": "SVAML commands to be executed when the call is rejected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onTimeout": {
            "description": "SVAML commands to be executed when the call is timed out",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onHangup": {
            "description": "SVAML commands to be executed when the call is hung up",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "SVAML commands to be executed when the call fails",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      }
    }
  }
}
```

### `amd`

Perform Answering Machine Detection on answered calls.

```json
{
  "command": "amd",
  "events": {
    "onHuman": [
      {
        "command": "pause",
        "durationMilliseconds": 1000
      },
      {
        "command": "bridgeCall",
        "bridgeName": "my-bridge"
      }
    ],
    "onBeep": [
      {
        "command": "messages",
        "messagesName": "my-amd-messages",
        "messages": [
          {
            "type": "SAY",
            "say": {
              "text": "Hello, this is a test message",
              "voiceName": "Emma"
            }
          }
        ]
      }
    ]
  }
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/amd",
  "components": {
    "schemas": {
      "amd": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answering Machine Detection",
        "description": "AMD (Answering Machine Detection) command to detect what answered the call. Possible outcomes are: human, machine, beep, or unknown.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while detection runs in parallel. Results are delivered via the `events` property.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "amd",
            "description": "Command to run Answering Machine Detection on the call"
          },
          "events": {
            "$ref": "#/components/schemas/amdEvents"
          }
        },
        "examples": [
          {
            "command": "amd",
            "events": {
              "onHuman": [
                {
                  "command": "pause",
                  "durationMilliseconds": 1000
                },
                {
                  "command": "bridgeCall",
                  "bridgeName": "my-bridge"
                }
              ],
              "onBeep": [
                {
                  "command": "messages",
                  "messagesName": "my-amd-messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Hello, this is a test message",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "phoneNumber": {
        "title": "Phone Number",
        "type": "string",
        "pattern": "^\\+[1-9]\\d{1,14}$",
        "minLength": 3,
        "maxLength": 16,
        "description": "E.164 Phone number",
        "examples": [
          "+4673522488"
        ]
      },
      "phone": {
        "type": "object",
        "additionalProperties": false,
        "title": "Phone",
        "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN).",
        "required": [
          "type",
          "phone"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PHONE",
            "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN). The number must be in E.164 format."
          },
          "phone": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "number"
            ],
            "properties": {
              "number": {
                "$ref": "#/components/schemas/phoneNumber"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PHONE",
            "phone": {
              "number": "+4673522488"
            }
          }
        ]
      },
      "sipFrom": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Origin",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Indicates the call originated from a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the originating endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "pattern": "^sips?:",
                "maxLength": 192
              },
              "displayName": {
                "type": "string",
                "description": "Display name presented to the called party as the caller identity. Transmitted as the display name part of the SIP `From` header (for example, `Alice <sip:alice@example.com>`).",
                "maxLength": 64,
                "example": "Alice"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "displayName": "Alice"
            }
          }
        ]
      },
      "from": {
        "description": "Call origin - Phone Number or SIP endpoint",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sipFrom"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sipFrom"
          }
        }
      },
      "sipCallHeaders": {
        "type": "array",
        "description": "Custom SIP headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[-A-Za-z0-9.!%*_+`'~]+$",
              "description": "Name of the SIP header.",
              "example": "X-Correlation-Id"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "description": "Value of the SIP header.",
              "example": "12345"
            }
          }
        },
        "examples": [
          [
            {
              "key": "X-Correlation-Id",
              "value": "12345"
            },
            {
              "key": "X-Call-Routing",
              "value": "forwarded"
            }
          ]
        ]
      },
      "sip": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Endpoint",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Routes the call to a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the destination endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "maxLength": 256,
                "pattern": "^sips?:"
              },
              "transport": {
                "type": "string",
                "description": "Transport protocol to use for the SIP signalling channel.\n\nIf omitted, the platform selects a default based on the URI scheme: `UDP` for `sip:` and `TLS` for `sips:`. Setting this explicitly overrides that default — for example, to force `TCP` for a `sip:` URI or to use `TLS` without switching to the `sips:` scheme.",
                "enum": [
                  "UDP",
                  "TCP",
                  "TLS"
                ],
                "x-enumDescriptions": {
                  "UDP": "Connectionless transport. Lowest overhead; suitable for most standard SIP deployments.",
                  "TCP": "Connection-oriented transport. More reliable for large SIP messages or NAT traversal scenarios.",
                  "TLS": "Encrypted transport. Provides confidentiality and integrity for SIP signalling."
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/sipCallHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "transport": "TCP",
              "callHeaders": [
                {
                  "key": "X-Correlation-Id",
                  "value": "12345"
                },
                {
                  "key": "X-Call-Routing",
                  "value": "forwarded"
                }
              ]
            }
          }
        ]
      },
      "callHeaders": {
        "type": "array",
        "description": "Custom headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]+$",
              "description": "Name of the header.",
              "example": "headerKey"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]*$",
              "description": "Value of the header.",
              "example": "headerValue"
            }
          }
        },
        "examples": [
          [
            {
              "key": "headerKey",
              "value": "headerValue"
            },
            {
              "key": "anotherKey",
              "value": "anotherValue"
            }
          ]
        ]
      },
      "stream": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stream",
        "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing.",
        "required": [
          "type",
          "stream"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "STREAM",
            "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing."
          },
          "stream": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "WebSocket endpoint that will accept the incoming connection for real-time audio streaming. Must be a valid WebSocket URL using either `ws://` or `wss://` (recommended). The URL must be reachable from the public internet and capable of handling the negotiated stream protocol.",
                "example": "wss://example.com"
              },
              "streamOptions": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "description": "Defines the version of the stream protocol.",
                    "default": 1,
                    "example": 1
                  },
                  "codec": {
                    "type": "string",
                    "const": "PCM",
                    "description": "Defines the audio codec/format used for the stream audio payload.\n\nCurrently, only `PCM` is supported (uncompressed raw audio). Use `sampleRate` to configure the sampling rate for the stream."
                  },
                  "sampleRate": {
                    "type": "integer",
                    "description": "Defines the audio sampling rate (Hz) used for the stream.\n\nFor calls that traverse the PSTN, audio is typically sampled at 8 kHz, so using a higher value will not improve perceived quality. \nHigher sample rates can be useful for non-PSTN scenarios (for example, SIP/streaming paths), but will increase bandwidth usage and processing load.",
                    "enum": [
                      8000,
                      16000,
                      24000,
                      44100,
                      48000,
                      96000
                    ],
                    "x-enumDescriptions": {
                      "8000": "8 kHz (standard for PSTN calls)",
                      "16000": "16 kHz (wideband audio)",
                      "24000": "24 kHz (super-wideband audio)",
                      "44100": "44.1 kHz (CD quality audio)",
                      "48000": "48 kHz (professional audio quality)",
                      "96000": "96 kHz (high-resolution audio)"
                    },
                    "default": 8000,
                    "example": 16000
                  }
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            },
            "examples": [
              {
                "endpoint": "wss://example.com",
                "streamOptions": {
                  "version": 1,
                  "codec": "PCM",
                  "sampleRate": 8000
                },
                "callHeaders": [
                  {
                    "key": "my-key",
                    "value": "my-key-value"
                  }
                ]
              }
            ]
          }
        },
        "examples": [
          {
            "type": "STREAM",
            "stream": {
              "endpoint": "wss://example.com",
              "streamOptions": {
                "version": 1,
                "codec": "PCM",
                "sampleRate": 16000
              },
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "voiceRelay": {
        "type": "object",
        "additionalProperties": false,
        "title": "Voice Relay",
        "description": "Routes the call through the Voice Relay service, enabling real-time speech-to-text (STT) and text-to-speech (TTS) via a WebSocket connection to the application backend.",
        "required": [
          "type",
          "voiceRelay"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "VOICE_RELAY",
            "description": "Connects to the Voice Relay service to enable STT and TTS services..."
          },
          "voiceRelay": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint",
              "ttsVoice",
              "sttLanguage"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "format": "uri",
                "description": "URL to the server that will accept the web-socket request",
                "example": "wss://acme.com/agent"
              },
              "enableInterruptions": {
                "type": "boolean",
                "description": "Allow \"barge-in\" during text-to-speech (TTS) playback.\n\nWhen `true`, TTS playback is interrupted as soon as inbound speech is detected, unless the currently playing content is marked as uninterruptible.\n\nWhen `false`, TTS playback continues uninterrupted, but an interruption signal is still sent over the WebSocket so the client application can choose to stop playback manually if needed.",
                "default": true,
                "example": true
              },
              "ttsVoice": {
                "type": "string",
                "description": "Name of the voice to be used when synthesizing speech. \n\nThis is the default voice used, if no override voice is provided in the web-socket TTS message.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              },
              "sttLanguage": {
                "type": "string",
                "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$",
                "description": "BCP-47 language tag used for speech-to-text transcription of the inbound audio.\n\nThis value determines which language model is used for transcription.",
                "example": "en-US"
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "VOICE_RELAY",
            "voiceRelay": {
              "endpoint": "wss://acme.com/agent",
              "enableInterruptions": true,
              "ttsVoice": "Emma",
              "sttLanguage": "en-US",
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "to": {
        "title": "To",
        "description": "Call destination - Phone Number or Stream URI",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sip"
          },
          {
            "$ref": "#/components/schemas/stream"
          },
          {
            "$ref": "#/components/schemas/voiceRelay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sip",
            "STREAM": "#/components/schemas/stream",
            "VOICE_RELAY": "#/components/schemas/voiceRelay"
          }
        }
      },
      "svamlCommands": {
        "type": "array",
        "title": "SVAML Commands",
        "description": "An ordered list of SVAML v2 (Sinch Voice Application Markup Language) commands that describe a call flow. Commands are executed sequentially in the order they are defined.\n\n**Blocking vs. non-blocking:** Some commands block execution until they complete (`pause`, `webhook`, `menu`, `gotoMenu`), while others return immediately and run in parallel (`dial`, `messages`, `amd`, `answer`, `hangup`, `startRecording`, `stopRecording`, `bridgeCall`, `stopMessages`). Each command's description specifies its behavior.\n\n**Nesting scope:** Commands that appear inside event handlers (e.g., `dial.events.onAnswer`, `messages.events.onFinish`) form independent sequences and execute in their own context — they are not continuations of the parent sequence.",
        "items": {
          "$ref": "#/components/schemas/svamlCommand"
        }
      },
      "callEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Call Events Webhook",
        "description": "Webhook to handle call events, used when callBehaviors are set to WEBHOOK",
        "properties": {
          "onAnswer": {
            "description": "SVAML commands to be executed when the call is answered",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBusy": {
            "description": "SVAML commands to be executed when the call is busy",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onReject": {
            "description": "SVAML commands to be executed when the call is rejected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onTimeout": {
            "description": "SVAML commands to be executed when the call is timed out",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onHangup": {
            "description": "SVAML commands to be executed when the call is hung up",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "SVAML commands to be executed when the call fails",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "dial": {
        "type": "object",
        "additionalProperties": false,
        "title": "Dial",
        "description": "Initiates a new outbound call leg within the current session.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while the call is being established in parallel. Call lifecycle events (answer, busy, reject, timeout, hangup, failure) are handled via the `events` property.\n\nThe `from` and `to` endpoint types should ideally match. If they differ, the platform attempts to convert the `from` value to be compatible with the `to` type. For example, PSTN supports only E.164 phone numbers, so a SIP address such as `sip:46701234567@acme.se` can be converted to an E.164 number. If the `from` value cannot be converted, it defaults to null (anonymous).",
        "required": [
          "command",
          "to"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "dial",
            "description": "Command to initiate a new call"
          },
          "callName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "outgoing",
            "description": "Identifier for this call leg within the session. Must be unique across all active call legs in the session.\n\nOther commands (e.g., `hangup`) can reference this name to target this specific leg."
          },
          "from": {
            "$ref": "#/components/schemas/from"
          },
          "to": {
            "$ref": "#/components/schemas/to"
          },
          "dialTimeoutDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "description": "Maximum time in seconds to wait for the call to be answered. If the timeout expires without an answer, the `onTimeout` event is triggered.",
            "example": 15
          },
          "maxCallDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 14400,
            "description": "Maximum duration of the call in seconds. The call is terminated automatically when this limit is reached.",
            "example": 3600
          },
          "events": {
            "$ref": "#/components/schemas/callEvents"
          }
        },
        "examples": [
          {
            "command": "dial",
            "callName": "destination",
            "from": {
              "type": "PHONE",
              "phone": {
                "number": "+15551234567"
              }
            },
            "to": {
              "type": "PHONE",
              "phone": {
                "number": "+15559876543"
              }
            },
            "dialTimeoutDurationSeconds": 30,
            "maxCallDurationSeconds": 3600,
            "events": {
              "onAnswer": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Your call has connected.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "messageSay": {
        "type": "object",
        "title": "Say Message",
        "description": "A text-to-speech (TTS) message item. The platform synthesizes the provided text into speech and plays it on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "say"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SAY",
            "description": "Text-to-speech message to be played during the call."
          },
          "say": {
            "type": "object",
            "additionalProperties": false,
            "title": "Say",
            "required": [
              "text",
              "voiceName"
            ],
            "properties": {
              "text": {
                "type": "string",
                "description": "The text to be synthesized into speech.\n\nIf `format` is `TEXT` (default), provide plain text.\nIf `format` is `SSML`, provide a valid SSML document (for example, `<speak>...</speak>`).",
                "maxLength": 600,
                "example": "Hello world"
              },
              "format": {
                "type": "string",
                "description": "Format of the message",
                "enum": [
                  "TEXT",
                  "SSML"
                ],
                "x-enumDescriptions": {
                  "TEXT": "Plain text format for the message.",
                  "SSML": "Speech Synthesis Markup Language format for advanced text-to-speech control."
                },
                "default": "TEXT"
              },
              "voiceName": {
                "type": "string",
                "description": "The name of the voice to use for text-to-speech synthesis.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SAY",
            "say": {
              "text": "Hello, this is a test message",
              "voiceName": "Emma"
            }
          },
          {
            "type": "SAY",
            "say": {
              "text": "<speak><prosody volume=\"-6dB\">Hello, this is a test message</prosody></speak>",
              "format": "SSML",
              "voiceName": "Brian"
            }
          }
        ]
      },
      "messagePlay": {
        "type": "object",
        "title": "Play Message",
        "description": "An audio file playback message item. The platform fetches and plays the audio file at the provided URL on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "play"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PLAY",
            "description": "Audio file playback during the call."
          },
          "play": {
            "type": "object",
            "additionalProperties": false,
            "title": "Play",
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "description": "URL of the media to send"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PLAY",
            "play": {
              "url": "https://example.com/media.mp3"
            }
          }
        ]
      },
      "message": {
        "type": "object",
        "title": "Message",
        "description": "A single message item. The required payload depends on `type`.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/messageSay"
          },
          {
            "$ref": "#/components/schemas/messagePlay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "SAY": "#/components/schemas/messageSay",
            "PLAY": "#/components/schemas/messagePlay"
          }
        }
      },
      "typesOfMessages": {
        "type": "array",
        "title": "Message List",
        "description": "Ordered list of messages to play.",
        "minItems": 1,
        "maxItems": 10,
        "items": {
          "$ref": "#/components/schemas/message"
        }
      },
      "messageEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Message Events",
        "description": "SVAML commands to execute based on message playback outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when all messages in the sequence have finished playing.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "messages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Messages",
        "description": "Plays one or more messages on the call. Multiple messages in the array are played sequentially in order.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while messages play in parallel. \nPlayback outcomes are handled via the `events` property. The `onFinish` event can be used to run a command after all messages complete.",
        "required": [
          "command",
          "messages"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "messages",
            "description": "Command to play a message on the channel"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message for identification and reference within the call session.\n\nThis name is used to uniquely identify the message and must be unique within the current call session.\nThis name can be referenced in other commands (e.g., `stopMessages`) to control this specific message.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-messages"
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          },
          "events": {
            "$ref": "#/components/schemas/messageEvents"
          }
        },
        "examples": [
          {
            "command": "messages",
            "messagesName": "greeting-sequence",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Hello! Your call is being connected.",
                  "voiceName": "Emma"
                }
              },
              {
                "type": "PLAY",
                "play": {
                  "url": "https://example.com/audio/hold-music.mp3"
                }
              },
              {
                "type": "SAY",
                "say": {
                  "text": "<speak><prosody volume=\"-6dB\">Thank you for waiting.</prosody></speak>",
                  "format": "SSML",
                  "voiceName": "Emma"
                }
              }
            ]
          }
        ]
      },
      "stopMessages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Messages",
        "description": "Stops a message sequence previously started by a `messages` command. Use `messagesName` to target a specific sequence and `flags` to control whether only the current message or all queued messages are cancelled. \n\nThis is a non-blocking command.",
        "required": [
          "command",
          "messagesName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopMessages",
            "description": "Command to stop playing messages"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message sequence to stop, as set by `messagesName` in the `messages` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$"
          },
          "flags": {
            "type": "string",
            "description": "Controls how much of the sequence is stopped — only the currently playing message or all remaining queued messages.",
            "default": "ALL_FROM_NOW_ON",
            "enum": [
              "ONLY_PLAYING",
              "ALL_FROM_NOW_ON"
            ],
            "x-enumDescriptions": {
              "ONLY_PLAYING": "Stops only the currently playing message. Queued messages will continue to play.",
              "ALL_FROM_NOW_ON": "Stops the currently playing message and cancels all queued messages."
            }
          }
        },
        "examples": [
          {
            "command": "stopMessages",
            "messagesName": "my-messages",
            "flags": "ONLY_PLAYING"
          }
        ]
      },
      "webhookFallbackUrl": {
        "title": "Webhook Fallback URL",
        "type": "string",
        "format": "uri",
        "description": "Fallback webhook URL used when the primary webhook URL fails.\n\nA failed request is re-sent to this URL immediately. After repeated consecutive failures of the primary URL, requests are sent only here until the primary URL recovers.\n\nSee *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "examples": [
          "https://example.com/fallback"
        ]
      },
      "webhook": {
        "type": "object",
        "additionalProperties": false,
        "title": "Webhook",
        "description": "Triggers a mid-call webhook to the application backend, allowing it to return a new set of SVAML commands that control the remainder of the call flow.\n\nThis is a blocking command — execution pauses until a response is received from the webhook endpoint. The next command in the sequence runs only after the backend responds. Webhook requests use a 5-second timeout. If a `fallbackUrl` is provided, a failed request is re-sent to it — see *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "required": [
          "command",
          "webhookName",
          "url"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "webhook",
            "description": "Command to trigger a mid-call webhook"
          },
          "webhookName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^\\S+$",
            "description": "Name for this webhook event. When triggered, the webhook request's `event` property will contain this name prepended with `call.webhook.`.\n\nFor example, if `webhookName` is set to `\"my.custom.event\"`, the event will be delivered as `\"call.webhook.my.custom.event\"`."
          },
          "url": {
            "type": "string",
            "description": "URL of the webhook endpoint to send the mid-call event to.",
            "format": "uri"
          },
          "fallbackUrl": {
            "$ref": "#/components/schemas/webhookFallbackUrl"
          }
        },
        "examples": [
          {
            "command": "webhook",
            "webhookName": "my.custom.event",
            "url": "https://example.com/webhook",
            "fallbackUrl": "https://example.com/fallback"
          }
        ]
      },
      "hangup": {
        "type": "object",
        "additionalProperties": false,
        "description": "Ends a call leg. This is a non-blocking command — execution continues to the next command in the sequence even though the call has been ended. The `onHangup` event is triggered for the call leg that was ended.\n\nAny subsequent commands that target the ended call leg (such as `messages` or other media commands) are valid but will not be executed. Commands that operate independently — such as initiating a new call with `dial` — will execute normally. This makes it possible, for example, to end one call and immediately start another within the same sequence.",
        "title": "Hangup",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "hangup",
            "description": "Hangup call"
          },
          "callName": {
            "type": "string",
            "description": "Name of the call leg to end, as set by `callName` in the `dial` command.\n\nIf omitted, the current call leg is ended.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "origin"
          }
        },
        "examples": [
          {
            "command": "hangup",
            "callName": "origin"
          }
        ]
      },
      "answer": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answer",
        "description": "Answers an inbound call leg. This is a non-blocking command — execution continues to the next command in the sequence immediately after the answer is initiated.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "answer",
            "description": "Answer call"
          }
        },
        "examples": [
          {
            "command": "answer"
          }
        ]
      },
      "pause": {
        "type": "object",
        "additionalProperties": false,
        "title": "Pause",
        "description": "Delays execution of the next command in the sequence for a specified duration. This is a blocking command — no further commands execute until the pause completes.\n\nThe pause does not affect call audio; the call remains connected and audio continues uninterrupted.",
        "required": [
          "command",
          "durationMilliseconds"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "pause",
            "description": "Pause execution."
          },
          "durationMilliseconds": {
            "type": "integer",
            "minimum": 1,
            "description": "Duration of the pause in milliseconds.",
            "example": 1000
          }
        },
        "examples": [
          {
            "command": "pause",
            "durationMilliseconds": 1500
          }
        ]
      },
      "recordingFormat": {
        "title": "Recording Format",
        "description": "Audio format for this recording.",
        "type": "string",
        "enum": [
          "MP3",
          "WAV"
        ],
        "x-enumDescriptions": {
          "MP3": "MPEG Audio Layer III compressed audio format.",
          "WAV": "Waveform Audio File Format, uncompressed audio."
        },
        "default": "MP3",
        "examples": [
          "MP3"
        ]
      },
      "recordingType": {
        "title": "Recording Type",
        "description": "The type of recording to perform.",
        "type": "string",
        "enum": [
          "COMBINED",
          "INBOUND",
          "OUTBOUND"
        ],
        "x-enumDescriptions": {
          "COMBINED": "Record inbound and outbound voice streams.",
          "INBOUND": "Record inbound voice stream only.",
          "OUTBOUND": "Record outbound voice stream only."
        },
        "default": "COMBINED"
      },
      "recordingDestination": {
        "title": "Recording Destination",
        "type": "string",
        "description": "Select target service to receive recorded and transcribed files",
        "enum": [
          "AWS",
          "GCP",
          "AZURE"
        ],
        "x-enumDescriptions": {
          "AWS": "Store recordings in Amazon Web Services S3 bucket. Use `s3` as schema for the URL.",
          "GCP": "Store recordings in Google Cloud Platform Storage. Use `gs` as schema for the URL.",
          "AZURE": "Store recordings in Microsoft Azure Blob Storage.  Use `azure` as schema for the URL."
        },
        "default": "AWS",
        "examples": [
          "AWS"
        ]
      },
      "transcriptionOptions": {
        "title": "Transcription Options",
        "description": "Configuration for automatic speech-to-text transcription of the recording.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "isEnabled"
        ],
        "properties": {
          "isEnabled": {
            "type": "boolean",
            "description": "If true, the recording will be transcribed to text.",
            "example": true
          },
          "locale": {
            "type": "string",
            "description": "Language code in BCP-47 format.",
            "default": "en-US",
            "example": "en-US"
          }
        }
      },
      "recordingOptions": {
        "title": "Recording Options",
        "type": "object",
        "additionalProperties": false,
        "description": "Recording options for this recording.",
        "required": [
          "destination",
          "destinationUrl",
          "credentials"
        ],
        "properties": {
          "format": {
            "$ref": "#/components/schemas/recordingFormat"
          },
          "recordingType": {
            "$ref": "#/components/schemas/recordingType"
          },
          "destination": {
            "$ref": "#/components/schemas/recordingDestination"
          },
          "destinationUrl": {
            "type": "string",
            "description": "Destination URL for the recording.",
            "example": "s3://voice-recordings-prod/calls"
          },
          "credentials": {
            "type": "string",
            "description": "Credentials to third party storage.",
            "example": "accessKeyId:secretAccessKey:eu-central-1"
          },
          "transcriptionOptions": {
            "$ref": "#/components/schemas/transcriptionOptions"
          }
        }
      },
      "recordingEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Recording Events",
        "description": "SVAML commands to execute based on recording lifecycle outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when the recording is successfully stopped. Note that this does not mean that the file is delivered to the configured destination yet.\n",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "Commands to execute if the recording fails to start. If omitted, failures are silently ignored and the call flow continues.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "startRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Start Recording",
        "required": [
          "command",
          "recordingOptions"
        ],
        "description": "Starts recording the call. This is a non-blocking command — execution continues to the next command in the sequence immediately after recording begins.",
        "properties": {
          "command": {
            "type": "string",
            "const": "startRecording",
            "description": "Command to start recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Identifier for this recording within the session. Must be unique across active recordings in the session.\n\nOther commands (e.g., `stopRecording`) reference this name to target a specific recording.\n\nSetting the recording name is useful for stopping the recording using the `stopRecording` command. If name is not set, recording can only be stopped when the call is disconnected.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          },
          "recordingOptions": {
            "$ref": "#/components/schemas/recordingOptions"
          },
          "events": {
            "$ref": "#/components/schemas/recordingEvents"
          }
        },
        "examples": [
          {
            "command": "startRecording",
            "recordingName": "customer-support-recording",
            "recordingOptions": {
              "format": "MP3",
              "recordingType": "COMBINED",
              "destination": "AWS",
              "destinationUrl": "s3://voice-recordings-prod/calls",
              "credentials": "accessKeyId:secretAccessKey:eu-central-1",
              "transcriptionOptions": {
                "isEnabled": true,
                "locale": "en-US"
              }
            },
            "events": {
              "onFinish": [
                {
                  "command": "hangup"
                }
              ],
              "onFailure": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Recording could not be started for this call.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "stopRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Recording",
        "description": "Stops a recording previously started by a `startRecording` command. This is a non-blocking command — execution continues to the next command in the sequence immediately after the stop is initiated.",
        "required": [
          "command",
          "recordingName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopRecording",
            "description": "Command to stop recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Name of the recording to stop, as set by `recordingName` in the `startRecording` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          }
        }
      },
      "bridgeCall": {
        "type": "object",
        "additionalProperties": false,
        "title": "Add call to bridge",
        "description": "Adds the current call to a bridge, enabling bidirectional audio communication with other calls in the same session. This is a non-blocking command — execution continues to the next command in the sequence immediately after the call joins the bridge.\n\nBridges are created automatically when referenced by name. If a bridge with the specified name already exists, the call joins that bridge; otherwise, a new bridge is created.",
        "required": [
          "command",
          "bridgeName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "bridgeCall",
            "description": "Command to add the call to a bridge"
          },
          "bridgeName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "description": "Name of the bridge to join. If no bridge with this name exists in the session, a new one is created automatically."
          }
        },
        "examples": [
          {
            "command": "bridgeCall",
            "bridgeName": "my_bridge"
          }
        ]
      },
      "menuPrompt": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Prompt",
        "description": "Prompt configuration for menu playback, including prompt messages and barge-in behavior.",
        "required": [
          "messages"
        ],
        "properties": {
          "allowBargeIn": {
            "type": "boolean",
            "description": "Controls whether input can interrupt prompt playback.\n\nWhen enabled, playback stops as soon as input is detected and the input is evaluated immediately if matching conditions are met.\n\nWhen disabled, input is still collected during playback and evaluated after playback finishes.",
            "default": true
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          }
        }
      },
      "menuItem": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Item",
        "description": "Defines a single menu step, including prompts, input handling rules, input-to-command matches, and failure handling.\n\nEach collected input is matched against the values in the `matches` property.\nIf no match succeeds, the `onFail` commands are executed.\n\nIf neither `matches` nor `onFail` is defined and the service call behavior is set to `WEBHOOK`, a webhook request is sent including the collected input.",
        "properties": {
          "prompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when this menu starts.\n\nThis prompt is also used as the repeat prompt when repeatPrompt is not defined for the menu."
          },
          "repeatPrompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when the menu is repeated.\n\nRepeats occur when input times out or when the provided input does not match any menu match item."
          },
          "inputTimeoutDurationSeconds": {
            "type": "integer",
            "description": "Maximum number of seconds to wait for user input before the input attempt times out.",
            "minimum": 1,
            "maximum": 60,
            "default": 5,
            "example": 10
          },
          "repeatCount": {
            "type": "integer",
            "description": "Maximum number of times the menu is repeated.\n\nA repeat occurs when input times out or when the provided input does not match any menu match item.",
            "minimum": 0,
            "maximum": 10,
            "default": 2,
            "example": 3
          },
          "minimumInputLength": {
            "type": "integer",
            "description": "Minimum number of input characters required before the menu evaluates the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 3
          },
          "maximumInputLength": {
            "type": "integer",
            "description": "Maximum number of input characters that triggers the menu to evaluate the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 10
          },
          "terminatingSequence": {
            "type": "string",
            "pattern": "^[0-9*#]+$",
            "description": "Character sequence that signals the end of input and triggers immediate evaluation.\n\nUseful when variable-length input is allowed and shorter valid options should be submitted without waiting for timeout or maximum length.\n\nThe terminating sequence value is included in the evaluated input.",
            "maxLength": 10
          },
          "inputMethods": {
            "type": "array",
            "description": "Input methods accepted for this menu when collecting user input.",
            "default": [
              "DTMF"
            ],
            "items": {
              "type": "string",
              "enum": [
                "DTMF"
              ],
              "x-enumDescriptions": {
                "DTMF": "Collect input from keypad tones (Dual-Tone Multi-Frequency)."
              }
            }
          },
          "matches": {
            "type": "object",
            "description": "Items matched against the collected input. Maximum number of allowed match expressions is 50.\n\nDefined as a dictionary where each property name is a literal or a regular expression string.\n\nValues are evaluated in the order they are defined.",
            "maxProperties": 50,
            "propertyNames": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "description": "A regular expression or literal string to match against the collected user input. Must not be empty.\n\nProperty keys are evaluated sequentially in the order defined. The first key that matches the input will trigger its associated SVAML commands.\n\n**Note**: Use `\\\\*` to match the DTMF star tone (*)."
            },
            "additionalProperties": {
              "$ref": "#/components/schemas/svamlCommands"
            }
          },
          "onFail": {
            "$ref": "#/components/schemas/svamlCommands",
            "description": "SVAML commands executed when the menu fails to collect a matching input.\n\nThis handler runs after the repeat limit is reached without any input matching a menu match item."
          }
        }
      },
      "menu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Run menus",
        "description": "Defines a set of named menus and executes them starting from startMenu. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\nEach menu item configures prompts, input collection, timeout handling, and repeat behavior.",
        "required": [
          "command",
          "startMenu",
          "menus"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "menu",
            "description": "Executes menu-based input collection using the configured menu definitions."
          },
          "startMenu": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "description": "Name of the menu to execute first. Must match a key in menus."
          },
          "menus": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "maxLength": 16
            },
            "description": "Map of menu definitions keyed by menu name.",
            "additionalProperties": {
              "$ref": "#/components/schemas/menuItem"
            }
          }
        },
        "examples": [
          {
            "command": "menu",
            "startMenu": "main",
            "menus": {
              "main": {
                "prompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "repeatPrompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Invalid option. Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "inputTimeoutDurationSeconds": 5,
                "repeatCount": 2,
                "minimumInputLength": 1,
                "maximumInputLength": 1,
                "inputMethods": [
                  "DTMF"
                ],
                "matches": {
                  "1": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to sales.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "sales",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15551234567"
                        }
                      }
                    }
                  ],
                  "2": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to support.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "support",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15557654321"
                        }
                      }
                    }
                  ]
                },
                "onFail": [
                  {
                    "command": "messages",
                    "messages": [
                      {
                        "type": "SAY",
                        "say": {
                          "text": "Sorry, no valid selection was received.",
                          "voiceName": "Emma"
                        }
                      }
                    ]
                  },
                  {
                    "command": "hangup"
                  }
                ]
              }
            }
          }
        ]
      },
      "gotoMenu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Goto Menu",
        "description": "Switches execution to another menu within the current menu context. The menu name must be a menu defined in the `menu` command. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\n**Important**: this command can only be called within a menu execution context.",
        "required": [
          "command",
          "menuName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "gotoMenu",
            "description": "Switch execution to another menu within the current menu context."
          },
          "menuName": {
            "type": "string",
            "description": "Name of the target menu to execute next. Must match a key in menus.",
            "minLength": 1,
            "maxLength": 16
          }
        }
      },
      "svamlCommand": {
        "title": "SVAML Command",
        "type": "object",
        "description": "A single SVAML (Sinch Voice Application Markup Language) command that controls call behavior.\n\nThe `command` property acts as a discriminator and determines which command schema applies. When multiple commands appear in a `svamlCommands` array, they execute sequentially in order.\n\n**Available commands:**\n- `dial` — Initiate an outbound call leg within the session.\n- `messages` — Play one or more TTS or audio messages on the call.\n- `stopMessages` — Stop a currently playing message sequence.\n- `webhook` — Trigger a mid-call webhook to the application backend for dynamic call control.\n- `amd` — Detect whether the call was answered by a human or an answering machine.\n- `hangup` — End the call or a specific call leg within the session.\n- `answer` — Explicitly answer an incoming call leg before executing further commands.\n- `pause` — Delay script execution without affecting call audio.\n- `startRecording` — Begin recording the call.\n- `stopRecording` — Stop an active call recording.\n- `bridgeCall` — Add the call to a named bridge for multi-party audio.\n- `menu` — Run menu-based input collection and route the call based on collected input.\n- `gotoMenu` — Switch execution to another named menu within the current menu context.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/amd"
          },
          {
            "$ref": "#/components/schemas/dial"
          },
          {
            "$ref": "#/components/schemas/messages"
          },
          {
            "$ref": "#/components/schemas/stopMessages"
          },
          {
            "$ref": "#/components/schemas/webhook"
          },
          {
            "$ref": "#/components/schemas/hangup"
          },
          {
            "$ref": "#/components/schemas/answer"
          },
          {
            "$ref": "#/components/schemas/pause"
          },
          {
            "$ref": "#/components/schemas/startRecording"
          },
          {
            "$ref": "#/components/schemas/stopRecording"
          },
          {
            "$ref": "#/components/schemas/bridgeCall"
          },
          {
            "$ref": "#/components/schemas/menu"
          },
          {
            "$ref": "#/components/schemas/gotoMenu"
          }
        ],
        "discriminator": {
          "propertyName": "command",
          "mapping": {
            "amd": "#/components/schemas/amd",
            "dial": "#/components/schemas/dial",
            "messages": "#/components/schemas/messages",
            "stopMessages": "#/components/schemas/stopMessages",
            "webhook": "#/components/schemas/webhook",
            "hangup": "#/components/schemas/hangup",
            "answer": "#/components/schemas/answer",
            "pause": "#/components/schemas/pause",
            "startRecording": "#/components/schemas/startRecording",
            "stopRecording": "#/components/schemas/stopRecording",
            "bridgeCall": "#/components/schemas/bridgeCall",
            "menu": "#/components/schemas/menu",
            "gotoMenu": "#/components/schemas/gotoMenu"
          }
        }
      },
      "amdEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "AMD Events",
        "description": "SVAML commands to execute based on the answering machine detection result. These events define different call flows depending on whether a human, machine, beep, or unknown entity answers the call.",
        "properties": {
          "onHuman": {
            "description": "SVAML commands to be executed when a human is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onMachine": {
            "description": "SVAML commands to be executed when a machine is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBeep": {
            "description": "SVAML commands to be executed when a beep is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onUnknown": {
            "description": "SVAML commands to be executed when an unknown event is detected",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      }
    }
  }
}
```

### `messages`

Play audio or text-to-speech messages to participants.

```json
{
  "command": "messages",
  "messagesName": "greeting-sequence",
  "messages": [
    {
      "type": "SAY",
      "say": {
        "text": "Hello! Your call is being connected.",
        "voiceName": "Emma"
      }
    },
    {
      "type": "PLAY",
      "play": {
        "url": "https://example.com/audio/hold-music.mp3"
      }
    },
    {
      "type": "SAY",
      "say": {
        "text": "<speak><prosody volume=\"-6dB\">Thank you for waiting.</prosody></speak>",
        "format": "SSML",
        "voiceName": "Emma"
      }
    }
  ]
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/messages",
  "components": {
    "schemas": {
      "messageSay": {
        "type": "object",
        "title": "Say Message",
        "description": "A text-to-speech (TTS) message item. The platform synthesizes the provided text into speech and plays it on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "say"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SAY",
            "description": "Text-to-speech message to be played during the call."
          },
          "say": {
            "type": "object",
            "additionalProperties": false,
            "title": "Say",
            "required": [
              "text",
              "voiceName"
            ],
            "properties": {
              "text": {
                "type": "string",
                "description": "The text to be synthesized into speech.\n\nIf `format` is `TEXT` (default), provide plain text.\nIf `format` is `SSML`, provide a valid SSML document (for example, `<speak>...</speak>`).",
                "maxLength": 600,
                "example": "Hello world"
              },
              "format": {
                "type": "string",
                "description": "Format of the message",
                "enum": [
                  "TEXT",
                  "SSML"
                ],
                "x-enumDescriptions": {
                  "TEXT": "Plain text format for the message.",
                  "SSML": "Speech Synthesis Markup Language format for advanced text-to-speech control."
                },
                "default": "TEXT"
              },
              "voiceName": {
                "type": "string",
                "description": "The name of the voice to use for text-to-speech synthesis.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SAY",
            "say": {
              "text": "Hello, this is a test message",
              "voiceName": "Emma"
            }
          },
          {
            "type": "SAY",
            "say": {
              "text": "<speak><prosody volume=\"-6dB\">Hello, this is a test message</prosody></speak>",
              "format": "SSML",
              "voiceName": "Brian"
            }
          }
        ]
      },
      "messagePlay": {
        "type": "object",
        "title": "Play Message",
        "description": "An audio file playback message item. The platform fetches and plays the audio file at the provided URL on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "play"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PLAY",
            "description": "Audio file playback during the call."
          },
          "play": {
            "type": "object",
            "additionalProperties": false,
            "title": "Play",
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "description": "URL of the media to send"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PLAY",
            "play": {
              "url": "https://example.com/media.mp3"
            }
          }
        ]
      },
      "message": {
        "type": "object",
        "title": "Message",
        "description": "A single message item. The required payload depends on `type`.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/messageSay"
          },
          {
            "$ref": "#/components/schemas/messagePlay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "SAY": "#/components/schemas/messageSay",
            "PLAY": "#/components/schemas/messagePlay"
          }
        }
      },
      "typesOfMessages": {
        "type": "array",
        "title": "Message List",
        "description": "Ordered list of messages to play.",
        "minItems": 1,
        "maxItems": 10,
        "items": {
          "$ref": "#/components/schemas/message"
        }
      },
      "svamlCommands": {
        "type": "array",
        "title": "SVAML Commands",
        "description": "An ordered list of SVAML v2 (Sinch Voice Application Markup Language) commands that describe a call flow. Commands are executed sequentially in the order they are defined.\n\n**Blocking vs. non-blocking:** Some commands block execution until they complete (`pause`, `webhook`, `menu`, `gotoMenu`), while others return immediately and run in parallel (`dial`, `messages`, `amd`, `answer`, `hangup`, `startRecording`, `stopRecording`, `bridgeCall`, `stopMessages`). Each command's description specifies its behavior.\n\n**Nesting scope:** Commands that appear inside event handlers (e.g., `dial.events.onAnswer`, `messages.events.onFinish`) form independent sequences and execute in their own context — they are not continuations of the parent sequence.",
        "items": {
          "$ref": "#/components/schemas/svamlCommand"
        }
      },
      "amdEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "AMD Events",
        "description": "SVAML commands to execute based on the answering machine detection result. These events define different call flows depending on whether a human, machine, beep, or unknown entity answers the call.",
        "properties": {
          "onHuman": {
            "description": "SVAML commands to be executed when a human is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onMachine": {
            "description": "SVAML commands to be executed when a machine is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBeep": {
            "description": "SVAML commands to be executed when a beep is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onUnknown": {
            "description": "SVAML commands to be executed when an unknown event is detected",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "amd": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answering Machine Detection",
        "description": "AMD (Answering Machine Detection) command to detect what answered the call. Possible outcomes are: human, machine, beep, or unknown.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while detection runs in parallel. Results are delivered via the `events` property.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "amd",
            "description": "Command to run Answering Machine Detection on the call"
          },
          "events": {
            "$ref": "#/components/schemas/amdEvents"
          }
        },
        "examples": [
          {
            "command": "amd",
            "events": {
              "onHuman": [
                {
                  "command": "pause",
                  "durationMilliseconds": 1000
                },
                {
                  "command": "bridgeCall",
                  "bridgeName": "my-bridge"
                }
              ],
              "onBeep": [
                {
                  "command": "messages",
                  "messagesName": "my-amd-messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Hello, this is a test message",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "phoneNumber": {
        "title": "Phone Number",
        "type": "string",
        "pattern": "^\\+[1-9]\\d{1,14}$",
        "minLength": 3,
        "maxLength": 16,
        "description": "E.164 Phone number",
        "examples": [
          "+4673522488"
        ]
      },
      "phone": {
        "type": "object",
        "additionalProperties": false,
        "title": "Phone",
        "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN).",
        "required": [
          "type",
          "phone"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PHONE",
            "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN). The number must be in E.164 format."
          },
          "phone": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "number"
            ],
            "properties": {
              "number": {
                "$ref": "#/components/schemas/phoneNumber"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PHONE",
            "phone": {
              "number": "+4673522488"
            }
          }
        ]
      },
      "sipFrom": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Origin",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Indicates the call originated from a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the originating endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "pattern": "^sips?:",
                "maxLength": 192
              },
              "displayName": {
                "type": "string",
                "description": "Display name presented to the called party as the caller identity. Transmitted as the display name part of the SIP `From` header (for example, `Alice <sip:alice@example.com>`).",
                "maxLength": 64,
                "example": "Alice"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "displayName": "Alice"
            }
          }
        ]
      },
      "from": {
        "description": "Call origin - Phone Number or SIP endpoint",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sipFrom"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sipFrom"
          }
        }
      },
      "sipCallHeaders": {
        "type": "array",
        "description": "Custom SIP headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[-A-Za-z0-9.!%*_+`'~]+$",
              "description": "Name of the SIP header.",
              "example": "X-Correlation-Id"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "description": "Value of the SIP header.",
              "example": "12345"
            }
          }
        },
        "examples": [
          [
            {
              "key": "X-Correlation-Id",
              "value": "12345"
            },
            {
              "key": "X-Call-Routing",
              "value": "forwarded"
            }
          ]
        ]
      },
      "sip": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Endpoint",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Routes the call to a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the destination endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "maxLength": 256,
                "pattern": "^sips?:"
              },
              "transport": {
                "type": "string",
                "description": "Transport protocol to use for the SIP signalling channel.\n\nIf omitted, the platform selects a default based on the URI scheme: `UDP` for `sip:` and `TLS` for `sips:`. Setting this explicitly overrides that default — for example, to force `TCP` for a `sip:` URI or to use `TLS` without switching to the `sips:` scheme.",
                "enum": [
                  "UDP",
                  "TCP",
                  "TLS"
                ],
                "x-enumDescriptions": {
                  "UDP": "Connectionless transport. Lowest overhead; suitable for most standard SIP deployments.",
                  "TCP": "Connection-oriented transport. More reliable for large SIP messages or NAT traversal scenarios.",
                  "TLS": "Encrypted transport. Provides confidentiality and integrity for SIP signalling."
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/sipCallHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "transport": "TCP",
              "callHeaders": [
                {
                  "key": "X-Correlation-Id",
                  "value": "12345"
                },
                {
                  "key": "X-Call-Routing",
                  "value": "forwarded"
                }
              ]
            }
          }
        ]
      },
      "callHeaders": {
        "type": "array",
        "description": "Custom headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]+$",
              "description": "Name of the header.",
              "example": "headerKey"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]*$",
              "description": "Value of the header.",
              "example": "headerValue"
            }
          }
        },
        "examples": [
          [
            {
              "key": "headerKey",
              "value": "headerValue"
            },
            {
              "key": "anotherKey",
              "value": "anotherValue"
            }
          ]
        ]
      },
      "stream": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stream",
        "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing.",
        "required": [
          "type",
          "stream"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "STREAM",
            "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing."
          },
          "stream": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "WebSocket endpoint that will accept the incoming connection for real-time audio streaming. Must be a valid WebSocket URL using either `ws://` or `wss://` (recommended). The URL must be reachable from the public internet and capable of handling the negotiated stream protocol.",
                "example": "wss://example.com"
              },
              "streamOptions": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "description": "Defines the version of the stream protocol.",
                    "default": 1,
                    "example": 1
                  },
                  "codec": {
                    "type": "string",
                    "const": "PCM",
                    "description": "Defines the audio codec/format used for the stream audio payload.\n\nCurrently, only `PCM` is supported (uncompressed raw audio). Use `sampleRate` to configure the sampling rate for the stream."
                  },
                  "sampleRate": {
                    "type": "integer",
                    "description": "Defines the audio sampling rate (Hz) used for the stream.\n\nFor calls that traverse the PSTN, audio is typically sampled at 8 kHz, so using a higher value will not improve perceived quality. \nHigher sample rates can be useful for non-PSTN scenarios (for example, SIP/streaming paths), but will increase bandwidth usage and processing load.",
                    "enum": [
                      8000,
                      16000,
                      24000,
                      44100,
                      48000,
                      96000
                    ],
                    "x-enumDescriptions": {
                      "8000": "8 kHz (standard for PSTN calls)",
                      "16000": "16 kHz (wideband audio)",
                      "24000": "24 kHz (super-wideband audio)",
                      "44100": "44.1 kHz (CD quality audio)",
                      "48000": "48 kHz (professional audio quality)",
                      "96000": "96 kHz (high-resolution audio)"
                    },
                    "default": 8000,
                    "example": 16000
                  }
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            },
            "examples": [
              {
                "endpoint": "wss://example.com",
                "streamOptions": {
                  "version": 1,
                  "codec": "PCM",
                  "sampleRate": 8000
                },
                "callHeaders": [
                  {
                    "key": "my-key",
                    "value": "my-key-value"
                  }
                ]
              }
            ]
          }
        },
        "examples": [
          {
            "type": "STREAM",
            "stream": {
              "endpoint": "wss://example.com",
              "streamOptions": {
                "version": 1,
                "codec": "PCM",
                "sampleRate": 16000
              },
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "voiceRelay": {
        "type": "object",
        "additionalProperties": false,
        "title": "Voice Relay",
        "description": "Routes the call through the Voice Relay service, enabling real-time speech-to-text (STT) and text-to-speech (TTS) via a WebSocket connection to the application backend.",
        "required": [
          "type",
          "voiceRelay"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "VOICE_RELAY",
            "description": "Connects to the Voice Relay service to enable STT and TTS services..."
          },
          "voiceRelay": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint",
              "ttsVoice",
              "sttLanguage"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "format": "uri",
                "description": "URL to the server that will accept the web-socket request",
                "example": "wss://acme.com/agent"
              },
              "enableInterruptions": {
                "type": "boolean",
                "description": "Allow \"barge-in\" during text-to-speech (TTS) playback.\n\nWhen `true`, TTS playback is interrupted as soon as inbound speech is detected, unless the currently playing content is marked as uninterruptible.\n\nWhen `false`, TTS playback continues uninterrupted, but an interruption signal is still sent over the WebSocket so the client application can choose to stop playback manually if needed.",
                "default": true,
                "example": true
              },
              "ttsVoice": {
                "type": "string",
                "description": "Name of the voice to be used when synthesizing speech. \n\nThis is the default voice used, if no override voice is provided in the web-socket TTS message.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              },
              "sttLanguage": {
                "type": "string",
                "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$",
                "description": "BCP-47 language tag used for speech-to-text transcription of the inbound audio.\n\nThis value determines which language model is used for transcription.",
                "example": "en-US"
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "VOICE_RELAY",
            "voiceRelay": {
              "endpoint": "wss://acme.com/agent",
              "enableInterruptions": true,
              "ttsVoice": "Emma",
              "sttLanguage": "en-US",
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "to": {
        "title": "To",
        "description": "Call destination - Phone Number or Stream URI",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sip"
          },
          {
            "$ref": "#/components/schemas/stream"
          },
          {
            "$ref": "#/components/schemas/voiceRelay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sip",
            "STREAM": "#/components/schemas/stream",
            "VOICE_RELAY": "#/components/schemas/voiceRelay"
          }
        }
      },
      "callEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Call Events Webhook",
        "description": "Webhook to handle call events, used when callBehaviors are set to WEBHOOK",
        "properties": {
          "onAnswer": {
            "description": "SVAML commands to be executed when the call is answered",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBusy": {
            "description": "SVAML commands to be executed when the call is busy",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onReject": {
            "description": "SVAML commands to be executed when the call is rejected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onTimeout": {
            "description": "SVAML commands to be executed when the call is timed out",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onHangup": {
            "description": "SVAML commands to be executed when the call is hung up",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "SVAML commands to be executed when the call fails",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "dial": {
        "type": "object",
        "additionalProperties": false,
        "title": "Dial",
        "description": "Initiates a new outbound call leg within the current session.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while the call is being established in parallel. Call lifecycle events (answer, busy, reject, timeout, hangup, failure) are handled via the `events` property.\n\nThe `from` and `to` endpoint types should ideally match. If they differ, the platform attempts to convert the `from` value to be compatible with the `to` type. For example, PSTN supports only E.164 phone numbers, so a SIP address such as `sip:46701234567@acme.se` can be converted to an E.164 number. If the `from` value cannot be converted, it defaults to null (anonymous).",
        "required": [
          "command",
          "to"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "dial",
            "description": "Command to initiate a new call"
          },
          "callName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "outgoing",
            "description": "Identifier for this call leg within the session. Must be unique across all active call legs in the session.\n\nOther commands (e.g., `hangup`) can reference this name to target this specific leg."
          },
          "from": {
            "$ref": "#/components/schemas/from"
          },
          "to": {
            "$ref": "#/components/schemas/to"
          },
          "dialTimeoutDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "description": "Maximum time in seconds to wait for the call to be answered. If the timeout expires without an answer, the `onTimeout` event is triggered.",
            "example": 15
          },
          "maxCallDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 14400,
            "description": "Maximum duration of the call in seconds. The call is terminated automatically when this limit is reached.",
            "example": 3600
          },
          "events": {
            "$ref": "#/components/schemas/callEvents"
          }
        },
        "examples": [
          {
            "command": "dial",
            "callName": "destination",
            "from": {
              "type": "PHONE",
              "phone": {
                "number": "+15551234567"
              }
            },
            "to": {
              "type": "PHONE",
              "phone": {
                "number": "+15559876543"
              }
            },
            "dialTimeoutDurationSeconds": 30,
            "maxCallDurationSeconds": 3600,
            "events": {
              "onAnswer": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Your call has connected.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "messages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Messages",
        "description": "Plays one or more messages on the call. Multiple messages in the array are played sequentially in order.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while messages play in parallel. \nPlayback outcomes are handled via the `events` property. The `onFinish` event can be used to run a command after all messages complete.",
        "required": [
          "command",
          "messages"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "messages",
            "description": "Command to play a message on the channel"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message for identification and reference within the call session.\n\nThis name is used to uniquely identify the message and must be unique within the current call session.\nThis name can be referenced in other commands (e.g., `stopMessages`) to control this specific message.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-messages"
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          },
          "events": {
            "$ref": "#/components/schemas/messageEvents"
          }
        },
        "examples": [
          {
            "command": "messages",
            "messagesName": "greeting-sequence",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Hello! Your call is being connected.",
                  "voiceName": "Emma"
                }
              },
              {
                "type": "PLAY",
                "play": {
                  "url": "https://example.com/audio/hold-music.mp3"
                }
              },
              {
                "type": "SAY",
                "say": {
                  "text": "<speak><prosody volume=\"-6dB\">Thank you for waiting.</prosody></speak>",
                  "format": "SSML",
                  "voiceName": "Emma"
                }
              }
            ]
          }
        ]
      },
      "stopMessages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Messages",
        "description": "Stops a message sequence previously started by a `messages` command. Use `messagesName` to target a specific sequence and `flags` to control whether only the current message or all queued messages are cancelled. \n\nThis is a non-blocking command.",
        "required": [
          "command",
          "messagesName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopMessages",
            "description": "Command to stop playing messages"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message sequence to stop, as set by `messagesName` in the `messages` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$"
          },
          "flags": {
            "type": "string",
            "description": "Controls how much of the sequence is stopped — only the currently playing message or all remaining queued messages.",
            "default": "ALL_FROM_NOW_ON",
            "enum": [
              "ONLY_PLAYING",
              "ALL_FROM_NOW_ON"
            ],
            "x-enumDescriptions": {
              "ONLY_PLAYING": "Stops only the currently playing message. Queued messages will continue to play.",
              "ALL_FROM_NOW_ON": "Stops the currently playing message and cancels all queued messages."
            }
          }
        },
        "examples": [
          {
            "command": "stopMessages",
            "messagesName": "my-messages",
            "flags": "ONLY_PLAYING"
          }
        ]
      },
      "webhookFallbackUrl": {
        "title": "Webhook Fallback URL",
        "type": "string",
        "format": "uri",
        "description": "Fallback webhook URL used when the primary webhook URL fails.\n\nA failed request is re-sent to this URL immediately. After repeated consecutive failures of the primary URL, requests are sent only here until the primary URL recovers.\n\nSee *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "examples": [
          "https://example.com/fallback"
        ]
      },
      "webhook": {
        "type": "object",
        "additionalProperties": false,
        "title": "Webhook",
        "description": "Triggers a mid-call webhook to the application backend, allowing it to return a new set of SVAML commands that control the remainder of the call flow.\n\nThis is a blocking command — execution pauses until a response is received from the webhook endpoint. The next command in the sequence runs only after the backend responds. Webhook requests use a 5-second timeout. If a `fallbackUrl` is provided, a failed request is re-sent to it — see *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "required": [
          "command",
          "webhookName",
          "url"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "webhook",
            "description": "Command to trigger a mid-call webhook"
          },
          "webhookName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^\\S+$",
            "description": "Name for this webhook event. When triggered, the webhook request's `event` property will contain this name prepended with `call.webhook.`.\n\nFor example, if `webhookName` is set to `\"my.custom.event\"`, the event will be delivered as `\"call.webhook.my.custom.event\"`."
          },
          "url": {
            "type": "string",
            "description": "URL of the webhook endpoint to send the mid-call event to.",
            "format": "uri"
          },
          "fallbackUrl": {
            "$ref": "#/components/schemas/webhookFallbackUrl"
          }
        },
        "examples": [
          {
            "command": "webhook",
            "webhookName": "my.custom.event",
            "url": "https://example.com/webhook",
            "fallbackUrl": "https://example.com/fallback"
          }
        ]
      },
      "hangup": {
        "type": "object",
        "additionalProperties": false,
        "description": "Ends a call leg. This is a non-blocking command — execution continues to the next command in the sequence even though the call has been ended. The `onHangup` event is triggered for the call leg that was ended.\n\nAny subsequent commands that target the ended call leg (such as `messages` or other media commands) are valid but will not be executed. Commands that operate independently — such as initiating a new call with `dial` — will execute normally. This makes it possible, for example, to end one call and immediately start another within the same sequence.",
        "title": "Hangup",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "hangup",
            "description": "Hangup call"
          },
          "callName": {
            "type": "string",
            "description": "Name of the call leg to end, as set by `callName` in the `dial` command.\n\nIf omitted, the current call leg is ended.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "origin"
          }
        },
        "examples": [
          {
            "command": "hangup",
            "callName": "origin"
          }
        ]
      },
      "answer": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answer",
        "description": "Answers an inbound call leg. This is a non-blocking command — execution continues to the next command in the sequence immediately after the answer is initiated.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "answer",
            "description": "Answer call"
          }
        },
        "examples": [
          {
            "command": "answer"
          }
        ]
      },
      "pause": {
        "type": "object",
        "additionalProperties": false,
        "title": "Pause",
        "description": "Delays execution of the next command in the sequence for a specified duration. This is a blocking command — no further commands execute until the pause completes.\n\nThe pause does not affect call audio; the call remains connected and audio continues uninterrupted.",
        "required": [
          "command",
          "durationMilliseconds"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "pause",
            "description": "Pause execution."
          },
          "durationMilliseconds": {
            "type": "integer",
            "minimum": 1,
            "description": "Duration of the pause in milliseconds.",
            "example": 1000
          }
        },
        "examples": [
          {
            "command": "pause",
            "durationMilliseconds": 1500
          }
        ]
      },
      "recordingFormat": {
        "title": "Recording Format",
        "description": "Audio format for this recording.",
        "type": "string",
        "enum": [
          "MP3",
          "WAV"
        ],
        "x-enumDescriptions": {
          "MP3": "MPEG Audio Layer III compressed audio format.",
          "WAV": "Waveform Audio File Format, uncompressed audio."
        },
        "default": "MP3",
        "examples": [
          "MP3"
        ]
      },
      "recordingType": {
        "title": "Recording Type",
        "description": "The type of recording to perform.",
        "type": "string",
        "enum": [
          "COMBINED",
          "INBOUND",
          "OUTBOUND"
        ],
        "x-enumDescriptions": {
          "COMBINED": "Record inbound and outbound voice streams.",
          "INBOUND": "Record inbound voice stream only.",
          "OUTBOUND": "Record outbound voice stream only."
        },
        "default": "COMBINED"
      },
      "recordingDestination": {
        "title": "Recording Destination",
        "type": "string",
        "description": "Select target service to receive recorded and transcribed files",
        "enum": [
          "AWS",
          "GCP",
          "AZURE"
        ],
        "x-enumDescriptions": {
          "AWS": "Store recordings in Amazon Web Services S3 bucket. Use `s3` as schema for the URL.",
          "GCP": "Store recordings in Google Cloud Platform Storage. Use `gs` as schema for the URL.",
          "AZURE": "Store recordings in Microsoft Azure Blob Storage.  Use `azure` as schema for the URL."
        },
        "default": "AWS",
        "examples": [
          "AWS"
        ]
      },
      "transcriptionOptions": {
        "title": "Transcription Options",
        "description": "Configuration for automatic speech-to-text transcription of the recording.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "isEnabled"
        ],
        "properties": {
          "isEnabled": {
            "type": "boolean",
            "description": "If true, the recording will be transcribed to text.",
            "example": true
          },
          "locale": {
            "type": "string",
            "description": "Language code in BCP-47 format.",
            "default": "en-US",
            "example": "en-US"
          }
        }
      },
      "recordingOptions": {
        "title": "Recording Options",
        "type": "object",
        "additionalProperties": false,
        "description": "Recording options for this recording.",
        "required": [
          "destination",
          "destinationUrl",
          "credentials"
        ],
        "properties": {
          "format": {
            "$ref": "#/components/schemas/recordingFormat"
          },
          "recordingType": {
            "$ref": "#/components/schemas/recordingType"
          },
          "destination": {
            "$ref": "#/components/schemas/recordingDestination"
          },
          "destinationUrl": {
            "type": "string",
            "description": "Destination URL for the recording.",
            "example": "s3://voice-recordings-prod/calls"
          },
          "credentials": {
            "type": "string",
            "description": "Credentials to third party storage.",
            "example": "accessKeyId:secretAccessKey:eu-central-1"
          },
          "transcriptionOptions": {
            "$ref": "#/components/schemas/transcriptionOptions"
          }
        }
      },
      "recordingEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Recording Events",
        "description": "SVAML commands to execute based on recording lifecycle outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when the recording is successfully stopped. Note that this does not mean that the file is delivered to the configured destination yet.\n",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "Commands to execute if the recording fails to start. If omitted, failures are silently ignored and the call flow continues.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "startRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Start Recording",
        "required": [
          "command",
          "recordingOptions"
        ],
        "description": "Starts recording the call. This is a non-blocking command — execution continues to the next command in the sequence immediately after recording begins.",
        "properties": {
          "command": {
            "type": "string",
            "const": "startRecording",
            "description": "Command to start recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Identifier for this recording within the session. Must be unique across active recordings in the session.\n\nOther commands (e.g., `stopRecording`) reference this name to target a specific recording.\n\nSetting the recording name is useful for stopping the recording using the `stopRecording` command. If name is not set, recording can only be stopped when the call is disconnected.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          },
          "recordingOptions": {
            "$ref": "#/components/schemas/recordingOptions"
          },
          "events": {
            "$ref": "#/components/schemas/recordingEvents"
          }
        },
        "examples": [
          {
            "command": "startRecording",
            "recordingName": "customer-support-recording",
            "recordingOptions": {
              "format": "MP3",
              "recordingType": "COMBINED",
              "destination": "AWS",
              "destinationUrl": "s3://voice-recordings-prod/calls",
              "credentials": "accessKeyId:secretAccessKey:eu-central-1",
              "transcriptionOptions": {
                "isEnabled": true,
                "locale": "en-US"
              }
            },
            "events": {
              "onFinish": [
                {
                  "command": "hangup"
                }
              ],
              "onFailure": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Recording could not be started for this call.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "stopRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Recording",
        "description": "Stops a recording previously started by a `startRecording` command. This is a non-blocking command — execution continues to the next command in the sequence immediately after the stop is initiated.",
        "required": [
          "command",
          "recordingName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopRecording",
            "description": "Command to stop recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Name of the recording to stop, as set by `recordingName` in the `startRecording` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          }
        }
      },
      "bridgeCall": {
        "type": "object",
        "additionalProperties": false,
        "title": "Add call to bridge",
        "description": "Adds the current call to a bridge, enabling bidirectional audio communication with other calls in the same session. This is a non-blocking command — execution continues to the next command in the sequence immediately after the call joins the bridge.\n\nBridges are created automatically when referenced by name. If a bridge with the specified name already exists, the call joins that bridge; otherwise, a new bridge is created.",
        "required": [
          "command",
          "bridgeName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "bridgeCall",
            "description": "Command to add the call to a bridge"
          },
          "bridgeName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "description": "Name of the bridge to join. If no bridge with this name exists in the session, a new one is created automatically."
          }
        },
        "examples": [
          {
            "command": "bridgeCall",
            "bridgeName": "my_bridge"
          }
        ]
      },
      "menuPrompt": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Prompt",
        "description": "Prompt configuration for menu playback, including prompt messages and barge-in behavior.",
        "required": [
          "messages"
        ],
        "properties": {
          "allowBargeIn": {
            "type": "boolean",
            "description": "Controls whether input can interrupt prompt playback.\n\nWhen enabled, playback stops as soon as input is detected and the input is evaluated immediately if matching conditions are met.\n\nWhen disabled, input is still collected during playback and evaluated after playback finishes.",
            "default": true
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          }
        }
      },
      "menuItem": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Item",
        "description": "Defines a single menu step, including prompts, input handling rules, input-to-command matches, and failure handling.\n\nEach collected input is matched against the values in the `matches` property.\nIf no match succeeds, the `onFail` commands are executed.\n\nIf neither `matches` nor `onFail` is defined and the service call behavior is set to `WEBHOOK`, a webhook request is sent including the collected input.",
        "properties": {
          "prompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when this menu starts.\n\nThis prompt is also used as the repeat prompt when repeatPrompt is not defined for the menu."
          },
          "repeatPrompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when the menu is repeated.\n\nRepeats occur when input times out or when the provided input does not match any menu match item."
          },
          "inputTimeoutDurationSeconds": {
            "type": "integer",
            "description": "Maximum number of seconds to wait for user input before the input attempt times out.",
            "minimum": 1,
            "maximum": 60,
            "default": 5,
            "example": 10
          },
          "repeatCount": {
            "type": "integer",
            "description": "Maximum number of times the menu is repeated.\n\nA repeat occurs when input times out or when the provided input does not match any menu match item.",
            "minimum": 0,
            "maximum": 10,
            "default": 2,
            "example": 3
          },
          "minimumInputLength": {
            "type": "integer",
            "description": "Minimum number of input characters required before the menu evaluates the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 3
          },
          "maximumInputLength": {
            "type": "integer",
            "description": "Maximum number of input characters that triggers the menu to evaluate the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 10
          },
          "terminatingSequence": {
            "type": "string",
            "pattern": "^[0-9*#]+$",
            "description": "Character sequence that signals the end of input and triggers immediate evaluation.\n\nUseful when variable-length input is allowed and shorter valid options should be submitted without waiting for timeout or maximum length.\n\nThe terminating sequence value is included in the evaluated input.",
            "maxLength": 10
          },
          "inputMethods": {
            "type": "array",
            "description": "Input methods accepted for this menu when collecting user input.",
            "default": [
              "DTMF"
            ],
            "items": {
              "type": "string",
              "enum": [
                "DTMF"
              ],
              "x-enumDescriptions": {
                "DTMF": "Collect input from keypad tones (Dual-Tone Multi-Frequency)."
              }
            }
          },
          "matches": {
            "type": "object",
            "description": "Items matched against the collected input. Maximum number of allowed match expressions is 50.\n\nDefined as a dictionary where each property name is a literal or a regular expression string.\n\nValues are evaluated in the order they are defined.",
            "maxProperties": 50,
            "propertyNames": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "description": "A regular expression or literal string to match against the collected user input. Must not be empty.\n\nProperty keys are evaluated sequentially in the order defined. The first key that matches the input will trigger its associated SVAML commands.\n\n**Note**: Use `\\\\*` to match the DTMF star tone (*)."
            },
            "additionalProperties": {
              "$ref": "#/components/schemas/svamlCommands"
            }
          },
          "onFail": {
            "$ref": "#/components/schemas/svamlCommands",
            "description": "SVAML commands executed when the menu fails to collect a matching input.\n\nThis handler runs after the repeat limit is reached without any input matching a menu match item."
          }
        }
      },
      "menu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Run menus",
        "description": "Defines a set of named menus and executes them starting from startMenu. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\nEach menu item configures prompts, input collection, timeout handling, and repeat behavior.",
        "required": [
          "command",
          "startMenu",
          "menus"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "menu",
            "description": "Executes menu-based input collection using the configured menu definitions."
          },
          "startMenu": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "description": "Name of the menu to execute first. Must match a key in menus."
          },
          "menus": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "maxLength": 16
            },
            "description": "Map of menu definitions keyed by menu name.",
            "additionalProperties": {
              "$ref": "#/components/schemas/menuItem"
            }
          }
        },
        "examples": [
          {
            "command": "menu",
            "startMenu": "main",
            "menus": {
              "main": {
                "prompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "repeatPrompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Invalid option. Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "inputTimeoutDurationSeconds": 5,
                "repeatCount": 2,
                "minimumInputLength": 1,
                "maximumInputLength": 1,
                "inputMethods": [
                  "DTMF"
                ],
                "matches": {
                  "1": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to sales.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "sales",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15551234567"
                        }
                      }
                    }
                  ],
                  "2": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to support.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "support",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15557654321"
                        }
                      }
                    }
                  ]
                },
                "onFail": [
                  {
                    "command": "messages",
                    "messages": [
                      {
                        "type": "SAY",
                        "say": {
                          "text": "Sorry, no valid selection was received.",
                          "voiceName": "Emma"
                        }
                      }
                    ]
                  },
                  {
                    "command": "hangup"
                  }
                ]
              }
            }
          }
        ]
      },
      "gotoMenu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Goto Menu",
        "description": "Switches execution to another menu within the current menu context. The menu name must be a menu defined in the `menu` command. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\n**Important**: this command can only be called within a menu execution context.",
        "required": [
          "command",
          "menuName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "gotoMenu",
            "description": "Switch execution to another menu within the current menu context."
          },
          "menuName": {
            "type": "string",
            "description": "Name of the target menu to execute next. Must match a key in menus.",
            "minLength": 1,
            "maxLength": 16
          }
        }
      },
      "svamlCommand": {
        "title": "SVAML Command",
        "type": "object",
        "description": "A single SVAML (Sinch Voice Application Markup Language) command that controls call behavior.\n\nThe `command` property acts as a discriminator and determines which command schema applies. When multiple commands appear in a `svamlCommands` array, they execute sequentially in order.\n\n**Available commands:**\n- `dial` — Initiate an outbound call leg within the session.\n- `messages` — Play one or more TTS or audio messages on the call.\n- `stopMessages` — Stop a currently playing message sequence.\n- `webhook` — Trigger a mid-call webhook to the application backend for dynamic call control.\n- `amd` — Detect whether the call was answered by a human or an answering machine.\n- `hangup` — End the call or a specific call leg within the session.\n- `answer` — Explicitly answer an incoming call leg before executing further commands.\n- `pause` — Delay script execution without affecting call audio.\n- `startRecording` — Begin recording the call.\n- `stopRecording` — Stop an active call recording.\n- `bridgeCall` — Add the call to a named bridge for multi-party audio.\n- `menu` — Run menu-based input collection and route the call based on collected input.\n- `gotoMenu` — Switch execution to another named menu within the current menu context.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/amd"
          },
          {
            "$ref": "#/components/schemas/dial"
          },
          {
            "$ref": "#/components/schemas/messages"
          },
          {
            "$ref": "#/components/schemas/stopMessages"
          },
          {
            "$ref": "#/components/schemas/webhook"
          },
          {
            "$ref": "#/components/schemas/hangup"
          },
          {
            "$ref": "#/components/schemas/answer"
          },
          {
            "$ref": "#/components/schemas/pause"
          },
          {
            "$ref": "#/components/schemas/startRecording"
          },
          {
            "$ref": "#/components/schemas/stopRecording"
          },
          {
            "$ref": "#/components/schemas/bridgeCall"
          },
          {
            "$ref": "#/components/schemas/menu"
          },
          {
            "$ref": "#/components/schemas/gotoMenu"
          }
        ],
        "discriminator": {
          "propertyName": "command",
          "mapping": {
            "amd": "#/components/schemas/amd",
            "dial": "#/components/schemas/dial",
            "messages": "#/components/schemas/messages",
            "stopMessages": "#/components/schemas/stopMessages",
            "webhook": "#/components/schemas/webhook",
            "hangup": "#/components/schemas/hangup",
            "answer": "#/components/schemas/answer",
            "pause": "#/components/schemas/pause",
            "startRecording": "#/components/schemas/startRecording",
            "stopRecording": "#/components/schemas/stopRecording",
            "bridgeCall": "#/components/schemas/bridgeCall",
            "menu": "#/components/schemas/menu",
            "gotoMenu": "#/components/schemas/gotoMenu"
          }
        }
      },
      "messageEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Message Events",
        "description": "SVAML commands to execute based on message playback outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when all messages in the sequence have finished playing.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      }
    }
  }
}
```

### `stopMessages`

Stop any ongoing message playback.

```json
{
  "command": "stopMessages",
  "messagesName": "my-messages",
  "flags": "ONLY_PLAYING"
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/stopMessages",
  "components": {
    "schemas": {
      "stopMessages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Messages",
        "description": "Stops a message sequence previously started by a `messages` command. Use `messagesName` to target a specific sequence and `flags` to control whether only the current message or all queued messages are cancelled. \n\nThis is a non-blocking command.",
        "required": [
          "command",
          "messagesName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopMessages",
            "description": "Command to stop playing messages"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message sequence to stop, as set by `messagesName` in the `messages` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$"
          },
          "flags": {
            "type": "string",
            "description": "Controls how much of the sequence is stopped — only the currently playing message or all remaining queued messages.",
            "default": "ALL_FROM_NOW_ON",
            "enum": [
              "ONLY_PLAYING",
              "ALL_FROM_NOW_ON"
            ],
            "x-enumDescriptions": {
              "ONLY_PLAYING": "Stops only the currently playing message. Queued messages will continue to play.",
              "ALL_FROM_NOW_ON": "Stops the currently playing message and cancels all queued messages."
            }
          }
        },
        "examples": [
          {
            "command": "stopMessages",
            "messagesName": "my-messages",
            "flags": "ONLY_PLAYING"
          }
        ]
      }
    }
  }
}
```

### `pause`

Temporarily halt call commands or media playback.

```json
{
  "command": "pause",
  "durationMilliseconds": 1500
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/pause",
  "components": {
    "schemas": {
      "pause": {
        "type": "object",
        "additionalProperties": false,
        "title": "Pause",
        "description": "Delays execution of the next command in the sequence for a specified duration. This is a blocking command — no further commands execute until the pause completes.\n\nThe pause does not affect call audio; the call remains connected and audio continues uninterrupted.",
        "required": [
          "command",
          "durationMilliseconds"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "pause",
            "description": "Pause execution."
          },
          "durationMilliseconds": {
            "type": "integer",
            "minimum": 1,
            "description": "Duration of the pause in milliseconds.",
            "example": 1000
          }
        },
        "examples": [
          {
            "command": "pause",
            "durationMilliseconds": 1500
          }
        ]
      }
    }
  }
}
```

### `hangup`

End a call or disconnect a participant.

```json
{
  "command": "hangup",
  "callName": "origin"
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/hangup",
  "components": {
    "schemas": {
      "hangup": {
        "type": "object",
        "additionalProperties": false,
        "description": "Ends a call leg. This is a non-blocking command — execution continues to the next command in the sequence even though the call has been ended. The `onHangup` event is triggered for the call leg that was ended.\n\nAny subsequent commands that target the ended call leg (such as `messages` or other media commands) are valid but will not be executed. Commands that operate independently — such as initiating a new call with `dial` — will execute normally. This makes it possible, for example, to end one call and immediately start another within the same sequence.",
        "title": "Hangup",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "hangup",
            "description": "Hangup call"
          },
          "callName": {
            "type": "string",
            "description": "Name of the call leg to end, as set by `callName` in the `dial` command.\n\nIf omitted, the current call leg is ended.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "origin"
          }
        },
        "examples": [
          {
            "command": "hangup",
            "callName": "origin"
          }
        ]
      }
    }
  }
}
```

### `webhook`

Execute a webhook to your backend for dynamic call control, expecting SVAML commands in response.

```json
{
  "command": "webhook",
  "webhookName": "my.custom.event",
  "url": "https://example.com/webhook",
  "fallbackUrl": "https://example.com/fallback"
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/webhook",
  "components": {
    "schemas": {
      "webhookFallbackUrl": {
        "title": "Webhook Fallback URL",
        "type": "string",
        "format": "uri",
        "description": "Fallback webhook URL used when the primary webhook URL fails.\n\nA failed request is re-sent to this URL immediately. After repeated consecutive failures of the primary URL, requests are sent only here until the primary URL recovers.\n\nSee *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "examples": [
          "https://example.com/fallback"
        ]
      },
      "webhook": {
        "type": "object",
        "additionalProperties": false,
        "title": "Webhook",
        "description": "Triggers a mid-call webhook to the application backend, allowing it to return a new set of SVAML commands that control the remainder of the call flow.\n\nThis is a blocking command — execution pauses until a response is received from the webhook endpoint. The next command in the sequence runs only after the backend responds. Webhook requests use a 5-second timeout. If a `fallbackUrl` is provided, a failed request is re-sent to it — see *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "required": [
          "command",
          "webhookName",
          "url"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "webhook",
            "description": "Command to trigger a mid-call webhook"
          },
          "webhookName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^\\S+$",
            "description": "Name for this webhook event. When triggered, the webhook request's `event` property will contain this name prepended with `call.webhook.`.\n\nFor example, if `webhookName` is set to `\"my.custom.event\"`, the event will be delivered as `\"call.webhook.my.custom.event\"`."
          },
          "url": {
            "type": "string",
            "description": "URL of the webhook endpoint to send the mid-call event to.",
            "format": "uri"
          },
          "fallbackUrl": {
            "$ref": "#/components/schemas/webhookFallbackUrl"
          }
        },
        "examples": [
          {
            "command": "webhook",
            "webhookName": "my.custom.event",
            "url": "https://example.com/webhook",
            "fallbackUrl": "https://example.com/fallback"
          }
        ]
      }
    }
  }
}
```

### `startRecording`

Starts a recording of the call channel.

```json
{
  "command": "startRecording",
  "recordingName": "customer-support-recording",
  "recordingOptions": {
    "format": "MP3",
    "recordingType": "COMBINED",
    "destination": "AWS",
    "destinationUrl": "s3://voice-recordings-prod/calls",
    "credentials": "accessKeyId:secretAccessKey:eu-central-1",
    "transcriptionOptions": {
      "isEnabled": true,
      "locale": "en-US"
    }
  },
  "events": {
    "onFinish": [
      {
        "command": "hangup"
      }
    ],
    "onFailure": [
      {
        "command": "messages",
        "messages": [
          {
            "type": "SAY",
            "say": {
              "text": "Recording could not be started for this call.",
              "voiceName": "Emma"
            }
          }
        ]
      }
    ]
  }
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/startRecording",
  "components": {
    "schemas": {
      "recordingFormat": {
        "title": "Recording Format",
        "description": "Audio format for this recording.",
        "type": "string",
        "enum": [
          "MP3",
          "WAV"
        ],
        "x-enumDescriptions": {
          "MP3": "MPEG Audio Layer III compressed audio format.",
          "WAV": "Waveform Audio File Format, uncompressed audio."
        },
        "default": "MP3",
        "examples": [
          "MP3"
        ]
      },
      "recordingType": {
        "title": "Recording Type",
        "description": "The type of recording to perform.",
        "type": "string",
        "enum": [
          "COMBINED",
          "INBOUND",
          "OUTBOUND"
        ],
        "x-enumDescriptions": {
          "COMBINED": "Record inbound and outbound voice streams.",
          "INBOUND": "Record inbound voice stream only.",
          "OUTBOUND": "Record outbound voice stream only."
        },
        "default": "COMBINED"
      },
      "recordingDestination": {
        "title": "Recording Destination",
        "type": "string",
        "description": "Select target service to receive recorded and transcribed files",
        "enum": [
          "AWS",
          "GCP",
          "AZURE"
        ],
        "x-enumDescriptions": {
          "AWS": "Store recordings in Amazon Web Services S3 bucket. Use `s3` as schema for the URL.",
          "GCP": "Store recordings in Google Cloud Platform Storage. Use `gs` as schema for the URL.",
          "AZURE": "Store recordings in Microsoft Azure Blob Storage.  Use `azure` as schema for the URL."
        },
        "default": "AWS",
        "examples": [
          "AWS"
        ]
      },
      "transcriptionOptions": {
        "title": "Transcription Options",
        "description": "Configuration for automatic speech-to-text transcription of the recording.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "isEnabled"
        ],
        "properties": {
          "isEnabled": {
            "type": "boolean",
            "description": "If true, the recording will be transcribed to text.",
            "example": true
          },
          "locale": {
            "type": "string",
            "description": "Language code in BCP-47 format.",
            "default": "en-US",
            "example": "en-US"
          }
        }
      },
      "recordingOptions": {
        "title": "Recording Options",
        "type": "object",
        "additionalProperties": false,
        "description": "Recording options for this recording.",
        "required": [
          "destination",
          "destinationUrl",
          "credentials"
        ],
        "properties": {
          "format": {
            "$ref": "#/components/schemas/recordingFormat"
          },
          "recordingType": {
            "$ref": "#/components/schemas/recordingType"
          },
          "destination": {
            "$ref": "#/components/schemas/recordingDestination"
          },
          "destinationUrl": {
            "type": "string",
            "description": "Destination URL for the recording.",
            "example": "s3://voice-recordings-prod/calls"
          },
          "credentials": {
            "type": "string",
            "description": "Credentials to third party storage.",
            "example": "accessKeyId:secretAccessKey:eu-central-1"
          },
          "transcriptionOptions": {
            "$ref": "#/components/schemas/transcriptionOptions"
          }
        }
      },
      "svamlCommands": {
        "type": "array",
        "title": "SVAML Commands",
        "description": "An ordered list of SVAML v2 (Sinch Voice Application Markup Language) commands that describe a call flow. Commands are executed sequentially in the order they are defined.\n\n**Blocking vs. non-blocking:** Some commands block execution until they complete (`pause`, `webhook`, `menu`, `gotoMenu`), while others return immediately and run in parallel (`dial`, `messages`, `amd`, `answer`, `hangup`, `startRecording`, `stopRecording`, `bridgeCall`, `stopMessages`). Each command's description specifies its behavior.\n\n**Nesting scope:** Commands that appear inside event handlers (e.g., `dial.events.onAnswer`, `messages.events.onFinish`) form independent sequences and execute in their own context — they are not continuations of the parent sequence.",
        "items": {
          "$ref": "#/components/schemas/svamlCommand"
        }
      },
      "amdEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "AMD Events",
        "description": "SVAML commands to execute based on the answering machine detection result. These events define different call flows depending on whether a human, machine, beep, or unknown entity answers the call.",
        "properties": {
          "onHuman": {
            "description": "SVAML commands to be executed when a human is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onMachine": {
            "description": "SVAML commands to be executed when a machine is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBeep": {
            "description": "SVAML commands to be executed when a beep is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onUnknown": {
            "description": "SVAML commands to be executed when an unknown event is detected",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "amd": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answering Machine Detection",
        "description": "AMD (Answering Machine Detection) command to detect what answered the call. Possible outcomes are: human, machine, beep, or unknown.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while detection runs in parallel. Results are delivered via the `events` property.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "amd",
            "description": "Command to run Answering Machine Detection on the call"
          },
          "events": {
            "$ref": "#/components/schemas/amdEvents"
          }
        },
        "examples": [
          {
            "command": "amd",
            "events": {
              "onHuman": [
                {
                  "command": "pause",
                  "durationMilliseconds": 1000
                },
                {
                  "command": "bridgeCall",
                  "bridgeName": "my-bridge"
                }
              ],
              "onBeep": [
                {
                  "command": "messages",
                  "messagesName": "my-amd-messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Hello, this is a test message",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "phoneNumber": {
        "title": "Phone Number",
        "type": "string",
        "pattern": "^\\+[1-9]\\d{1,14}$",
        "minLength": 3,
        "maxLength": 16,
        "description": "E.164 Phone number",
        "examples": [
          "+4673522488"
        ]
      },
      "phone": {
        "type": "object",
        "additionalProperties": false,
        "title": "Phone",
        "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN).",
        "required": [
          "type",
          "phone"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PHONE",
            "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN). The number must be in E.164 format."
          },
          "phone": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "number"
            ],
            "properties": {
              "number": {
                "$ref": "#/components/schemas/phoneNumber"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PHONE",
            "phone": {
              "number": "+4673522488"
            }
          }
        ]
      },
      "sipFrom": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Origin",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Indicates the call originated from a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the originating endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "pattern": "^sips?:",
                "maxLength": 192
              },
              "displayName": {
                "type": "string",
                "description": "Display name presented to the called party as the caller identity. Transmitted as the display name part of the SIP `From` header (for example, `Alice <sip:alice@example.com>`).",
                "maxLength": 64,
                "example": "Alice"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "displayName": "Alice"
            }
          }
        ]
      },
      "from": {
        "description": "Call origin - Phone Number or SIP endpoint",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sipFrom"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sipFrom"
          }
        }
      },
      "sipCallHeaders": {
        "type": "array",
        "description": "Custom SIP headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[-A-Za-z0-9.!%*_+`'~]+$",
              "description": "Name of the SIP header.",
              "example": "X-Correlation-Id"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "description": "Value of the SIP header.",
              "example": "12345"
            }
          }
        },
        "examples": [
          [
            {
              "key": "X-Correlation-Id",
              "value": "12345"
            },
            {
              "key": "X-Call-Routing",
              "value": "forwarded"
            }
          ]
        ]
      },
      "sip": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Endpoint",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Routes the call to a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the destination endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "maxLength": 256,
                "pattern": "^sips?:"
              },
              "transport": {
                "type": "string",
                "description": "Transport protocol to use for the SIP signalling channel.\n\nIf omitted, the platform selects a default based on the URI scheme: `UDP` for `sip:` and `TLS` for `sips:`. Setting this explicitly overrides that default — for example, to force `TCP` for a `sip:` URI or to use `TLS` without switching to the `sips:` scheme.",
                "enum": [
                  "UDP",
                  "TCP",
                  "TLS"
                ],
                "x-enumDescriptions": {
                  "UDP": "Connectionless transport. Lowest overhead; suitable for most standard SIP deployments.",
                  "TCP": "Connection-oriented transport. More reliable for large SIP messages or NAT traversal scenarios.",
                  "TLS": "Encrypted transport. Provides confidentiality and integrity for SIP signalling."
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/sipCallHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "transport": "TCP",
              "callHeaders": [
                {
                  "key": "X-Correlation-Id",
                  "value": "12345"
                },
                {
                  "key": "X-Call-Routing",
                  "value": "forwarded"
                }
              ]
            }
          }
        ]
      },
      "callHeaders": {
        "type": "array",
        "description": "Custom headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]+$",
              "description": "Name of the header.",
              "example": "headerKey"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]*$",
              "description": "Value of the header.",
              "example": "headerValue"
            }
          }
        },
        "examples": [
          [
            {
              "key": "headerKey",
              "value": "headerValue"
            },
            {
              "key": "anotherKey",
              "value": "anotherValue"
            }
          ]
        ]
      },
      "stream": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stream",
        "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing.",
        "required": [
          "type",
          "stream"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "STREAM",
            "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing."
          },
          "stream": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "WebSocket endpoint that will accept the incoming connection for real-time audio streaming. Must be a valid WebSocket URL using either `ws://` or `wss://` (recommended). The URL must be reachable from the public internet and capable of handling the negotiated stream protocol.",
                "example": "wss://example.com"
              },
              "streamOptions": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "description": "Defines the version of the stream protocol.",
                    "default": 1,
                    "example": 1
                  },
                  "codec": {
                    "type": "string",
                    "const": "PCM",
                    "description": "Defines the audio codec/format used for the stream audio payload.\n\nCurrently, only `PCM` is supported (uncompressed raw audio). Use `sampleRate` to configure the sampling rate for the stream."
                  },
                  "sampleRate": {
                    "type": "integer",
                    "description": "Defines the audio sampling rate (Hz) used for the stream.\n\nFor calls that traverse the PSTN, audio is typically sampled at 8 kHz, so using a higher value will not improve perceived quality. \nHigher sample rates can be useful for non-PSTN scenarios (for example, SIP/streaming paths), but will increase bandwidth usage and processing load.",
                    "enum": [
                      8000,
                      16000,
                      24000,
                      44100,
                      48000,
                      96000
                    ],
                    "x-enumDescriptions": {
                      "8000": "8 kHz (standard for PSTN calls)",
                      "16000": "16 kHz (wideband audio)",
                      "24000": "24 kHz (super-wideband audio)",
                      "44100": "44.1 kHz (CD quality audio)",
                      "48000": "48 kHz (professional audio quality)",
                      "96000": "96 kHz (high-resolution audio)"
                    },
                    "default": 8000,
                    "example": 16000
                  }
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            },
            "examples": [
              {
                "endpoint": "wss://example.com",
                "streamOptions": {
                  "version": 1,
                  "codec": "PCM",
                  "sampleRate": 8000
                },
                "callHeaders": [
                  {
                    "key": "my-key",
                    "value": "my-key-value"
                  }
                ]
              }
            ]
          }
        },
        "examples": [
          {
            "type": "STREAM",
            "stream": {
              "endpoint": "wss://example.com",
              "streamOptions": {
                "version": 1,
                "codec": "PCM",
                "sampleRate": 16000
              },
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "voiceRelay": {
        "type": "object",
        "additionalProperties": false,
        "title": "Voice Relay",
        "description": "Routes the call through the Voice Relay service, enabling real-time speech-to-text (STT) and text-to-speech (TTS) via a WebSocket connection to the application backend.",
        "required": [
          "type",
          "voiceRelay"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "VOICE_RELAY",
            "description": "Connects to the Voice Relay service to enable STT and TTS services..."
          },
          "voiceRelay": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint",
              "ttsVoice",
              "sttLanguage"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "format": "uri",
                "description": "URL to the server that will accept the web-socket request",
                "example": "wss://acme.com/agent"
              },
              "enableInterruptions": {
                "type": "boolean",
                "description": "Allow \"barge-in\" during text-to-speech (TTS) playback.\n\nWhen `true`, TTS playback is interrupted as soon as inbound speech is detected, unless the currently playing content is marked as uninterruptible.\n\nWhen `false`, TTS playback continues uninterrupted, but an interruption signal is still sent over the WebSocket so the client application can choose to stop playback manually if needed.",
                "default": true,
                "example": true
              },
              "ttsVoice": {
                "type": "string",
                "description": "Name of the voice to be used when synthesizing speech. \n\nThis is the default voice used, if no override voice is provided in the web-socket TTS message.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              },
              "sttLanguage": {
                "type": "string",
                "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$",
                "description": "BCP-47 language tag used for speech-to-text transcription of the inbound audio.\n\nThis value determines which language model is used for transcription.",
                "example": "en-US"
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "VOICE_RELAY",
            "voiceRelay": {
              "endpoint": "wss://acme.com/agent",
              "enableInterruptions": true,
              "ttsVoice": "Emma",
              "sttLanguage": "en-US",
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "to": {
        "title": "To",
        "description": "Call destination - Phone Number or Stream URI",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sip"
          },
          {
            "$ref": "#/components/schemas/stream"
          },
          {
            "$ref": "#/components/schemas/voiceRelay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sip",
            "STREAM": "#/components/schemas/stream",
            "VOICE_RELAY": "#/components/schemas/voiceRelay"
          }
        }
      },
      "callEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Call Events Webhook",
        "description": "Webhook to handle call events, used when callBehaviors are set to WEBHOOK",
        "properties": {
          "onAnswer": {
            "description": "SVAML commands to be executed when the call is answered",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBusy": {
            "description": "SVAML commands to be executed when the call is busy",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onReject": {
            "description": "SVAML commands to be executed when the call is rejected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onTimeout": {
            "description": "SVAML commands to be executed when the call is timed out",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onHangup": {
            "description": "SVAML commands to be executed when the call is hung up",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "SVAML commands to be executed when the call fails",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "dial": {
        "type": "object",
        "additionalProperties": false,
        "title": "Dial",
        "description": "Initiates a new outbound call leg within the current session.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while the call is being established in parallel. Call lifecycle events (answer, busy, reject, timeout, hangup, failure) are handled via the `events` property.\n\nThe `from` and `to` endpoint types should ideally match. If they differ, the platform attempts to convert the `from` value to be compatible with the `to` type. For example, PSTN supports only E.164 phone numbers, so a SIP address such as `sip:46701234567@acme.se` can be converted to an E.164 number. If the `from` value cannot be converted, it defaults to null (anonymous).",
        "required": [
          "command",
          "to"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "dial",
            "description": "Command to initiate a new call"
          },
          "callName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "outgoing",
            "description": "Identifier for this call leg within the session. Must be unique across all active call legs in the session.\n\nOther commands (e.g., `hangup`) can reference this name to target this specific leg."
          },
          "from": {
            "$ref": "#/components/schemas/from"
          },
          "to": {
            "$ref": "#/components/schemas/to"
          },
          "dialTimeoutDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "description": "Maximum time in seconds to wait for the call to be answered. If the timeout expires without an answer, the `onTimeout` event is triggered.",
            "example": 15
          },
          "maxCallDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 14400,
            "description": "Maximum duration of the call in seconds. The call is terminated automatically when this limit is reached.",
            "example": 3600
          },
          "events": {
            "$ref": "#/components/schemas/callEvents"
          }
        },
        "examples": [
          {
            "command": "dial",
            "callName": "destination",
            "from": {
              "type": "PHONE",
              "phone": {
                "number": "+15551234567"
              }
            },
            "to": {
              "type": "PHONE",
              "phone": {
                "number": "+15559876543"
              }
            },
            "dialTimeoutDurationSeconds": 30,
            "maxCallDurationSeconds": 3600,
            "events": {
              "onAnswer": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Your call has connected.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "messageSay": {
        "type": "object",
        "title": "Say Message",
        "description": "A text-to-speech (TTS) message item. The platform synthesizes the provided text into speech and plays it on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "say"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SAY",
            "description": "Text-to-speech message to be played during the call."
          },
          "say": {
            "type": "object",
            "additionalProperties": false,
            "title": "Say",
            "required": [
              "text",
              "voiceName"
            ],
            "properties": {
              "text": {
                "type": "string",
                "description": "The text to be synthesized into speech.\n\nIf `format` is `TEXT` (default), provide plain text.\nIf `format` is `SSML`, provide a valid SSML document (for example, `<speak>...</speak>`).",
                "maxLength": 600,
                "example": "Hello world"
              },
              "format": {
                "type": "string",
                "description": "Format of the message",
                "enum": [
                  "TEXT",
                  "SSML"
                ],
                "x-enumDescriptions": {
                  "TEXT": "Plain text format for the message.",
                  "SSML": "Speech Synthesis Markup Language format for advanced text-to-speech control."
                },
                "default": "TEXT"
              },
              "voiceName": {
                "type": "string",
                "description": "The name of the voice to use for text-to-speech synthesis.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SAY",
            "say": {
              "text": "Hello, this is a test message",
              "voiceName": "Emma"
            }
          },
          {
            "type": "SAY",
            "say": {
              "text": "<speak><prosody volume=\"-6dB\">Hello, this is a test message</prosody></speak>",
              "format": "SSML",
              "voiceName": "Brian"
            }
          }
        ]
      },
      "messagePlay": {
        "type": "object",
        "title": "Play Message",
        "description": "An audio file playback message item. The platform fetches and plays the audio file at the provided URL on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "play"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PLAY",
            "description": "Audio file playback during the call."
          },
          "play": {
            "type": "object",
            "additionalProperties": false,
            "title": "Play",
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "description": "URL of the media to send"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PLAY",
            "play": {
              "url": "https://example.com/media.mp3"
            }
          }
        ]
      },
      "message": {
        "type": "object",
        "title": "Message",
        "description": "A single message item. The required payload depends on `type`.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/messageSay"
          },
          {
            "$ref": "#/components/schemas/messagePlay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "SAY": "#/components/schemas/messageSay",
            "PLAY": "#/components/schemas/messagePlay"
          }
        }
      },
      "typesOfMessages": {
        "type": "array",
        "title": "Message List",
        "description": "Ordered list of messages to play.",
        "minItems": 1,
        "maxItems": 10,
        "items": {
          "$ref": "#/components/schemas/message"
        }
      },
      "messageEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Message Events",
        "description": "SVAML commands to execute based on message playback outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when all messages in the sequence have finished playing.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "messages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Messages",
        "description": "Plays one or more messages on the call. Multiple messages in the array are played sequentially in order.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while messages play in parallel. \nPlayback outcomes are handled via the `events` property. The `onFinish` event can be used to run a command after all messages complete.",
        "required": [
          "command",
          "messages"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "messages",
            "description": "Command to play a message on the channel"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message for identification and reference within the call session.\n\nThis name is used to uniquely identify the message and must be unique within the current call session.\nThis name can be referenced in other commands (e.g., `stopMessages`) to control this specific message.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-messages"
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          },
          "events": {
            "$ref": "#/components/schemas/messageEvents"
          }
        },
        "examples": [
          {
            "command": "messages",
            "messagesName": "greeting-sequence",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Hello! Your call is being connected.",
                  "voiceName": "Emma"
                }
              },
              {
                "type": "PLAY",
                "play": {
                  "url": "https://example.com/audio/hold-music.mp3"
                }
              },
              {
                "type": "SAY",
                "say": {
                  "text": "<speak><prosody volume=\"-6dB\">Thank you for waiting.</prosody></speak>",
                  "format": "SSML",
                  "voiceName": "Emma"
                }
              }
            ]
          }
        ]
      },
      "stopMessages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Messages",
        "description": "Stops a message sequence previously started by a `messages` command. Use `messagesName` to target a specific sequence and `flags` to control whether only the current message or all queued messages are cancelled. \n\nThis is a non-blocking command.",
        "required": [
          "command",
          "messagesName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopMessages",
            "description": "Command to stop playing messages"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message sequence to stop, as set by `messagesName` in the `messages` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$"
          },
          "flags": {
            "type": "string",
            "description": "Controls how much of the sequence is stopped — only the currently playing message or all remaining queued messages.",
            "default": "ALL_FROM_NOW_ON",
            "enum": [
              "ONLY_PLAYING",
              "ALL_FROM_NOW_ON"
            ],
            "x-enumDescriptions": {
              "ONLY_PLAYING": "Stops only the currently playing message. Queued messages will continue to play.",
              "ALL_FROM_NOW_ON": "Stops the currently playing message and cancels all queued messages."
            }
          }
        },
        "examples": [
          {
            "command": "stopMessages",
            "messagesName": "my-messages",
            "flags": "ONLY_PLAYING"
          }
        ]
      },
      "webhookFallbackUrl": {
        "title": "Webhook Fallback URL",
        "type": "string",
        "format": "uri",
        "description": "Fallback webhook URL used when the primary webhook URL fails.\n\nA failed request is re-sent to this URL immediately. After repeated consecutive failures of the primary URL, requests are sent only here until the primary URL recovers.\n\nSee *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "examples": [
          "https://example.com/fallback"
        ]
      },
      "webhook": {
        "type": "object",
        "additionalProperties": false,
        "title": "Webhook",
        "description": "Triggers a mid-call webhook to the application backend, allowing it to return a new set of SVAML commands that control the remainder of the call flow.\n\nThis is a blocking command — execution pauses until a response is received from the webhook endpoint. The next command in the sequence runs only after the backend responds. Webhook requests use a 5-second timeout. If a `fallbackUrl` is provided, a failed request is re-sent to it — see *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "required": [
          "command",
          "webhookName",
          "url"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "webhook",
            "description": "Command to trigger a mid-call webhook"
          },
          "webhookName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^\\S+$",
            "description": "Name for this webhook event. When triggered, the webhook request's `event` property will contain this name prepended with `call.webhook.`.\n\nFor example, if `webhookName` is set to `\"my.custom.event\"`, the event will be delivered as `\"call.webhook.my.custom.event\"`."
          },
          "url": {
            "type": "string",
            "description": "URL of the webhook endpoint to send the mid-call event to.",
            "format": "uri"
          },
          "fallbackUrl": {
            "$ref": "#/components/schemas/webhookFallbackUrl"
          }
        },
        "examples": [
          {
            "command": "webhook",
            "webhookName": "my.custom.event",
            "url": "https://example.com/webhook",
            "fallbackUrl": "https://example.com/fallback"
          }
        ]
      },
      "hangup": {
        "type": "object",
        "additionalProperties": false,
        "description": "Ends a call leg. This is a non-blocking command — execution continues to the next command in the sequence even though the call has been ended. The `onHangup` event is triggered for the call leg that was ended.\n\nAny subsequent commands that target the ended call leg (such as `messages` or other media commands) are valid but will not be executed. Commands that operate independently — such as initiating a new call with `dial` — will execute normally. This makes it possible, for example, to end one call and immediately start another within the same sequence.",
        "title": "Hangup",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "hangup",
            "description": "Hangup call"
          },
          "callName": {
            "type": "string",
            "description": "Name of the call leg to end, as set by `callName` in the `dial` command.\n\nIf omitted, the current call leg is ended.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "origin"
          }
        },
        "examples": [
          {
            "command": "hangup",
            "callName": "origin"
          }
        ]
      },
      "answer": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answer",
        "description": "Answers an inbound call leg. This is a non-blocking command — execution continues to the next command in the sequence immediately after the answer is initiated.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "answer",
            "description": "Answer call"
          }
        },
        "examples": [
          {
            "command": "answer"
          }
        ]
      },
      "pause": {
        "type": "object",
        "additionalProperties": false,
        "title": "Pause",
        "description": "Delays execution of the next command in the sequence for a specified duration. This is a blocking command — no further commands execute until the pause completes.\n\nThe pause does not affect call audio; the call remains connected and audio continues uninterrupted.",
        "required": [
          "command",
          "durationMilliseconds"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "pause",
            "description": "Pause execution."
          },
          "durationMilliseconds": {
            "type": "integer",
            "minimum": 1,
            "description": "Duration of the pause in milliseconds.",
            "example": 1000
          }
        },
        "examples": [
          {
            "command": "pause",
            "durationMilliseconds": 1500
          }
        ]
      },
      "startRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Start Recording",
        "required": [
          "command",
          "recordingOptions"
        ],
        "description": "Starts recording the call. This is a non-blocking command — execution continues to the next command in the sequence immediately after recording begins.",
        "properties": {
          "command": {
            "type": "string",
            "const": "startRecording",
            "description": "Command to start recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Identifier for this recording within the session. Must be unique across active recordings in the session.\n\nOther commands (e.g., `stopRecording`) reference this name to target a specific recording.\n\nSetting the recording name is useful for stopping the recording using the `stopRecording` command. If name is not set, recording can only be stopped when the call is disconnected.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          },
          "recordingOptions": {
            "$ref": "#/components/schemas/recordingOptions"
          },
          "events": {
            "$ref": "#/components/schemas/recordingEvents"
          }
        },
        "examples": [
          {
            "command": "startRecording",
            "recordingName": "customer-support-recording",
            "recordingOptions": {
              "format": "MP3",
              "recordingType": "COMBINED",
              "destination": "AWS",
              "destinationUrl": "s3://voice-recordings-prod/calls",
              "credentials": "accessKeyId:secretAccessKey:eu-central-1",
              "transcriptionOptions": {
                "isEnabled": true,
                "locale": "en-US"
              }
            },
            "events": {
              "onFinish": [
                {
                  "command": "hangup"
                }
              ],
              "onFailure": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Recording could not be started for this call.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "stopRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Recording",
        "description": "Stops a recording previously started by a `startRecording` command. This is a non-blocking command — execution continues to the next command in the sequence immediately after the stop is initiated.",
        "required": [
          "command",
          "recordingName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopRecording",
            "description": "Command to stop recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Name of the recording to stop, as set by `recordingName` in the `startRecording` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          }
        }
      },
      "bridgeCall": {
        "type": "object",
        "additionalProperties": false,
        "title": "Add call to bridge",
        "description": "Adds the current call to a bridge, enabling bidirectional audio communication with other calls in the same session. This is a non-blocking command — execution continues to the next command in the sequence immediately after the call joins the bridge.\n\nBridges are created automatically when referenced by name. If a bridge with the specified name already exists, the call joins that bridge; otherwise, a new bridge is created.",
        "required": [
          "command",
          "bridgeName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "bridgeCall",
            "description": "Command to add the call to a bridge"
          },
          "bridgeName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "description": "Name of the bridge to join. If no bridge with this name exists in the session, a new one is created automatically."
          }
        },
        "examples": [
          {
            "command": "bridgeCall",
            "bridgeName": "my_bridge"
          }
        ]
      },
      "menuPrompt": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Prompt",
        "description": "Prompt configuration for menu playback, including prompt messages and barge-in behavior.",
        "required": [
          "messages"
        ],
        "properties": {
          "allowBargeIn": {
            "type": "boolean",
            "description": "Controls whether input can interrupt prompt playback.\n\nWhen enabled, playback stops as soon as input is detected and the input is evaluated immediately if matching conditions are met.\n\nWhen disabled, input is still collected during playback and evaluated after playback finishes.",
            "default": true
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          }
        }
      },
      "menuItem": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Item",
        "description": "Defines a single menu step, including prompts, input handling rules, input-to-command matches, and failure handling.\n\nEach collected input is matched against the values in the `matches` property.\nIf no match succeeds, the `onFail` commands are executed.\n\nIf neither `matches` nor `onFail` is defined and the service call behavior is set to `WEBHOOK`, a webhook request is sent including the collected input.",
        "properties": {
          "prompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when this menu starts.\n\nThis prompt is also used as the repeat prompt when repeatPrompt is not defined for the menu."
          },
          "repeatPrompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when the menu is repeated.\n\nRepeats occur when input times out or when the provided input does not match any menu match item."
          },
          "inputTimeoutDurationSeconds": {
            "type": "integer",
            "description": "Maximum number of seconds to wait for user input before the input attempt times out.",
            "minimum": 1,
            "maximum": 60,
            "default": 5,
            "example": 10
          },
          "repeatCount": {
            "type": "integer",
            "description": "Maximum number of times the menu is repeated.\n\nA repeat occurs when input times out or when the provided input does not match any menu match item.",
            "minimum": 0,
            "maximum": 10,
            "default": 2,
            "example": 3
          },
          "minimumInputLength": {
            "type": "integer",
            "description": "Minimum number of input characters required before the menu evaluates the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 3
          },
          "maximumInputLength": {
            "type": "integer",
            "description": "Maximum number of input characters that triggers the menu to evaluate the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 10
          },
          "terminatingSequence": {
            "type": "string",
            "pattern": "^[0-9*#]+$",
            "description": "Character sequence that signals the end of input and triggers immediate evaluation.\n\nUseful when variable-length input is allowed and shorter valid options should be submitted without waiting for timeout or maximum length.\n\nThe terminating sequence value is included in the evaluated input.",
            "maxLength": 10
          },
          "inputMethods": {
            "type": "array",
            "description": "Input methods accepted for this menu when collecting user input.",
            "default": [
              "DTMF"
            ],
            "items": {
              "type": "string",
              "enum": [
                "DTMF"
              ],
              "x-enumDescriptions": {
                "DTMF": "Collect input from keypad tones (Dual-Tone Multi-Frequency)."
              }
            }
          },
          "matches": {
            "type": "object",
            "description": "Items matched against the collected input. Maximum number of allowed match expressions is 50.\n\nDefined as a dictionary where each property name is a literal or a regular expression string.\n\nValues are evaluated in the order they are defined.",
            "maxProperties": 50,
            "propertyNames": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "description": "A regular expression or literal string to match against the collected user input. Must not be empty.\n\nProperty keys are evaluated sequentially in the order defined. The first key that matches the input will trigger its associated SVAML commands.\n\n**Note**: Use `\\\\*` to match the DTMF star tone (*)."
            },
            "additionalProperties": {
              "$ref": "#/components/schemas/svamlCommands"
            }
          },
          "onFail": {
            "$ref": "#/components/schemas/svamlCommands",
            "description": "SVAML commands executed when the menu fails to collect a matching input.\n\nThis handler runs after the repeat limit is reached without any input matching a menu match item."
          }
        }
      },
      "menu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Run menus",
        "description": "Defines a set of named menus and executes them starting from startMenu. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\nEach menu item configures prompts, input collection, timeout handling, and repeat behavior.",
        "required": [
          "command",
          "startMenu",
          "menus"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "menu",
            "description": "Executes menu-based input collection using the configured menu definitions."
          },
          "startMenu": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "description": "Name of the menu to execute first. Must match a key in menus."
          },
          "menus": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "maxLength": 16
            },
            "description": "Map of menu definitions keyed by menu name.",
            "additionalProperties": {
              "$ref": "#/components/schemas/menuItem"
            }
          }
        },
        "examples": [
          {
            "command": "menu",
            "startMenu": "main",
            "menus": {
              "main": {
                "prompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "repeatPrompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Invalid option. Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "inputTimeoutDurationSeconds": 5,
                "repeatCount": 2,
                "minimumInputLength": 1,
                "maximumInputLength": 1,
                "inputMethods": [
                  "DTMF"
                ],
                "matches": {
                  "1": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to sales.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "sales",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15551234567"
                        }
                      }
                    }
                  ],
                  "2": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to support.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "support",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15557654321"
                        }
                      }
                    }
                  ]
                },
                "onFail": [
                  {
                    "command": "messages",
                    "messages": [
                      {
                        "type": "SAY",
                        "say": {
                          "text": "Sorry, no valid selection was received.",
                          "voiceName": "Emma"
                        }
                      }
                    ]
                  },
                  {
                    "command": "hangup"
                  }
                ]
              }
            }
          }
        ]
      },
      "gotoMenu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Goto Menu",
        "description": "Switches execution to another menu within the current menu context. The menu name must be a menu defined in the `menu` command. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\n**Important**: this command can only be called within a menu execution context.",
        "required": [
          "command",
          "menuName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "gotoMenu",
            "description": "Switch execution to another menu within the current menu context."
          },
          "menuName": {
            "type": "string",
            "description": "Name of the target menu to execute next. Must match a key in menus.",
            "minLength": 1,
            "maxLength": 16
          }
        }
      },
      "svamlCommand": {
        "title": "SVAML Command",
        "type": "object",
        "description": "A single SVAML (Sinch Voice Application Markup Language) command that controls call behavior.\n\nThe `command` property acts as a discriminator and determines which command schema applies. When multiple commands appear in a `svamlCommands` array, they execute sequentially in order.\n\n**Available commands:**\n- `dial` — Initiate an outbound call leg within the session.\n- `messages` — Play one or more TTS or audio messages on the call.\n- `stopMessages` — Stop a currently playing message sequence.\n- `webhook` — Trigger a mid-call webhook to the application backend for dynamic call control.\n- `amd` — Detect whether the call was answered by a human or an answering machine.\n- `hangup` — End the call or a specific call leg within the session.\n- `answer` — Explicitly answer an incoming call leg before executing further commands.\n- `pause` — Delay script execution without affecting call audio.\n- `startRecording` — Begin recording the call.\n- `stopRecording` — Stop an active call recording.\n- `bridgeCall` — Add the call to a named bridge for multi-party audio.\n- `menu` — Run menu-based input collection and route the call based on collected input.\n- `gotoMenu` — Switch execution to another named menu within the current menu context.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/amd"
          },
          {
            "$ref": "#/components/schemas/dial"
          },
          {
            "$ref": "#/components/schemas/messages"
          },
          {
            "$ref": "#/components/schemas/stopMessages"
          },
          {
            "$ref": "#/components/schemas/webhook"
          },
          {
            "$ref": "#/components/schemas/hangup"
          },
          {
            "$ref": "#/components/schemas/answer"
          },
          {
            "$ref": "#/components/schemas/pause"
          },
          {
            "$ref": "#/components/schemas/startRecording"
          },
          {
            "$ref": "#/components/schemas/stopRecording"
          },
          {
            "$ref": "#/components/schemas/bridgeCall"
          },
          {
            "$ref": "#/components/schemas/menu"
          },
          {
            "$ref": "#/components/schemas/gotoMenu"
          }
        ],
        "discriminator": {
          "propertyName": "command",
          "mapping": {
            "amd": "#/components/schemas/amd",
            "dial": "#/components/schemas/dial",
            "messages": "#/components/schemas/messages",
            "stopMessages": "#/components/schemas/stopMessages",
            "webhook": "#/components/schemas/webhook",
            "hangup": "#/components/schemas/hangup",
            "answer": "#/components/schemas/answer",
            "pause": "#/components/schemas/pause",
            "startRecording": "#/components/schemas/startRecording",
            "stopRecording": "#/components/schemas/stopRecording",
            "bridgeCall": "#/components/schemas/bridgeCall",
            "menu": "#/components/schemas/menu",
            "gotoMenu": "#/components/schemas/gotoMenu"
          }
        }
      },
      "recordingEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Recording Events",
        "description": "SVAML commands to execute based on recording lifecycle outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when the recording is successfully stopped. Note that this does not mean that the file is delivered to the configured destination yet.\n",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "Commands to execute if the recording fails to start. If omitted, failures are silently ignored and the call flow continues.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      }
    }
  }
}
```

### `stopRecording`

Stops recording.

```json
{
  "command": "stopRecording",
  "recordingName": "my-recording"
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/stopRecording",
  "components": {
    "schemas": {
      "stopRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Recording",
        "description": "Stops a recording previously started by a `startRecording` command. This is a non-blocking command — execution continues to the next command in the sequence immediately after the stop is initiated.",
        "required": [
          "command",
          "recordingName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopRecording",
            "description": "Command to stop recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Name of the recording to stop, as set by `recordingName` in the `startRecording` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          }
        }
      }
    }
  }
}
```

### `bridgeCall`

Bridges two calls.

```json
{
  "command": "bridgeCall",
  "bridgeName": "my_bridge"
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/bridgeCall",
  "components": {
    "schemas": {
      "bridgeCall": {
        "type": "object",
        "additionalProperties": false,
        "title": "Add call to bridge",
        "description": "Adds the current call to a bridge, enabling bidirectional audio communication with other calls in the same session. This is a non-blocking command — execution continues to the next command in the sequence immediately after the call joins the bridge.\n\nBridges are created automatically when referenced by name. If a bridge with the specified name already exists, the call joins that bridge; otherwise, a new bridge is created.",
        "required": [
          "command",
          "bridgeName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "bridgeCall",
            "description": "Command to add the call to a bridge"
          },
          "bridgeName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "description": "Name of the bridge to join. If no bridge with this name exists in the session, a new one is created automatically."
          }
        },
        "examples": [
          {
            "command": "bridgeCall",
            "bridgeName": "my_bridge"
          }
        ]
      }
    }
  }
}
```

### `menu`

Define IVR menus.

```json
{
  "command": "menu",
  "startMenu": "main",
  "menus": {
    "main": {
      "prompt": {
        "allowBargeIn": true,
        "messages": [
          {
            "type": "SAY",
            "say": {
              "text": "Press 1 for sales or 2 for support.",
              "voiceName": "Emma"
            }
          }
        ]
      },
      "repeatPrompt": {
        "allowBargeIn": true,
        "messages": [
          {
            "type": "SAY",
            "say": {
              "text": "Invalid option. Press 1 for sales or 2 for support.",
              "voiceName": "Emma"
            }
          }
        ]
      },
      "inputTimeoutDurationSeconds": 5,
      "repeatCount": 2,
      "minimumInputLength": 1,
      "maximumInputLength": 1,
      "inputMethods": [
        "DTMF"
      ],
      "matches": {
        "1": [
          {
            "command": "messages",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Connecting to sales.",
                  "voiceName": "Emma"
                }
              }
            ]
          },
          {
            "command": "dial",
            "callName": "sales",
            "to": {
              "type": "PHONE",
              "phone": {
                "number": "+15551234567"
              }
            }
          }
        ],
        "2": [
          {
            "command": "messages",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Connecting to support.",
                  "voiceName": "Emma"
                }
              }
            ]
          },
          {
            "command": "dial",
            "callName": "support",
            "to": {
              "type": "PHONE",
              "phone": {
                "number": "+15557654321"
              }
            }
          }
        ]
      },
      "onFail": [
        {
          "command": "messages",
          "messages": [
            {
              "type": "SAY",
              "say": {
                "text": "Sorry, no valid selection was received.",
                "voiceName": "Emma"
              }
            }
          ]
        },
        {
          "command": "hangup"
        }
      ]
    }
  }
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/menu",
  "components": {
    "schemas": {
      "messageSay": {
        "type": "object",
        "title": "Say Message",
        "description": "A text-to-speech (TTS) message item. The platform synthesizes the provided text into speech and plays it on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "say"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SAY",
            "description": "Text-to-speech message to be played during the call."
          },
          "say": {
            "type": "object",
            "additionalProperties": false,
            "title": "Say",
            "required": [
              "text",
              "voiceName"
            ],
            "properties": {
              "text": {
                "type": "string",
                "description": "The text to be synthesized into speech.\n\nIf `format` is `TEXT` (default), provide plain text.\nIf `format` is `SSML`, provide a valid SSML document (for example, `<speak>...</speak>`).",
                "maxLength": 600,
                "example": "Hello world"
              },
              "format": {
                "type": "string",
                "description": "Format of the message",
                "enum": [
                  "TEXT",
                  "SSML"
                ],
                "x-enumDescriptions": {
                  "TEXT": "Plain text format for the message.",
                  "SSML": "Speech Synthesis Markup Language format for advanced text-to-speech control."
                },
                "default": "TEXT"
              },
              "voiceName": {
                "type": "string",
                "description": "The name of the voice to use for text-to-speech synthesis.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SAY",
            "say": {
              "text": "Hello, this is a test message",
              "voiceName": "Emma"
            }
          },
          {
            "type": "SAY",
            "say": {
              "text": "<speak><prosody volume=\"-6dB\">Hello, this is a test message</prosody></speak>",
              "format": "SSML",
              "voiceName": "Brian"
            }
          }
        ]
      },
      "messagePlay": {
        "type": "object",
        "title": "Play Message",
        "description": "An audio file playback message item. The platform fetches and plays the audio file at the provided URL on the call.",
        "additionalProperties": false,
        "required": [
          "type",
          "play"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PLAY",
            "description": "Audio file playback during the call."
          },
          "play": {
            "type": "object",
            "additionalProperties": false,
            "title": "Play",
            "required": [
              "url"
            ],
            "properties": {
              "url": {
                "type": "string",
                "description": "URL of the media to send"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PLAY",
            "play": {
              "url": "https://example.com/media.mp3"
            }
          }
        ]
      },
      "message": {
        "type": "object",
        "title": "Message",
        "description": "A single message item. The required payload depends on `type`.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/messageSay"
          },
          {
            "$ref": "#/components/schemas/messagePlay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "SAY": "#/components/schemas/messageSay",
            "PLAY": "#/components/schemas/messagePlay"
          }
        }
      },
      "typesOfMessages": {
        "type": "array",
        "title": "Message List",
        "description": "Ordered list of messages to play.",
        "minItems": 1,
        "maxItems": 10,
        "items": {
          "$ref": "#/components/schemas/message"
        }
      },
      "menuPrompt": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Prompt",
        "description": "Prompt configuration for menu playback, including prompt messages and barge-in behavior.",
        "required": [
          "messages"
        ],
        "properties": {
          "allowBargeIn": {
            "type": "boolean",
            "description": "Controls whether input can interrupt prompt playback.\n\nWhen enabled, playback stops as soon as input is detected and the input is evaluated immediately if matching conditions are met.\n\nWhen disabled, input is still collected during playback and evaluated after playback finishes.",
            "default": true
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          }
        }
      },
      "svamlCommands": {
        "type": "array",
        "title": "SVAML Commands",
        "description": "An ordered list of SVAML v2 (Sinch Voice Application Markup Language) commands that describe a call flow. Commands are executed sequentially in the order they are defined.\n\n**Blocking vs. non-blocking:** Some commands block execution until they complete (`pause`, `webhook`, `menu`, `gotoMenu`), while others return immediately and run in parallel (`dial`, `messages`, `amd`, `answer`, `hangup`, `startRecording`, `stopRecording`, `bridgeCall`, `stopMessages`). Each command's description specifies its behavior.\n\n**Nesting scope:** Commands that appear inside event handlers (e.g., `dial.events.onAnswer`, `messages.events.onFinish`) form independent sequences and execute in their own context — they are not continuations of the parent sequence.",
        "items": {
          "$ref": "#/components/schemas/svamlCommand"
        }
      },
      "amdEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "AMD Events",
        "description": "SVAML commands to execute based on the answering machine detection result. These events define different call flows depending on whether a human, machine, beep, or unknown entity answers the call.",
        "properties": {
          "onHuman": {
            "description": "SVAML commands to be executed when a human is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onMachine": {
            "description": "SVAML commands to be executed when a machine is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBeep": {
            "description": "SVAML commands to be executed when a beep is detected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onUnknown": {
            "description": "SVAML commands to be executed when an unknown event is detected",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "amd": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answering Machine Detection",
        "description": "AMD (Answering Machine Detection) command to detect what answered the call. Possible outcomes are: human, machine, beep, or unknown.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while detection runs in parallel. Results are delivered via the `events` property.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "amd",
            "description": "Command to run Answering Machine Detection on the call"
          },
          "events": {
            "$ref": "#/components/schemas/amdEvents"
          }
        },
        "examples": [
          {
            "command": "amd",
            "events": {
              "onHuman": [
                {
                  "command": "pause",
                  "durationMilliseconds": 1000
                },
                {
                  "command": "bridgeCall",
                  "bridgeName": "my-bridge"
                }
              ],
              "onBeep": [
                {
                  "command": "messages",
                  "messagesName": "my-amd-messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Hello, this is a test message",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "phoneNumber": {
        "title": "Phone Number",
        "type": "string",
        "pattern": "^\\+[1-9]\\d{1,14}$",
        "minLength": 3,
        "maxLength": 16,
        "description": "E.164 Phone number",
        "examples": [
          "+4673522488"
        ]
      },
      "phone": {
        "type": "object",
        "additionalProperties": false,
        "title": "Phone",
        "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN).",
        "required": [
          "type",
          "phone"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "PHONE",
            "description": "Routes the call to a phone number on the Public Switched Telephone Network (PSTN). The number must be in E.164 format."
          },
          "phone": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "number"
            ],
            "properties": {
              "number": {
                "$ref": "#/components/schemas/phoneNumber"
              }
            }
          }
        },
        "examples": [
          {
            "type": "PHONE",
            "phone": {
              "number": "+4673522488"
            }
          }
        ]
      },
      "sipFrom": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Origin",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Indicates the call originated from a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the originating endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "pattern": "^sips?:",
                "maxLength": 192
              },
              "displayName": {
                "type": "string",
                "description": "Display name presented to the called party as the caller identity. Transmitted as the display name part of the SIP `From` header (for example, `Alice <sip:alice@example.com>`).",
                "maxLength": 64,
                "example": "Alice"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "displayName": "Alice"
            }
          }
        ]
      },
      "from": {
        "description": "Call origin - Phone Number or SIP endpoint",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sipFrom"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sipFrom"
          }
        }
      },
      "sipCallHeaders": {
        "type": "array",
        "description": "Custom SIP headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[-A-Za-z0-9.!%*_+`'~]+$",
              "description": "Name of the SIP header.",
              "example": "X-Correlation-Id"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "description": "Value of the SIP header.",
              "example": "12345"
            }
          }
        },
        "examples": [
          [
            {
              "key": "X-Correlation-Id",
              "value": "12345"
            },
            {
              "key": "X-Call-Routing",
              "value": "forwarded"
            }
          ]
        ]
      },
      "sip": {
        "type": "object",
        "additionalProperties": false,
        "title": "SIP Endpoint",
        "required": [
          "type",
          "sip"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SIP",
            "description": "Routes the call to a SIP (Session Initiation Protocol) endpoint."
          },
          "sip": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "SIP URI of the destination endpoint. Both `sip:` (unencrypted) and `sips:` (TLS-encrypted) schemes are supported.",
                "format": "uri",
                "maxLength": 256,
                "pattern": "^sips?:"
              },
              "transport": {
                "type": "string",
                "description": "Transport protocol to use for the SIP signalling channel.\n\nIf omitted, the platform selects a default based on the URI scheme: `UDP` for `sip:` and `TLS` for `sips:`. Setting this explicitly overrides that default — for example, to force `TCP` for a `sip:` URI or to use `TLS` without switching to the `sips:` scheme.",
                "enum": [
                  "UDP",
                  "TCP",
                  "TLS"
                ],
                "x-enumDescriptions": {
                  "UDP": "Connectionless transport. Lowest overhead; suitable for most standard SIP deployments.",
                  "TCP": "Connection-oriented transport. More reliable for large SIP messages or NAT traversal scenarios.",
                  "TLS": "Encrypted transport. Provides confidentiality and integrity for SIP signalling."
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/sipCallHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "SIP",
            "sip": {
              "endpoint": "sip:user@example.com",
              "transport": "TCP",
              "callHeaders": [
                {
                  "key": "X-Correlation-Id",
                  "value": "12345"
                },
                {
                  "key": "X-Call-Routing",
                  "value": "forwarded"
                }
              ]
            }
          }
        ]
      },
      "callHeaders": {
        "type": "array",
        "description": "Custom headers to be sent in the call setup.",
        "maxItems": 16,
        "items": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "key"
          ],
          "properties": {
            "key": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]+$",
              "description": "Name of the header.",
              "example": "headerKey"
            },
            "value": {
              "type": "string",
              "maxLength": 255,
              "pattern": "[\\x20-\\x7e\\t]*$",
              "description": "Value of the header.",
              "example": "headerValue"
            }
          }
        },
        "examples": [
          [
            {
              "key": "headerKey",
              "value": "headerValue"
            },
            {
              "key": "anotherKey",
              "value": "anotherValue"
            }
          ]
        ]
      },
      "stream": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stream",
        "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing.",
        "required": [
          "type",
          "stream"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "STREAM",
            "description": "Routes the call to a WebSocket stream endpoint for real-time audio processing."
          },
          "stream": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "description": "WebSocket endpoint that will accept the incoming connection for real-time audio streaming. Must be a valid WebSocket URL using either `ws://` or `wss://` (recommended). The URL must be reachable from the public internet and capable of handling the negotiated stream protocol.",
                "example": "wss://example.com"
              },
              "streamOptions": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "version": {
                    "type": "integer",
                    "description": "Defines the version of the stream protocol.",
                    "default": 1,
                    "example": 1
                  },
                  "codec": {
                    "type": "string",
                    "const": "PCM",
                    "description": "Defines the audio codec/format used for the stream audio payload.\n\nCurrently, only `PCM` is supported (uncompressed raw audio). Use `sampleRate` to configure the sampling rate for the stream."
                  },
                  "sampleRate": {
                    "type": "integer",
                    "description": "Defines the audio sampling rate (Hz) used for the stream.\n\nFor calls that traverse the PSTN, audio is typically sampled at 8 kHz, so using a higher value will not improve perceived quality. \nHigher sample rates can be useful for non-PSTN scenarios (for example, SIP/streaming paths), but will increase bandwidth usage and processing load.",
                    "enum": [
                      8000,
                      16000,
                      24000,
                      44100,
                      48000,
                      96000
                    ],
                    "x-enumDescriptions": {
                      "8000": "8 kHz (standard for PSTN calls)",
                      "16000": "16 kHz (wideband audio)",
                      "24000": "24 kHz (super-wideband audio)",
                      "44100": "44.1 kHz (CD quality audio)",
                      "48000": "48 kHz (professional audio quality)",
                      "96000": "96 kHz (high-resolution audio)"
                    },
                    "default": 8000,
                    "example": 16000
                  }
                }
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            },
            "examples": [
              {
                "endpoint": "wss://example.com",
                "streamOptions": {
                  "version": 1,
                  "codec": "PCM",
                  "sampleRate": 8000
                },
                "callHeaders": [
                  {
                    "key": "my-key",
                    "value": "my-key-value"
                  }
                ]
              }
            ]
          }
        },
        "examples": [
          {
            "type": "STREAM",
            "stream": {
              "endpoint": "wss://example.com",
              "streamOptions": {
                "version": 1,
                "codec": "PCM",
                "sampleRate": 16000
              },
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "voiceRelay": {
        "type": "object",
        "additionalProperties": false,
        "title": "Voice Relay",
        "description": "Routes the call through the Voice Relay service, enabling real-time speech-to-text (STT) and text-to-speech (TTS) via a WebSocket connection to the application backend.",
        "required": [
          "type",
          "voiceRelay"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "VOICE_RELAY",
            "description": "Connects to the Voice Relay service to enable STT and TTS services..."
          },
          "voiceRelay": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "endpoint",
              "ttsVoice",
              "sttLanguage"
            ],
            "properties": {
              "endpoint": {
                "type": "string",
                "format": "uri",
                "description": "URL to the server that will accept the web-socket request",
                "example": "wss://acme.com/agent"
              },
              "enableInterruptions": {
                "type": "boolean",
                "description": "Allow \"barge-in\" during text-to-speech (TTS) playback.\n\nWhen `true`, TTS playback is interrupted as soon as inbound speech is detected, unless the currently playing content is marked as uninterruptible.\n\nWhen `false`, TTS playback continues uninterrupted, but an interruption signal is still sent over the WebSocket so the client application can choose to stop playback manually if needed.",
                "default": true,
                "example": true
              },
              "ttsVoice": {
                "type": "string",
                "description": "Name of the voice to be used when synthesizing speech. \n\nThis is the default voice used, if no override voice is provided in the web-socket TTS message.\n\nSupported voices include: Emma, Brian, and others. For a complete list of available voices and their characteristics, see the [Text-to-Speech Voices documentation](/docs/voice/api-reference/text-to-speech-voices).",
                "example": "Emma"
              },
              "sttLanguage": {
                "type": "string",
                "pattern": "^[a-z]{2,3}(-[A-Z][a-z]{3})?(-([A-Z]{2}|[0-9]{3}))?$",
                "description": "BCP-47 language tag used for speech-to-text transcription of the inbound audio.\n\nThis value determines which language model is used for transcription.",
                "example": "en-US"
              },
              "callHeaders": {
                "$ref": "#/components/schemas/callHeaders"
              }
            }
          }
        },
        "examples": [
          {
            "type": "VOICE_RELAY",
            "voiceRelay": {
              "endpoint": "wss://acme.com/agent",
              "enableInterruptions": true,
              "ttsVoice": "Emma",
              "sttLanguage": "en-US",
              "callHeaders": [
                {
                  "key": "my-key",
                  "value": "my-key-value"
                }
              ]
            }
          }
        ]
      },
      "to": {
        "title": "To",
        "description": "Call destination - Phone Number or Stream URI",
        "oneOf": [
          {
            "$ref": "#/components/schemas/phone"
          },
          {
            "$ref": "#/components/schemas/sip"
          },
          {
            "$ref": "#/components/schemas/stream"
          },
          {
            "$ref": "#/components/schemas/voiceRelay"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "PHONE": "#/components/schemas/phone",
            "SIP": "#/components/schemas/sip",
            "STREAM": "#/components/schemas/stream",
            "VOICE_RELAY": "#/components/schemas/voiceRelay"
          }
        }
      },
      "callEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Call Events Webhook",
        "description": "Webhook to handle call events, used when callBehaviors are set to WEBHOOK",
        "properties": {
          "onAnswer": {
            "description": "SVAML commands to be executed when the call is answered",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onBusy": {
            "description": "SVAML commands to be executed when the call is busy",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onReject": {
            "description": "SVAML commands to be executed when the call is rejected",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onTimeout": {
            "description": "SVAML commands to be executed when the call is timed out",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onHangup": {
            "description": "SVAML commands to be executed when the call is hung up",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "SVAML commands to be executed when the call fails",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "dial": {
        "type": "object",
        "additionalProperties": false,
        "title": "Dial",
        "description": "Initiates a new outbound call leg within the current session.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while the call is being established in parallel. Call lifecycle events (answer, busy, reject, timeout, hangup, failure) are handled via the `events` property.\n\nThe `from` and `to` endpoint types should ideally match. If they differ, the platform attempts to convert the `from` value to be compatible with the `to` type. For example, PSTN supports only E.164 phone numbers, so a SIP address such as `sip:46701234567@acme.se` can be converted to an E.164 number. If the `from` value cannot be converted, it defaults to null (anonymous).",
        "required": [
          "command",
          "to"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "dial",
            "description": "Command to initiate a new call"
          },
          "callName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "outgoing",
            "description": "Identifier for this call leg within the session. Must be unique across all active call legs in the session.\n\nOther commands (e.g., `hangup`) can reference this name to target this specific leg."
          },
          "from": {
            "$ref": "#/components/schemas/from"
          },
          "to": {
            "$ref": "#/components/schemas/to"
          },
          "dialTimeoutDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "description": "Maximum time in seconds to wait for the call to be answered. If the timeout expires without an answer, the `onTimeout` event is triggered.",
            "example": 15
          },
          "maxCallDurationSeconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 14400,
            "description": "Maximum duration of the call in seconds. The call is terminated automatically when this limit is reached.",
            "example": 3600
          },
          "events": {
            "$ref": "#/components/schemas/callEvents"
          }
        },
        "examples": [
          {
            "command": "dial",
            "callName": "destination",
            "from": {
              "type": "PHONE",
              "phone": {
                "number": "+15551234567"
              }
            },
            "to": {
              "type": "PHONE",
              "phone": {
                "number": "+15559876543"
              }
            },
            "dialTimeoutDurationSeconds": 30,
            "maxCallDurationSeconds": 3600,
            "events": {
              "onAnswer": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Your call has connected.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "messageEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Message Events",
        "description": "SVAML commands to execute based on message playback outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when all messages in the sequence have finished playing.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "messages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Messages",
        "description": "Plays one or more messages on the call. Multiple messages in the array are played sequentially in order.\n\nThis is a non-blocking command — the next command in the sequence executes immediately while messages play in parallel. \nPlayback outcomes are handled via the `events` property. The `onFinish` event can be used to run a command after all messages complete.",
        "required": [
          "command",
          "messages"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "messages",
            "description": "Command to play a message on the channel"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message for identification and reference within the call session.\n\nThis name is used to uniquely identify the message and must be unique within the current call session.\nThis name can be referenced in other commands (e.g., `stopMessages`) to control this specific message.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-messages"
          },
          "messages": {
            "$ref": "#/components/schemas/typesOfMessages"
          },
          "events": {
            "$ref": "#/components/schemas/messageEvents"
          }
        },
        "examples": [
          {
            "command": "messages",
            "messagesName": "greeting-sequence",
            "messages": [
              {
                "type": "SAY",
                "say": {
                  "text": "Hello! Your call is being connected.",
                  "voiceName": "Emma"
                }
              },
              {
                "type": "PLAY",
                "play": {
                  "url": "https://example.com/audio/hold-music.mp3"
                }
              },
              {
                "type": "SAY",
                "say": {
                  "text": "<speak><prosody volume=\"-6dB\">Thank you for waiting.</prosody></speak>",
                  "format": "SSML",
                  "voiceName": "Emma"
                }
              }
            ]
          }
        ]
      },
      "stopMessages": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Messages",
        "description": "Stops a message sequence previously started by a `messages` command. Use `messagesName` to target a specific sequence and `flags` to control whether only the current message or all queued messages are cancelled. \n\nThis is a non-blocking command.",
        "required": [
          "command",
          "messagesName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopMessages",
            "description": "Command to stop playing messages"
          },
          "messagesName": {
            "type": "string",
            "description": "Name of the message sequence to stop, as set by `messagesName` in the `messages` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$"
          },
          "flags": {
            "type": "string",
            "description": "Controls how much of the sequence is stopped — only the currently playing message or all remaining queued messages.",
            "default": "ALL_FROM_NOW_ON",
            "enum": [
              "ONLY_PLAYING",
              "ALL_FROM_NOW_ON"
            ],
            "x-enumDescriptions": {
              "ONLY_PLAYING": "Stops only the currently playing message. Queued messages will continue to play.",
              "ALL_FROM_NOW_ON": "Stops the currently playing message and cancels all queued messages."
            }
          }
        },
        "examples": [
          {
            "command": "stopMessages",
            "messagesName": "my-messages",
            "flags": "ONLY_PLAYING"
          }
        ]
      },
      "webhookFallbackUrl": {
        "title": "Webhook Fallback URL",
        "type": "string",
        "format": "uri",
        "description": "Fallback webhook URL used when the primary webhook URL fails.\n\nA failed request is re-sent to this URL immediately. After repeated consecutive failures of the primary URL, requests are sent only here until the primary URL recovers.\n\nSee *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "examples": [
          "https://example.com/fallback"
        ]
      },
      "webhook": {
        "type": "object",
        "additionalProperties": false,
        "title": "Webhook",
        "description": "Triggers a mid-call webhook to the application backend, allowing it to return a new set of SVAML commands that control the remainder of the call flow.\n\nThis is a blocking command — execution pauses until a response is received from the webhook endpoint. The next command in the sequence runs only after the backend responds. Webhook requests use a 5-second timeout. If a `fallbackUrl` is provided, a failed request is re-sent to it — see *Timeouts and failover* in the **Webhooks** section for the authoritative algorithm.",
        "required": [
          "command",
          "webhookName",
          "url"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "webhook",
            "description": "Command to trigger a mid-call webhook"
          },
          "webhookName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^\\S+$",
            "description": "Name for this webhook event. When triggered, the webhook request's `event` property will contain this name prepended with `call.webhook.`.\n\nFor example, if `webhookName` is set to `\"my.custom.event\"`, the event will be delivered as `\"call.webhook.my.custom.event\"`."
          },
          "url": {
            "type": "string",
            "description": "URL of the webhook endpoint to send the mid-call event to.",
            "format": "uri"
          },
          "fallbackUrl": {
            "$ref": "#/components/schemas/webhookFallbackUrl"
          }
        },
        "examples": [
          {
            "command": "webhook",
            "webhookName": "my.custom.event",
            "url": "https://example.com/webhook",
            "fallbackUrl": "https://example.com/fallback"
          }
        ]
      },
      "hangup": {
        "type": "object",
        "additionalProperties": false,
        "description": "Ends a call leg. This is a non-blocking command — execution continues to the next command in the sequence even though the call has been ended. The `onHangup` event is triggered for the call leg that was ended.\n\nAny subsequent commands that target the ended call leg (such as `messages` or other media commands) are valid but will not be executed. Commands that operate independently — such as initiating a new call with `dial` — will execute normally. This makes it possible, for example, to end one call and immediately start another within the same sequence.",
        "title": "Hangup",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "hangup",
            "description": "Hangup call"
          },
          "callName": {
            "type": "string",
            "description": "Name of the call leg to end, as set by `callName` in the `dial` command.\n\nIf omitted, the current call leg is ended.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "origin"
          }
        },
        "examples": [
          {
            "command": "hangup",
            "callName": "origin"
          }
        ]
      },
      "answer": {
        "type": "object",
        "additionalProperties": false,
        "title": "Answer",
        "description": "Answers an inbound call leg. This is a non-blocking command — execution continues to the next command in the sequence immediately after the answer is initiated.",
        "required": [
          "command"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "answer",
            "description": "Answer call"
          }
        },
        "examples": [
          {
            "command": "answer"
          }
        ]
      },
      "pause": {
        "type": "object",
        "additionalProperties": false,
        "title": "Pause",
        "description": "Delays execution of the next command in the sequence for a specified duration. This is a blocking command — no further commands execute until the pause completes.\n\nThe pause does not affect call audio; the call remains connected and audio continues uninterrupted.",
        "required": [
          "command",
          "durationMilliseconds"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "pause",
            "description": "Pause execution."
          },
          "durationMilliseconds": {
            "type": "integer",
            "minimum": 1,
            "description": "Duration of the pause in milliseconds.",
            "example": 1000
          }
        },
        "examples": [
          {
            "command": "pause",
            "durationMilliseconds": 1500
          }
        ]
      },
      "recordingFormat": {
        "title": "Recording Format",
        "description": "Audio format for this recording.",
        "type": "string",
        "enum": [
          "MP3",
          "WAV"
        ],
        "x-enumDescriptions": {
          "MP3": "MPEG Audio Layer III compressed audio format.",
          "WAV": "Waveform Audio File Format, uncompressed audio."
        },
        "default": "MP3",
        "examples": [
          "MP3"
        ]
      },
      "recordingType": {
        "title": "Recording Type",
        "description": "The type of recording to perform.",
        "type": "string",
        "enum": [
          "COMBINED",
          "INBOUND",
          "OUTBOUND"
        ],
        "x-enumDescriptions": {
          "COMBINED": "Record inbound and outbound voice streams.",
          "INBOUND": "Record inbound voice stream only.",
          "OUTBOUND": "Record outbound voice stream only."
        },
        "default": "COMBINED"
      },
      "recordingDestination": {
        "title": "Recording Destination",
        "type": "string",
        "description": "Select target service to receive recorded and transcribed files",
        "enum": [
          "AWS",
          "GCP",
          "AZURE"
        ],
        "x-enumDescriptions": {
          "AWS": "Store recordings in Amazon Web Services S3 bucket. Use `s3` as schema for the URL.",
          "GCP": "Store recordings in Google Cloud Platform Storage. Use `gs` as schema for the URL.",
          "AZURE": "Store recordings in Microsoft Azure Blob Storage.  Use `azure` as schema for the URL."
        },
        "default": "AWS",
        "examples": [
          "AWS"
        ]
      },
      "transcriptionOptions": {
        "title": "Transcription Options",
        "description": "Configuration for automatic speech-to-text transcription of the recording.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "isEnabled"
        ],
        "properties": {
          "isEnabled": {
            "type": "boolean",
            "description": "If true, the recording will be transcribed to text.",
            "example": true
          },
          "locale": {
            "type": "string",
            "description": "Language code in BCP-47 format.",
            "default": "en-US",
            "example": "en-US"
          }
        }
      },
      "recordingOptions": {
        "title": "Recording Options",
        "type": "object",
        "additionalProperties": false,
        "description": "Recording options for this recording.",
        "required": [
          "destination",
          "destinationUrl",
          "credentials"
        ],
        "properties": {
          "format": {
            "$ref": "#/components/schemas/recordingFormat"
          },
          "recordingType": {
            "$ref": "#/components/schemas/recordingType"
          },
          "destination": {
            "$ref": "#/components/schemas/recordingDestination"
          },
          "destinationUrl": {
            "type": "string",
            "description": "Destination URL for the recording.",
            "example": "s3://voice-recordings-prod/calls"
          },
          "credentials": {
            "type": "string",
            "description": "Credentials to third party storage.",
            "example": "accessKeyId:secretAccessKey:eu-central-1"
          },
          "transcriptionOptions": {
            "$ref": "#/components/schemas/transcriptionOptions"
          }
        }
      },
      "recordingEvents": {
        "type": "object",
        "additionalProperties": false,
        "title": "Recording Events",
        "description": "SVAML commands to execute based on recording lifecycle outcomes.\n",
        "properties": {
          "onFinish": {
            "description": "Commands to execute when the recording is successfully stopped. Note that this does not mean that the file is delivered to the configured destination yet.\n",
            "$ref": "#/components/schemas/svamlCommands"
          },
          "onFailure": {
            "description": "Commands to execute if the recording fails to start. If omitted, failures are silently ignored and the call flow continues.\n",
            "$ref": "#/components/schemas/svamlCommands"
          }
        }
      },
      "startRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Start Recording",
        "required": [
          "command",
          "recordingOptions"
        ],
        "description": "Starts recording the call. This is a non-blocking command — execution continues to the next command in the sequence immediately after recording begins.",
        "properties": {
          "command": {
            "type": "string",
            "const": "startRecording",
            "description": "Command to start recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Identifier for this recording within the session. Must be unique across active recordings in the session.\n\nOther commands (e.g., `stopRecording`) reference this name to target a specific recording.\n\nSetting the recording name is useful for stopping the recording using the `stopRecording` command. If name is not set, recording can only be stopped when the call is disconnected.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          },
          "recordingOptions": {
            "$ref": "#/components/schemas/recordingOptions"
          },
          "events": {
            "$ref": "#/components/schemas/recordingEvents"
          }
        },
        "examples": [
          {
            "command": "startRecording",
            "recordingName": "customer-support-recording",
            "recordingOptions": {
              "format": "MP3",
              "recordingType": "COMBINED",
              "destination": "AWS",
              "destinationUrl": "s3://voice-recordings-prod/calls",
              "credentials": "accessKeyId:secretAccessKey:eu-central-1",
              "transcriptionOptions": {
                "isEnabled": true,
                "locale": "en-US"
              }
            },
            "events": {
              "onFinish": [
                {
                  "command": "hangup"
                }
              ],
              "onFailure": [
                {
                  "command": "messages",
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Recording could not be started for this call.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "stopRecording": {
        "type": "object",
        "additionalProperties": false,
        "title": "Stop Recording",
        "description": "Stops a recording previously started by a `startRecording` command. This is a non-blocking command — execution continues to the next command in the sequence immediately after the stop is initiated.",
        "required": [
          "command",
          "recordingName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "stopRecording",
            "description": "Command to stop recording on the channel"
          },
          "recordingName": {
            "type": "string",
            "description": "Name of the recording to stop, as set by `recordingName` in the `startRecording` command.",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "example": "my-recording"
          }
        }
      },
      "bridgeCall": {
        "type": "object",
        "additionalProperties": false,
        "title": "Add call to bridge",
        "description": "Adds the current call to a bridge, enabling bidirectional audio communication with other calls in the same session. This is a non-blocking command — execution continues to the next command in the sequence immediately after the call joins the bridge.\n\nBridges are created automatically when referenced by name. If a bridge with the specified name already exists, the call joins that bridge; otherwise, a new bridge is created.",
        "required": [
          "command",
          "bridgeName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "bridgeCall",
            "description": "Command to add the call to a bridge"
          },
          "bridgeName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 32,
            "pattern": "^\\S+$",
            "description": "Name of the bridge to join. If no bridge with this name exists in the session, a new one is created automatically."
          }
        },
        "examples": [
          {
            "command": "bridgeCall",
            "bridgeName": "my_bridge"
          }
        ]
      },
      "menu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Run menus",
        "description": "Defines a set of named menus and executes them starting from startMenu. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\nEach menu item configures prompts, input collection, timeout handling, and repeat behavior.",
        "required": [
          "command",
          "startMenu",
          "menus"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "menu",
            "description": "Executes menu-based input collection using the configured menu definitions."
          },
          "startMenu": {
            "type": "string",
            "minLength": 1,
            "maxLength": 16,
            "description": "Name of the menu to execute first. Must match a key in menus."
          },
          "menus": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "maxLength": 16
            },
            "description": "Map of menu definitions keyed by menu name.",
            "additionalProperties": {
              "$ref": "#/components/schemas/menuItem"
            }
          }
        },
        "examples": [
          {
            "command": "menu",
            "startMenu": "main",
            "menus": {
              "main": {
                "prompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "repeatPrompt": {
                  "allowBargeIn": true,
                  "messages": [
                    {
                      "type": "SAY",
                      "say": {
                        "text": "Invalid option. Press 1 for sales or 2 for support.",
                        "voiceName": "Emma"
                      }
                    }
                  ]
                },
                "inputTimeoutDurationSeconds": 5,
                "repeatCount": 2,
                "minimumInputLength": 1,
                "maximumInputLength": 1,
                "inputMethods": [
                  "DTMF"
                ],
                "matches": {
                  "1": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to sales.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "sales",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15551234567"
                        }
                      }
                    }
                  ],
                  "2": [
                    {
                      "command": "messages",
                      "messages": [
                        {
                          "type": "SAY",
                          "say": {
                            "text": "Connecting to support.",
                            "voiceName": "Emma"
                          }
                        }
                      ]
                    },
                    {
                      "command": "dial",
                      "callName": "support",
                      "to": {
                        "type": "PHONE",
                        "phone": {
                          "number": "+15557654321"
                        }
                      }
                    }
                  ]
                },
                "onFail": [
                  {
                    "command": "messages",
                    "messages": [
                      {
                        "type": "SAY",
                        "say": {
                          "text": "Sorry, no valid selection was received.",
                          "voiceName": "Emma"
                        }
                      }
                    ]
                  },
                  {
                    "command": "hangup"
                  }
                ]
              }
            }
          }
        ]
      },
      "gotoMenu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Goto Menu",
        "description": "Switches execution to another menu within the current menu context. The menu name must be a menu defined in the `menu` command. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\n**Important**: this command can only be called within a menu execution context.",
        "required": [
          "command",
          "menuName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "gotoMenu",
            "description": "Switch execution to another menu within the current menu context."
          },
          "menuName": {
            "type": "string",
            "description": "Name of the target menu to execute next. Must match a key in menus.",
            "minLength": 1,
            "maxLength": 16
          }
        }
      },
      "svamlCommand": {
        "title": "SVAML Command",
        "type": "object",
        "description": "A single SVAML (Sinch Voice Application Markup Language) command that controls call behavior.\n\nThe `command` property acts as a discriminator and determines which command schema applies. When multiple commands appear in a `svamlCommands` array, they execute sequentially in order.\n\n**Available commands:**\n- `dial` — Initiate an outbound call leg within the session.\n- `messages` — Play one or more TTS or audio messages on the call.\n- `stopMessages` — Stop a currently playing message sequence.\n- `webhook` — Trigger a mid-call webhook to the application backend for dynamic call control.\n- `amd` — Detect whether the call was answered by a human or an answering machine.\n- `hangup` — End the call or a specific call leg within the session.\n- `answer` — Explicitly answer an incoming call leg before executing further commands.\n- `pause` — Delay script execution without affecting call audio.\n- `startRecording` — Begin recording the call.\n- `stopRecording` — Stop an active call recording.\n- `bridgeCall` — Add the call to a named bridge for multi-party audio.\n- `menu` — Run menu-based input collection and route the call based on collected input.\n- `gotoMenu` — Switch execution to another named menu within the current menu context.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/amd"
          },
          {
            "$ref": "#/components/schemas/dial"
          },
          {
            "$ref": "#/components/schemas/messages"
          },
          {
            "$ref": "#/components/schemas/stopMessages"
          },
          {
            "$ref": "#/components/schemas/webhook"
          },
          {
            "$ref": "#/components/schemas/hangup"
          },
          {
            "$ref": "#/components/schemas/answer"
          },
          {
            "$ref": "#/components/schemas/pause"
          },
          {
            "$ref": "#/components/schemas/startRecording"
          },
          {
            "$ref": "#/components/schemas/stopRecording"
          },
          {
            "$ref": "#/components/schemas/bridgeCall"
          },
          {
            "$ref": "#/components/schemas/menu"
          },
          {
            "$ref": "#/components/schemas/gotoMenu"
          }
        ],
        "discriminator": {
          "propertyName": "command",
          "mapping": {
            "amd": "#/components/schemas/amd",
            "dial": "#/components/schemas/dial",
            "messages": "#/components/schemas/messages",
            "stopMessages": "#/components/schemas/stopMessages",
            "webhook": "#/components/schemas/webhook",
            "hangup": "#/components/schemas/hangup",
            "answer": "#/components/schemas/answer",
            "pause": "#/components/schemas/pause",
            "startRecording": "#/components/schemas/startRecording",
            "stopRecording": "#/components/schemas/stopRecording",
            "bridgeCall": "#/components/schemas/bridgeCall",
            "menu": "#/components/schemas/menu",
            "gotoMenu": "#/components/schemas/gotoMenu"
          }
        }
      },
      "menuItem": {
        "type": "object",
        "additionalProperties": false,
        "title": "Menu Item",
        "description": "Defines a single menu step, including prompts, input handling rules, input-to-command matches, and failure handling.\n\nEach collected input is matched against the values in the `matches` property.\nIf no match succeeds, the `onFail` commands are executed.\n\nIf neither `matches` nor `onFail` is defined and the service call behavior is set to `WEBHOOK`, a webhook request is sent including the collected input.",
        "properties": {
          "prompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when this menu starts.\n\nThis prompt is also used as the repeat prompt when repeatPrompt is not defined for the menu."
          },
          "repeatPrompt": {
            "$ref": "#/components/schemas/menuPrompt",
            "description": "Prompt played when the menu is repeated.\n\nRepeats occur when input times out or when the provided input does not match any menu match item."
          },
          "inputTimeoutDurationSeconds": {
            "type": "integer",
            "description": "Maximum number of seconds to wait for user input before the input attempt times out.",
            "minimum": 1,
            "maximum": 60,
            "default": 5,
            "example": 10
          },
          "repeatCount": {
            "type": "integer",
            "description": "Maximum number of times the menu is repeated.\n\nA repeat occurs when input times out or when the provided input does not match any menu match item.",
            "minimum": 0,
            "maximum": 10,
            "default": 2,
            "example": 3
          },
          "minimumInputLength": {
            "type": "integer",
            "description": "Minimum number of input characters required before the menu evaluates the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 3
          },
          "maximumInputLength": {
            "type": "integer",
            "description": "Maximum number of input characters that triggers the menu to evaluate the collected input.",
            "minimum": 1,
            "maximum": 100,
            "default": 1,
            "example": 10
          },
          "terminatingSequence": {
            "type": "string",
            "pattern": "^[0-9*#]+$",
            "description": "Character sequence that signals the end of input and triggers immediate evaluation.\n\nUseful when variable-length input is allowed and shorter valid options should be submitted without waiting for timeout or maximum length.\n\nThe terminating sequence value is included in the evaluated input.",
            "maxLength": 10
          },
          "inputMethods": {
            "type": "array",
            "description": "Input methods accepted for this menu when collecting user input.",
            "default": [
              "DTMF"
            ],
            "items": {
              "type": "string",
              "enum": [
                "DTMF"
              ],
              "x-enumDescriptions": {
                "DTMF": "Collect input from keypad tones (Dual-Tone Multi-Frequency)."
              }
            }
          },
          "matches": {
            "type": "object",
            "description": "Items matched against the collected input. Maximum number of allowed match expressions is 50.\n\nDefined as a dictionary where each property name is a literal or a regular expression string.\n\nValues are evaluated in the order they are defined.",
            "maxProperties": 50,
            "propertyNames": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "description": "A regular expression or literal string to match against the collected user input. Must not be empty.\n\nProperty keys are evaluated sequentially in the order defined. The first key that matches the input will trigger its associated SVAML commands.\n\n**Note**: Use `\\\\*` to match the DTMF star tone (*)."
            },
            "additionalProperties": {
              "$ref": "#/components/schemas/svamlCommands"
            }
          },
          "onFail": {
            "$ref": "#/components/schemas/svamlCommands",
            "description": "SVAML commands executed when the menu fails to collect a matching input.\n\nThis handler runs after the repeat limit is reached without any input matching a menu match item."
          }
        }
      }
    }
  }
}
```

### `gotoMenu`

Navigate IVR Menus

```json
{
  "command": "gotoMenu",
  "menuName": "string"
}
```

**Schema:**

```json
{
  "$ref": "#/components/schemas/gotoMenu",
  "components": {
    "schemas": {
      "gotoMenu": {
        "type": "object",
        "additionalProperties": false,
        "title": "Goto Menu",
        "description": "Switches execution to another menu within the current menu context. The menu name must be a menu defined in the `menu` command. This is a blocking command — execution waits for the menu to complete before proceeding to the next command.\n\n**Important**: this command can only be called within a menu execution context.",
        "required": [
          "command",
          "menuName"
        ],
        "properties": {
          "command": {
            "type": "string",
            "const": "gotoMenu",
            "description": "Switch execution to another menu within the current menu context."
          },
          "menuName": {
            "type": "string",
            "description": "Name of the target menu to execute next. Must match a key in menus.",
            "minLength": 1,
            "maxLength": 16
          }
        }
      }
    }
  }
}
```

See the API reference for a full list of supported commands and their parameters.

## Example: An entire call behavior defined with SVAML Commands

This example illustrates a complete call flow defined in a single SVAML payload:

- The call begins with a `dial` command.
- When the call is answered, the `on_answer` event triggers a sequence of other commands:
  - **AMD Detection:** Performs Answering Machine Detection.
  - **Pause:** Introduces a brief delay.
  - **Message Playback:** Plays a message to the callee.
- If AMD detects a machine or a beep, nested event handlers execute additional commands:
  - **Stop Messages:** Stops any ongoing message playback.
  - **Play Alternate Messages:** Delivers an alternate message based on the event.
  - **Hang Up:** Ends the call.


All actions are handled within the SVAML payload, eliminating the need for webhook round-trips.

```json
{
  "commands": [
    {
      "command": "dial",
      "name": "outbound_call",
      "from": {
        "type": "PHONE",
        "phone": {
          "number": "+46701234567"
        }
      },
      "to": {
        "type": "PHONE",
        "phone": {
          "number": "+46701234568"
        }
      },
      "events": [
        {
          "on_answer": [
            {
              "command": "amd",
              "events": [
                {
                  "on_machine": [
                    {
                      "command": "pause",
                      "duration": "1500ms"
                    },
                    {
                      "command": "messages",
                      "name": "da-other-messages",
                      "messages": [
                        {
                          "type": "say",
                          "say": "Detected machine, alternate message played.",
                          "format": "text"
                        }
                      ]
                    },
                    {
                      "command": "hangup"
                    }
                  ]
                },
                {
                  "on_beep": [
                    {
                      "command": "stop-messages",
                      "name": "da-messages"
                    },
                    {
                      "command": "messages",
                      "name": "da-other-messages",
                      "messages": [
                        {
                          "type": "say",
                          "say": "Beep detected, stopping previous messages and playing new one.",
                          "format": "text"
                        }
                      ]
                    },
                    {
                      "command": "hangup"
                    }
                  ]
                }
              ]
            },
            {
              "command": "pause",
              "duration": "1500ms"
            },
            {
              "command": "messages",
              "name": "da-messages",
              "messages": [
                {
                  "type": "say",
                  "say": "Hello, this is a test message",
                  "format": "text"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}
```