Logo
Search
API Docs

Live Call Control

Live Call Features

Live Call Control: The controlUrl

Overview

When you create a call via the /call endpoint, the response includes a monitor object with two URLs for interacting with that call while it's still in progress: listenUrl and controlUrl. The Live Call Monitoring page covers listenUrl in detail — a read-only WebSocket for streaming the call's audio without touching it. This page is the complete reference for controlUrl: a plain HTTPS endpoint you POST to in order to take action on a live call from your own server or backend system.

Where listenUrl only lets you listen, controlUrl lets you act — forcing the assistant to say something, injecting a message into the conversation, muting or unmuting the assistant, ending the call outright, or routing it elsewhere. Live Call Monitoring already demonstrates two of these actions (say and add-message) framed around whisper/barge-in supervisor scenarios; this page documents every control action type controlUrl supports, independent of any particular use case.


Getting the controlUrl

Initiate a call via the /call endpoint as usual. The response includes a monitor object containing both URLs:

{
  "monitor": {
    "listenUrl": "wss://phone-call-websocket.sulus.ai/<call-id>/transport",
    "controlUrl": "https://phone-call-websocket.sulus.ai/<call-id>/control"
  }
}

Every control action in this page is a POST request to that same controlUrl, with a JSON body whose type field determines which action fires.


say: Force the Assistant to Speak

Use the say type to make the assistant speak specific content immediately, interrupting whatever it would otherwise do next:

curl -X POST '<controlUrl>' \
  -H 'content-type: application/json' \
  --data-raw '{
    "type": "say",
    "content": "Please hold while I transfer you to a specialist.",
    "endCallAfterSpoken": false
  }'
FieldRequiredDescription
contentYesThe exact text the assistant should speak
endCallAfterSpokenNoWhen true, the call ends automatically right after the assistant finishes speaking — useful for a closing message you want to guarantee gets said before hangup

add-message: Injecting Into the Conversation (Server-Side)

Use the add-message type to add a message to the conversation history from your own server, optionally triggering the assistant to respond to it:

curl -X POST '<controlUrl>' \
  -H 'content-type: application/json' \
  --data-raw '{
    "type": "add-message",
    "message": {
      "role": "system",
      "content": "The customer is a VIP -- offer them a 20% discount."
    },
    "triggerResponseEnabled": true
  }'
FieldRequiredDescription
message.roleYesOrigin of the message: system, user, assistant, tool, or function
message.contentYesThe text content being added
triggerResponseEnabledNoWhen true, the assistant reacts to the new message right away; when omitted or false, the message is added silently and the assistant only sees it on its next turn

How this relates to Async Server Tools & Background Messages: that page documents the client-side add-message mechanism — a background message sent from the Web SDK with sulusVoice.send({ type: "add-message" }), with no server involved at all. The add-message control covered here is the server-side, external-control equivalent: instead of the browser sending it, your own backend posts it to the controlUrl for a call already in progress. Both use the same message shape and the same underlying mechanism — they differ only in where the request originates.


control: Mute, Unmute, and Say-First-Message

Use the control type to adjust the assistant's basic call behavior. The control field accepts three values:

ValueEffect
mute-assistantMutes the assistant so it stops speaking/audio output
unmute-assistantUnmutes a previously muted assistant
say-first-messageTriggers the assistant to speak its configured first message on demand
curl -X POST '<controlUrl>' \
  -H 'content-type: application/json' \
  --data-raw '{
    "type": "control",
    "control": "mute-assistant"
  }'

end-call: Terminating the Call Programmatically

Use the end-call type to terminate the call outright from your server, without waiting for the assistant or caller to hang up:

curl -X POST '<controlUrl>' \
  -H 'content-type: application/json' \
  --data-raw '{
    "type": "end-call"
  }'

Summary of controlUrl Actions

TypeActs OnDescription
sayCurrent callForces the assistant to speak specific content immediately, with an optional auto-hangup afterward
add-messageCurrent callAdds a message to the conversation history, optionally triggering a response
controlCurrent callMutes/unmutes the assistant, or triggers the first message
end-callCurrent callEnds the call programmatically
transferRoutes elsewhereTransfers the call to a phone number or SIP URI — see Assistant-Based Warm Transfer: Deep Dive
handoffRoutes elsewhereHands the call off to a different assistant configuration — see Squad Routing: Handoff Destinations & Context Engineering

In short: say, add-message, control, and end-call all act on the current call in place, while transfer and handoff route the call somewhere else entirely. Together with the read-only listenUrl covered on Live Call Monitoring, the controlUrl gives your own backend systems full programmatic control over a call while it's still live.