Get started →
Documentation

Receive calls with TwiML

When someone calls one of your numbers, Ruut Voice answers and executes a set of TwiML instructions — XML that tells the platform what to say, play, gather, or dial next.

How inbound call handling works

  1. A caller dials a number assigned to your account.
  2. Ruut Voice sends an HTTP request to the number's Voice URL (GET or POST).
  3. Your server returns TwiML.
  4. Ruut Voice executes the TwiML: speaks, plays audio, gathers input, or dials out.

Configure the Voice URL

Set the Voice URL in the dashboard for the incoming number, or via the IncomingPhoneNumbers API:

curlbash

curl -X POST "https://voice.ruut.chat/2010-04-01/Accounts/$RUUT_ACCOUNT_SID/IncomingPhoneNumbers/$NUMBER_SID" \
  -u "$RUUT_ACCOUNT_SID:$RUUT_AUTH_TOKEN" \
  --data-urlencode "VoiceUrl=https://app.example.com/twiml/inbound" \
  --data-urlencode "VoiceMethod=POST"

A simple greeting

Your endpoint returns XML. Here's a greeting that also plays a tone:

TwiMLxml


  Thanks for calling!

Build it with the SDK instead of hand-writing XML:

Examplets

import { VoiceResponse } from "@ruut/voice-sdk";

const xml = new VoiceResponse()
  .say("Thanks for calling!", { voice: "alice", language: "en-NG" })
  .toXml();

An IVR menu

Combine <Gather> and <Say> to collect a digit and route the caller:

TwiMLxml


  
    Press 1 for sales. Press 2 for support.
  
  We did not receive any input. Goodbye.

The action URL is requested with the gathered digits (as Digits) when the caller finishes. Route on them however you like.

Dial a number or agent

Forward the call to a phone number, a SIP URI, a client, or a conference:

TwiMLxml


  +2348000000009

TwiMLxml


  
    support-room
  

Record the call

Use <Record> to capture a message, or record a bridged call with <Dial record="…">. See the recording guide for full details.

TwiML reference

Every verb and attribute is documented in the TwiML verbs reference.

The root element must always be <Response>. When building with the SDK, call .toXml() on the VoiceResponse object (not on a sub-builder like dial), or the response will be rejected.