Stream one live conversation's transcript
A server-sent events stream of what is being said on one conversation that is live right now, pushed turn by turn. Works for either channel: a voice call streams as it is spoken, a chat as messages are sent. The connection stays open until you close it or the conversation is over.
The first seed event carries everything said so far, so a client that only opens the stream needs no separate read. Each later append event carries only the turns added since the previous event — append them, do not replace what you have. A further seed may arrive in place of an append, and REPLACES what you have: a long chat's stored history is trimmed from the front, so the conversation can lose its head as well as gain a tail. A final ended event says the conversation is over; nothing follows it and the connection then closes. A chat ends when the agent finishes it, when it reaches its message limit, or when it passes 24 hours without a message and so can no longer be continued. Going idle is NOT ending — an idle chat's stream simply stays open and quiet, because the visitor may still reply. Comment lines (: keep-alive) arrive periodically and carry no data; ignore them.
A coaching event carries a supervisor's coaching note on the conversation: id, at, text, author, about when the note is about an earlier message (see CoachingNoteAbout), and appliedTurn once the agent has taken it into a turn. Every note already written arrives right after the seed, and a note arrives again when appliedTurn is set; keep the latest per id.
A held_reply event carries a chat reply the agent has written but the visitor has not yet seen, held for review because the conversation carries an alert: id, text, deadline, and status, which is pending until a supervisor sends it (approved), sends an edit (edited, with editedText), or the deadline passes and it sends itself as written (expired). A pending reply arrives right after the seed, and again each time its status or deadline changes; keep the latest. Ignore any event name you do not recognise: more may be added.
Once a supervisor has taken a call over, the transcript goes on with what the caller and the supervisor say, transcribed apart. A phase event says so, once: phase is supervised, with since and by (userId and name, which is null when it could not be resolved). A supervised_seed event then carries every line said since, and each supervised_append the lines added after it. A line carries id, speaker (caller or supervisor), text, at, and, on a supervisor's line, their userId and name. These lines are never turns: the agent has left the call, and they come after its last one. The stream ends when the supervisor's call does. A stream opened after the take-over still starts with the agent's part as its seed.
A presence event, sent only when presence is tile or view, says what this supervisor may do on the conversation and who else has it: you is monitor when they are the one monitoring it, and viewer otherwise, in which case they may read it but not act on it. That includes when nobody monitors it, until they claim it. presence carries the monitor, if any, and the viewers, as the conversation's presence does on the live conversations collection. It is sent when the stream opens and again whenever either changes. The transcript after a take-over is being rolled out, so an organization may not see it yet.
A tool call is a turn of its own with role tool, carrying a tool object (see ToolCall). truncated becomes true once the conversation has passed the retained-transcript size limit, after which no further turns are added.
The conversation id is a query parameter rather than a path segment, and this endpoint is read with fetch and a streaming response body rather than EventSource, which cannot send an Authorization header.
Each event's data is JSON in which < and > are written as the escapes \u003c and \u003e. JSON.parse restores both characters, so parse the payload rather than matching against its raw text.
Authorization
bearerAuth A Tandem bearer token. Requests are scoped to the organization the token belongs to; no organization header is required.
In: header
Query Parameters
The conversationId of a conversation that is live right now, as returned by the live conversations collection.
tile when this stream backs a transcript the supervisor has open: it monitors the conversation if nobody else does, and views it otherwise, for as long as the stream is open. view views it and never claims it, for a viewer reconnecting. Omitted or none, the stream reads the transcript and claims nothing.
Value in
- "tile"
- "view"
- "none"
Response Body
text/event-stream
application/json
curl -X GET "https://example.com/v1/agent-media/live-conversations/transcript-stream?conversationId=string""event: seed\ndata: {\"turns\":[{\"role\":\"user\",\"text\":\"I need my balance\",\"at\":\"2026-08-21T10:00:00.000Z\"}],\"truncated\":false}\n\nevent: append\ndata: {\"turns\":[{\"role\":\"assistant\",\"text\":\"One moment while I look that up.\"}],\"truncated\":false}\n\n: keep-alive\n\nevent: ended\ndata: {}\n"{ "error": "string", "message": "string", "limit": 0, "length": 0, "reason": "string"}