Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.vobiz.ai/llms.txt

Use this file to discover all available pages before exploring further.

PurposeThe stop event terminates the stream from your application’s side. When Vobiz receives it:
  • The stream stops immediately and the WebSocket closes
  • Vobiz moves to the next XML element in your response (e.g. <Speak>, <Dial>, <Redirect>)
  • If there is no next element, Vobiz hangs up the call automatically (HangupCauseCode=4010)

Attributes

AttributeDescription
event
string
Required
Indicates the event type. Use stop as the value.
streamId
string
Required
A unique identifier generated for each audio stream.
This value is provided by Vobiz in the initial “start” event when the WebSocket connection is established.

Request & Response

Request Format

Send this JSON message through the WebSocket to terminate the stream:
Stop event request
{
  "event": "stop",
  "streamId": "c4dfd815-a92a-4140-ab85-5ff28c004116"
}

Response Format

There is no inbound JSON acknowledgment for the stop event. The WebSocket close itself is your confirmation.
No inbound stop event exists. Vobiz does not send { "event": "stop" } when the call ends — the WebSocket simply closes. Do not wait for an inbound JSON reply after sending the stop command. Treat the WebSocket close event as your end-of-stream signal.
What happens after you send stop:
StepWhat Vobiz does
1Stream stops immediately; WebSocket closes
2Next XML element executes — or the call hangs up automatically if there is no next element
3Event=StopStream POSTed to statusCallbackUrl
4Event=Hangup POSTed to hangup_url (only if the call ended — i.e. no further XML elements after <Stream>)

Examples

Complete Event Sequence

Send stop to end the stream
// After agent finishes its final response...

// 1. Send the last audio chunk
ws.send(JSON.stringify({
  event: 'playAudio',
  media: {
    contentType: 'audio/x-l16',
    sampleRate: 8000,
    payload: farewellAudioBase64
  }
}));

// 2. Send checkpoint to wait for playback completion
ws.send(JSON.stringify({
  event: 'checkpoint',
  streamId: '20170ada-f610-433b-8758-c02a2aab3662',
  name: 'farewell'
}));

// 3. Wait for playedStream acknowledgment, then stop
ws.on('message', (message) => {
  const data = JSON.parse(message);

  if (data.event === 'playedStream' && data.name === 'farewell') {
    // Farewell audio finished playing — now terminate the stream
    ws.send(JSON.stringify({
      event: 'stop',
      streamId: '20170ada-f610-433b-8758-c02a2aab3662'
    }));
  }
});

// 4. Handle WebSocket close (the stop confirmation)
ws.on('close', () => {
  console.log('Stream terminated successfully');
});

Node.js Implementation

Agent teardown with stop event
const WebSocket = require('ws');

let currentStreamId = null;

wss.on('connection', (ws) => {
  ws.on('message', (message) => {
    const data = JSON.parse(message);

    if (data.event === 'start') {
      currentStreamId = data.start.streamId;
      console.log('Stream started:', currentStreamId);

      // Begin conversation flow
      startConversation(ws);
    }

    if (data.event === 'playedStream') {
      console.log('Checkpoint reached:', data.name);

      if (data.name === 'farewell') {
        // Final audio played — terminate the stream
        terminateStream(ws);
      }
    }

    if (data.event === 'media') {
      // Process incoming audio
      const audioBuffer = Buffer.from(data.media.payload, 'base64');
      // ... transcribe, run through LLM, generate TTS response
    }
  });

  ws.on('close', () => {
    // WebSocket close confirms the stop was received
    console.log('Stream ended:', currentStreamId);
    cleanupSession(currentStreamId);
  });
});

function terminateStream(ws) {
  console.log('Sending stop event...');

  ws.send(JSON.stringify({
    event: 'stop',
    streamId: currentStreamId
  }));
}

function cleanupSession(streamId) {
  // Flush recordings, close DB connections, etc.
  console.log('Cleaning up session for stream:', streamId);
}

Python AsyncIO Example

Stop event in Python asyncio
import asyncio
import websockets
import json

stream_id = None

async def terminate_stream(websocket):
    """Send stop event to end the stream"""
    stop_msg = {
        'event': 'stop',
        'streamId': stream_id
    }
    await websocket.send(json.dumps(stop_msg))
    print("Stop event sent — waiting for WebSocket close")

async def handle_stream(websocket, path):
    global stream_id

    try:
        async for message in websocket:
            data = json.loads(message)

            if data['event'] == 'start':
                stream_id = data['start']['streamId']
                print(f"Stream started: {stream_id}")

                # Begin conversation
                await start_conversation(websocket)

            elif data['event'] == 'playedStream':
                print(f"Checkpoint reached: {data['name']}")

                if data['name'] == 'farewell':
                    # Final audio confirmed — end the stream
                    await terminate_stream(websocket)

            elif data['event'] == 'media':
                # Process inbound audio
                audio_bytes = __import__('base64').b64decode(data['media']['payload'])
                # ... STT / LLM / TTS pipeline

    except websockets.exceptions.ConnectionClosed:
        # WebSocket close is the stop confirmation
        print(f"Stream ended: {stream_id}")
        await cleanup_session(stream_id)

async def cleanup_session(sid):
    """Flush recordings, close connections, etc."""
    print(f"Cleaning up session: {sid}")

async def main():
    async with websockets.serve(handle_stream, "0.0.0.0", 8080):
        print("WebSocket server running on port 8080")
        await asyncio.Future()

if __name__ == "__main__":
    asyncio.run(main())

Best Practices

Play Farewell Audio Before Stopping

Send any farewell audio and a checkpoint before the stop event. Wait for the playedStream acknowledgment so the caller hears the full goodbye message before the stream terminates.

Handle the WebSocket Close Event

Wire up a ws.on('close') handler to flush in-memory buffers (recordings, transcripts) and clean up per-call state. Do not rely on a JSON reply — the close event is your only confirmation.

Avoid Sending Events After Stop

Do not send playAudio, clearAudio, or checkpoint events after the stop command. The WebSocket closes immediately and any queued sends will be dropped.