Skip to main content

WebSocket API

Real-time bidirectional communication for audio streaming and live meeting updates. The WebSocket handles both JSON control messages and raw binary PCM audio.

Connection

wss://api.creovine.com/lira/v1/ws?token=<jwt_token>

Authentication is via JWT in the query string. The connection upgrades from HTTP to WebSocket on success.

const ws = new WebSocket(`wss://api.creovine.com/lira/v1/ws?token=${token}`);

Message Types

The protocol uses two channels:

  • JSON messages — control signals, transcripts, and metadata
  • Binary frames — raw PCM audio data

Client → Server (JSON)

TypeDescriptionPayload
joinJoin a meeting session{ meetingId }
textSend a text message{ text }
audio_startBegin audio streaming{}
audio_stopStop audio streaming{}
settingsUpdate bot settings mid-session{ personality?, wake_word_enabled?, ... }
leaveLeave the meeting{}

Example — Join a meeting:

{
"type": "join",
"meetingId": "mtg_def456"
}

Client → Server (Binary)

Stream raw PCM audio from the client microphone:

  • Format: 16-bit signed integer, little-endian
  • Sample rate: 16,000 Hz
  • Channels: Mono (1 channel)
// Capture audio from microphone and send as binary PCM
mediaRecorder.ondataavailable = (event) => {
const pcmData = convertToPCM16(event.data); // Int16Array
ws.send(pcmData.buffer);
};

Server → Client (JSON)

TypeDescriptionPayload
joinedSuccessfully joined session{ sessionId, participants }
participant_eventParticipant joined/left{ participant, action }
transcriptReal-time transcript update{ speaker, text, timestamp, role }
ai_responseAI text response{ text, timestamp }
ai_response_endAI finished responding{}
audio_readyAudio chunk available{ duration }
settings_updatedSettings change confirmed{ settings }
interruptionBarge-in detected — AI stopped{}
task_createdAI extracted a task mid-meeting{ task }
errorError message{ code, message }

Example — Transcript update:

{
"type": "transcript",
"data": {
"speaker": "Sarah Chen",
"text": "I think we should refactor the API layer",
"timestamp": "2026-03-29T10:15:32Z",
"role": "user"
}
}

Example — AI response:

{
"type": "ai_response",
"data": {
"text": "Based on your codebase, refactoring the API layer would improve...",
"timestamp": "2026-03-29T10:15:38Z"
}
}

Server → Client (Binary)

Raw PCM audio from the AI response:

  • Format: 16-bit signed integer, little-endian
  • Sample rate: 24,000 Hz
  • Channels: Mono (1 channel)
ws.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) {
// Binary audio from AI — play through speakers
const pcm = new Int16Array(event.data);
playAudio(pcm, 24000);
} else {
// JSON control message
const msg = JSON.parse(event.data);
handleMessage(msg);
}
};

Connection Lifecycle

1. Client connects with JWT token
2. Client sends { type: "join", meetingId: "..." }
3. Server responds with { type: "joined", ... }
4. Client sends { type: "audio_start" }
5. Client streams binary PCM → Server
6. Server streams transcript + AI response JSON
7. Server streams binary AI audio
8. Meeting ends → connection closes

Barge-In (Interruption)

If a participant starts speaking while the AI is responding:

  1. Server sends { type: "interruption" }
  2. AI audio output stops immediately
  3. Client should clear any queued audio buffers
  4. AI begins listening to the new speaker

Error Handling

{
"type": "error",
"data": {
"code": "SESSION_NOT_FOUND",
"message": "Meeting session not found or has ended"
}
}

Common error codes:

CodeDescription
SESSION_NOT_FOUNDMeeting session doesn't exist
UNAUTHORIZEDInvalid or expired token
ALREADY_JOINEDClient already in a session
RATE_LIMITEDToo many messages