# SVAML cheat sheet The actions and instructions you will actually use. Node.js uses `IceSvamlBuilder` / `PieSvamlBuilder` / `AceSvamlBuilder`. C# uses the equivalent `*Builder` classes with `.Instructions.*` and `.Action.*` accessors. For the **concept** of SVAML (what it is, when it matters), see [the SVAML concept page](#). For the **authoritative spec**, see [developers.sinch.com/docs/voice/api-reference/svaml](/docs/voice/api-reference/svaml/). ## The three builders | Builder | Where used | Available actions | | --- | --- | --- | | `Ice*` | `ice` handler | Full set: `hangup`, `connectPstn/Sip/Mxp/Conf/Agent`, `runMenu`, `park`, `continue` | | `Pie*` | `pie` handler | Same as ICE except no `park` / `answer` | | `Ace*` | `ace` handler | Only `continue` and `hangup` | Every builder chain ends with `.build()` (Node) or `.Build()` (C#). ## Instructions — things to do before the action ### `say` — text to speech ```typescript // Node .say('Welcome to Acme Corp!') .say('Bonjour!', 'fr-FR') ``` ```csharp // C# .Instructions.Say("Welcome to Acme Corp!") .Instructions.Say("Bonjour!", "fr-FR") ``` Default locale: `en-US`. ### `play` / `playFiles` — play audio ```typescript // Node .play('https://example.com/greeting.mp3') .playFiles(['file1.wav', 'file2.wav'], 'en-US') ``` ```csharp // C# .Instructions.PlayFiles(new[] { "file1.wav", "file2.wav" }, "en-US") ``` ### `setCookie` — persist a value across callbacks Store a string that survives between ICE, PIE, ACE callbacks on the same call. ```typescript .setCookie('language', 'en-US') ``` ```csharp .Instructions.SetCookie("language", "en-US") ``` ### `sendDtmf` — send tones after connecting ```typescript .sendDtmf('1234#') ``` ```csharp .Instructions.SendDtmf("1234#") ``` ### `startRecording` / `stopRecording` ```typescript // Node .startRecording({ destinationUrl: 'https://my-server.com/recordings', format: 'mp3', notificationEvents: true, }) .stopRecording() ``` ```csharp // C# .Instructions.StartRecording(new StartRecordingOptions { DestinationUrl = "https://my-server.com/recordings", Format = "mp3", NotificationEvents = true, }) .Instructions.StopRecording() ``` ## Actions — what the call does ### `hangup` ```typescript return new IceSvamlBuilder().say('Goodbye!').hangup().build(); ``` ```csharp return Ok(new IceSvamletBuilder().Instructions.Say("Goodbye!").Action.Hangup().Build()); ``` ### `continue` Let the call proceed to the next callback. ```typescript .continue() ``` ```csharp .Action.Continue() ``` ### `connectPstn` — connect to a phone number ```typescript // Node — simple .connectPstn('+15551234567') // Node — with options (all IntelliSense-discoverable) .connectPstn('+15551234567', { cli: data.cli, // show caller's number maxDuration: 3600, timeout: 30, enableAce: true, // fire ACE when answered enableDice: true, amd: { enabled: true }, // answering machine detection indications: 'us', }) ``` ```csharp // C# — simple .Action.ConnectPstn("+15551234567") // C# — with options .Action.ConnectPstn("+15551234567", new ConnectPstnOptions { Cli = data.Cli, MaxDuration = 3600, ConnectTimeout = 30, Indications = "us", }) ``` ### `connectSip` — connect to a SIP URI ```typescript .connectSip('sip:alice@sip.example.com', { cli: '+15551234567', headers: { 'X-Custom-Header': 'value' }, }) ``` ```csharp .Action.ConnectSip("sip:alice@sip.example.com", new ConnectSipOptions { Cli = "+15551234567", Transport = "TLS", Headers = new Dictionary { ["X-Custom"] = "value" }, }) ``` ### `connectConf` — join a conference ```typescript .connectConf('room-42', { moh: 'music', enableDice: true }) ``` ```csharp .Action.ConnectConf("room-42", new ConnectConfOptions { MusicOnHold = "music" }) ``` ### `connectMxp` — connect to a Sinch SDK user ```typescript .connectMxp('alice') ``` ```csharp .Action.ConnectMxp("alice") ``` ### `connectAgent` — connect to an AI voice agent ```typescript import { AgentProvider } from '@sinch/functions-runtime'; .connectAgent(AgentProvider.ElevenLabs, 'agent_abc123', { suppressCallbacks: true }) ``` ```csharp using SinchFunctions.AI; .Action.ConnectAgent(AgentProvider.ElevenLabs, "agent_abc123", new ConnectAgentOptions { SuppressCallbacks = true, }) ``` ### `park` — put the caller on hold ICE only. Not available on PIE. ```typescript .park('Your call is important to us. Please hold.', { maxDuration: 600 }) ``` ```csharp .Action.Park("Your call is important to us. Please hold.", new ParkOptions { MaxDuration = 600 }) ``` ### `runMenu` — run an IVR menu (PIE fires after) ```typescript import { createMenu, MenuTemplates } from '@sinch/functions-runtime'; // Template .runMenu(MenuTemplates.business('Acme Corp')) // Custom const menu = createMenu() .prompt('Press 1 for sales, press 2 for support.') .option('1', 'return(sales)') .option('2', 'return(support)') .maxDigits(1) .timeout(8000) .build(); .runMenu(menu) ``` ```csharp // Template .Action.RunMenu(MenuTemplates.Business("Acme Corp")) // Custom var menu = new MenuBuilder() .Prompt("Press 1 for sales, press 2 for support.") .Option("1", "return(sales)") .Option("2", "return(support)") .MaxDigits(1) .Timeout(8000) .Build(); .Action.RunMenu(menu) ``` ## Menu option action values | Action syntax | Result in PIE (`menuResult.value`) | | --- | --- | | `'return'` | The DTMF digit pressed. | | `'return(sales)'` | `'sales'` | | `'menu(submenu)'` | Navigates to another menu; PIE fires after submenu | ## Pre-built menu templates Import from the runtime package. Available in both languages unless noted. | Template | What it does | Returns | | --- | --- | --- | | `business(companyName?)` | Sales (1), Support (2), Operator (0) | `'sales'`, `'support'`, `'operator'` | | `yesNo(question?)` | Yes/No confirmation | `'yes'`, `'no'` | | `language(languages?)` | Language selection | language value strings | | `afterHours(name?, hours?)` | After-hours message | `'voicemail'`, `'website'`, `'emergency'` | | `recordingConsent()` | Recording consent prompt | `'consent'`, `'no_consent'` | | `numericInput(prompt, digits?)` | Collect multi-digit input (Node only) | the entered digits | | `CallbackRequest(waitTime?)` | Hold or callback (C# only) | `'hold'`, `'callback'` | | `CustomerService()` | 4-option customer service (C# only) | `'billing'`, `'technical'`, … | | `SatisfactionSurvey()` | Post-call survey (C# only) | `'excellent'`, `'good'`, `'fair'`, `'poor'` | ## Don't - **Don't** return raw JSON objects from voice handlers — always `.build()` through a builder. - **Don't** call `.build()` without setting an action — it throws. - **Don't** add instructions after `.build()` — the builder is frozen. - **Don't** use `AceSvamlBuilder` to connect calls — ACE only supports `continue` and `hangup`. - **Don't** use `park` in a PIE response — ICE only. ## Related - [SVAML concept](#) — what SVAML is, why builders - [Voice callbacks](#) — which callbacks return SVAML and when - [developers.sinch.com SVAML spec](/docs/voice/api-reference/svaml/) — full specification with every option