Skip to navigation

SSE for Live Transcripts

Real-time user and agent speech events for an active call over Server-Sent Events.

View as Markdown

Real-time streaming of user speech (STT) and agent speech (TTS) events for an active call via Server-Sent Events.

Endpoint

GET /api/v1/events?callId={callId}

DetailValue
ProtocolServer-Sent Events (SSE)
AuthenticationCookie-based (logged-in dashboard user)
AuthorizationUser must belong to the org that owns the agent
Content-Typetext/event-stream

Query Parameters

ParameterTypeRequiredDescription
callIdstringYesThe call ID to subscribe events for

Errors

StatusCondition
400Missing or invalid callId
400Call is already completed
404Not authorized / org mismatch
404Call log or agent not found

All events are sent as data: <JSON>\n\n. The three transcript-relevant event types are:

1. user_interim_transcription

Fired as the user is speaking. Contains partial, in-progress transcription text. These events are emitted frequently and may change as more audio is processed.

{
"event_type": "user_interim_transcription",
"event_id": "evt_abc123",
"timestamp": "2026-03-02T10:00:01.123Z",
"call_id": "CALL-1758124225863-80752e",
"interim_transcription_text": "I wanted to ask about my"
}

2. user_transcription

Fired when the user finishes a speech segment. Contains the final transcription for that turn.

{
"event_type": "user_transcription",
"event_id": "evt_abc456",
"timestamp": "2026-03-02T10:00:02.456Z",
"call_id": "CALL-1758124225863-80752e",
"user_transcription_text": "I wanted to ask about my recent order"
}

3. tts_completed

Fired when the agent finishes speaking a TTS segment. Contains the text that was spoken and optionally the TTS latency.

{
"event_type": "tts_completed",
"event_id": "evt_abc789",
"timestamp": "2026-03-02T10:00:03.789Z",
"call_id": "CALL-1758124225863-80752e",
"tts_latency": 245,
"tts_text": "Sure, I can help you with your recent order. Could you provide your order number?"
}

Lifecycle Events

sse_init

Sent immediately when the SSE connection is established.

{
"event_type": "sse_init",
"event_time": "2026-03-02T10:00:00.000Z"
}

sse_close

Sent when the call ends, right before the server closes the connection.

{
"event_type": "sse_close",
"event_time": "2026-03-02T10:05:00.000Z"
}

Usage Examples

cURL

curl -N 'https://api.smallest.ai/atoms/v1/events?callId=CALL-1758124225863-80752e' \
-H 'Cookie: your_session_cookie' \
-H 'Accept: text/event-stream'

JavaScript (Browser)

const callId = "CALL-1758124225863-80752e";
const evtSource = new EventSource(
`/api/v1/events?callId=${callId}`,
{ withCredentials: true }
);
evtSource.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.event_type) {
case "user_interim_transcription":
// Update live transcription preview (partial, will change)
console.log("[STT interim]", data.interim_transcription_text);
break;
case "user_transcription":
// Final user speech for this turn
console.log("[STT final]", data.user_transcription_text);
break;
case "tts_completed":
// Agent finished speaking this segment
console.log("[TTS]", data.tts_text);
break;
case "sse_close":
// Call ended, clean up
evtSource.close();
break;
}
};
evtSource.onerror = (err) => {
console.error("SSE connection error:", err);
evtSource.close();
};

Node.js

import EventSource from "eventsource";
const BASE_URL = "https://api.smallest.ai/atoms/v1";
const callId = "CALL-1758124225863-80752e";
const es = new EventSource(
`${BASE_URL}/events?callId=${callId}`,
{ headers: { Cookie: "your_session_cookie" } }
);
es.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.event_type === "user_transcription") {
console.log(`User said: ${data.user_transcription_text}`);
}
if (data.event_type === "tts_completed") {
console.log(`Agent said: ${data.tts_text}`);
}
if (data.event_type === "sse_close") {
es.close();
}
};

Python

import json
import requests
url = "https://api.smallest.ai/atoms/v1/events"
params = {"callId": "CALL-1758124225863-80752e"}
headers = {
"Cookie": "your_session_cookie",
"Accept": "text/event-stream",
}
with requests.get(url, params=params, headers=headers, stream=True) as resp:
for line in resp.iter_lines(decode_unicode=True):
if not line or not line.startswith("data: "):
continue
data = json.loads(line[len("data: "):])
if data["event_type"] == "user_interim_transcription":
print(f"[STT interim] {data['interim_transcription_text']}")
elif data["event_type"] == "user_transcription":
print(f"[STT final] {data['user_transcription_text']}")
elif data["event_type"] == "tts_completed":
print(f"[TTS] {data['tts_text']}")
elif data["event_type"] == "sse_close":
print("Call ended.")
break

Notes

  • The connection is real-time - events stream directly from the call runtime as they are produced.
  • Interim transcriptions are partial and will be superseded by the final user_transcription event. Use them for live preview UI only.
  • The SSE connection auto-closes when the call ends (sse_close event). The server will also terminate the connection.
  • Only active calls can be subscribed to. Completed calls return a 400 error.
  • Other event types (e.g. call_start, call_end, turn_latency, metrics) are also sent on this stream but are not covered in this doc.