---sidebar_position: 0---# SWML Overviewimport Tabs from @theme/Tabs;import TabItem from @theme/TabItem;SignalWire Markup Language (SWML) allows you to build RELAY applications using a descriptiveformat which doesnt necessarily require additional infrastructure such as yourown server. You can think of SWML as the RELAY equivalent of[Compatibility XML](compatibility-api/xml/index.mdx). It is, however, expressedin JSON / YAML.SWML Scripts can be written and saved in the [RELAY Dashboard](https://my.signalwire.com/relay-bins) of your SignalWire Space.Heres a basic SWML document:yamlsections: main: - record - play: say:Hello, world! - hangupjson{ sections: { main: [record, { play: say:Hello, world! }, hangup] }}## Document FetchingA SWML script is fetched as follows:1. SignalWire receives a call (e.g., a PSTN call) to one of the numbers configured to use SWML.2. SignalWire sends a POST request to the configured webhook, with a body containing the set of currently defined [script variables](#variables) (initially empty) and the current call object:json{ call: { project_id: project uuid, space_id: space_uuid, call_id: uuid, state: created, type: sip, from: sip:+15551231234@example.com, to: sip:+15553214321@example.com, headers: [ { name: X-Header-1, value: X-Header-1-Value }, { name: X-Header-2, value: X-Header-2-Value } ] }, vars: { customer_script_var_1: customer_script_var_1_value, customer_script_var_2: customer_script_var_2_value }, params: { param_1: param_1_value, param_2: param_2_value }}3. The server replies with a SWML script to execute, using application/json or application/yaml or text/x-yaml as content-type.## VersioningAt the top level of a script is a version field, which is a string containing a semantic version of the document schema. Suggested use is for a MAJOR version to reflect breaking changes where a script may not operate correctly without changes (i.e., renaming, refactoring, or new required parameters for existing methods). A MINOR version can be used as new methods or new optional fields for existing methods are introduced. A PATCH version can be used to reflect only the most minor bug fixes which still have some impact on the schema.## Document ExecutionEvery SWML script contains a sections field that is a mapping of named sections forexecution. The main section is always executed first. There must always be amain section in the document. The [transfer](./methods.mdx#transfer) method is used to jump to othersections within the document, or to a new URL.Each section is an array of strings or objects. Strings can be used for methodsthat do not require parameters, such as [answer](./methods.mdx#answer),[hangup](./methods.mdx#hangup), or[denoise](./methods.mdx#denoise). Use objects to execute methods withparameters. Each string or object in the sections array is executed in orderuntil the section is completed. If there are no more methods to execute, thecall ends.## Expression Evaluation with JavaScriptAll text wrapped in %{} is evaluated as JavaScript or as a plain variable substitution.## Variables and Call Parameters {#variables}All variables and call parameters are delivered in the POST body to the URL in transfer and execute. Use the [set](./methods.mdx#set) and [unset](./methods.mdx#unset) methods to set or delete variables.All variables can be referenced inside %{} JavaScript expressions in the vars. JavaScript object.Variables can not be permanently changed inside JavaScript expressions.All Call object parameters are referenceable inside JavaScript expressions. For example %{call.from} or %{call.headers.X-Customer-ID}. Call object parameters are read only.All variables are global, and their scope corresponds to the scope of the call(_not_ of the section, and _not_ of the script).## Script ExampleIn this example, the main section is executed to answer the call, play twofiles, then jump to the get-input-1 section. The get-input-1 section prompts forDTMF input. If 1 is pressed, the flow transfers back to the main section.Otherwise the call is hung up.yamlsections: main: - answer - play: volume: 20 urls: - https://example.com/welcome.mp3 - https://example.com/music.mp3 - transfer: get-input-1 get-input-1: - prompt: - https://example.com/prompt.wav - switch: variable: prompt_value case: 1: - transfer: main - hangupjson{ sections: { main: [ answer, { play: { volume: 20.0, urls: [https://example.com/welcome.mp3, https://example.com/music.mp3] } }, { transfer: get-input-1 } ], get-input-1: [ { prompt: [https://example.com/prompt.wav] }, { switch: { variable: prompt_value, case: { 1: [{ transfer: main }] } } }, hangup ] }}## Implementing Subroutines or IntegrationsThe [execute](./methods.mdx#execute) method provides a mechanism for calling subroutines. A subroutine is implemented as a section in the document that can optionally accept named parameters and return a result or can be hosted by a server.The subroutine may optionally be implemented as an object with meta and code fields to add user-defined data and the code to execute, respectively.### JSON Subroutine in Scriptjson{ sections: { main: [ { execute: { params: { file: https://example.com/foo.wav }, meta: { x: 100, y: 100 }, dest: my_subroutine }, execute: { params: { file: https://example.com/bar.wav }, dest: my_subroutine, on_return: [ { cond: [{ when: vars.return_value == 1, then: [hangup] }] } ] } } ], my_subroutine: { meta: { foo: bar }, code: [{ play: %{params.file} }, { return: 1 }] } }}### JSON Subroutine Hosted by ServerThis operates similarly to the previous example, except the script will execute a URL that will reply with the following document:json{ sections: { main: [{ play: %{params.file} }, { return: 1 }] }}