Skip to main content
A stream with protocol twilio speaks the bidirectional Twilio Media Streams protocol over its WebSocket. This page lists every message and field. To connect a bot, such as a Pipecat bot, see Bring your Twilio or Pipecat app. The connection itself works as for any stream: Fonoster dials the stream’s URL and signs the request. See Session protocol: Connection and Verify request signatures.

Messages Fonoster sends

Every message except connected carries sequenceNumber, a string that counts up from "1", and streamSid.
first message
{ "event": "connected", "protocol": "Call", "version": "1.0.0" }
once, after connected
caller audio, every 20 ms
media.track is always "inbound". media.chunk is a string that counts up from "1". media.timestamp is milliseconds since the stream started, as a string. media.payload is base64 μ-law, 8000 Hz, mono, without headers.
caller keypress
dtmf.track is always "inbound_track". dtmf.digit is the key.
answer to your mark
mark.name is the name you sent. Sent when the audio queued before the mark has played, or when clear drops it.
last message
stop.accountSid and stop.callSid, as in start. Fonoster then closes the socket.
This is what a bot receives at the start of a call:

Messages Fonoster accepts

Fonoster doesn’t read streamSid on incoming messages. It ignores binary frames, invalid JSON, media without a payload, mark without a name, and any other event. The call continues.

Differences from Twilio

What isn’t supported

  • TwiML. Fonoster doesn’t fetch or run TwiML. The stream’s URL is the WebSocket itself.
  • A speech layer. Fonoster doesn’t transcribe the caller or speak text for you. The stream’s voice and speech settings don’t apply.
  • Call control. No transfer, hold or sending keypresses. Use the fonoster protocol for those.
  • Events of the fonoster protocol, such as turn events and the answering-machine verdict. Your bot gets only the messages listed above.

Hanging up

Closing the WebSocket hangs up the call, on every install. Fonoster can also serve Twilio’s hang-up request, where the operator turns it on:
{accountSid} is the workspace’s access key ID and {callSid} the callSid from start. The operator configures how Basic auth is checked:
  • Workspace API keys: the user is an API key ID (AP…) and the password its secret. The key must belong to the workspace in the URL.
  • One fixed pair (self-hosted installs): the user and the URL’s accountSid are the pair’s accountSid, and the password its authToken.
Error bodies have Twilio’s shape: { code, message, more_info, status }. With Pipecat, set base_url on TwilioFrameSerializer to the endpoint’s address and auto_hang_up works unchanged.