Reference
WebSocket events
Every socket and every frame, with its fields and an example.
accountEvents /v1/events
The owner's dashboard: `events.ready` once the socket is listening, then `lists.changed` whenever a list of transcriptions or broadcasts of any principal the caller may act for is out of date — a recording changed state, a transcription settled, a title was written, or the owner changed something from another device. It says that, not what: re-read `GET /v1/transcriptions` and `GET /v1/broadcasts`. It replaces polling those lists. A user may hold a few of these at once (5 by default): opening one more closes their oldest with code 4001. One is closed with code 4002 after a day. After either, do not reconnect at once — a client that does takes its place straight back; reconnect when the user next uses that screen.
events.readylists.changed
broadcastEvents /v1/broadcasts/{id}/events
What a screen waiting on a broadcast needs: when a recording starts in it (`recording.started`: it is live), when that recording ends (`recording.ended`), a file job's progress (`job.progress`), and a pulled stream's state (`stream.ingest`). Each frame's `transcriptionId` is the transcription the recording is made in: on a broadcast's socket, the live transcription feeding it.
recording.startedrecording.endedjob.progressstream.ingest
realtimeSession /v1/realtime/sessions/{token}/socket
Connect to the `streamUrl` a realtime session returned (treat it as opaque).
session.loadingA heartbeat while the machine gets ready (`stage`: `download`, thensession.readyThe realtime session is ready: send audio from now on.transcript.committedOne final segment, with word timings, numbered by `seq` (0, 1, 2…,transcript.draftThe live tail: the words heard since the last commit, stilltranscript.wordsWord timings for the live tail as they firm up (`events.words`);transcript.amendedAn already-delivered committed segment was rewritten by the enginetranscript.latencyA delivered segment's latency, measured again now that the engine'stranscript.speakerA tentative speaker label on a delivered segment was settled:transcript.speakerGenderA speaker's gender, as the pitch band heard it, once it settlestranscript.speakerIdentifiedA diarized speaker turned out to be somebody the caller has atranscript.sentenceFull-replacement upsert of one sentence, keyed by `sentenceId`.transcript.translatedtranscript.voiceA spoken rendering of one definitive sentence (`SessionOptions::voice`).transcript.voiceStatusWhy a listener who picked a voice is not hearing it yet — or willtranscript.progressstream.pull`input.kind = "stream"`: how the engine's pull of the stream issource.progress`input.prepare`: the source on its way in. `phase` "fetching"source.prepared`input.prepare`: the source is stored and ready to transcribe.session.doneerror
subscribe /v1/recordings/{id}/subscribe
Follow a recording: first frame `subscribe.ready {lastSeq}`, then `GET /v1/recordings/{id}/transcript` and discard buffered frames with `seq <= lastSeq`. `voice` picks which voice speaks the language for this listener; two listeners on the same (lang, voice) share one synthesis, so changing voice means reopening the socket. Send `{"type":"subscribe.update","lang":"ja"}` to switch language, `{"type":"subscribe.update","audio":true}` to receive live Opus.
session.loadingA heartbeat while the machine gets ready (`stage`: `download`, thensession.readyThe realtime session is ready: send audio from now on.transcript.committedOne final segment, with word timings, numbered by `seq` (0, 1, 2…,transcript.draftThe live tail: the words heard since the last commit, stilltranscript.wordsWord timings for the live tail as they firm up (`events.words`);transcript.amendedAn already-delivered committed segment was rewritten by the enginetranscript.latencyA delivered segment's latency, measured again now that the engine'stranscript.speakerA tentative speaker label on a delivered segment was settled:transcript.speakerGenderA speaker's gender, as the pitch band heard it, once it settlestranscript.speakerIdentifiedA diarized speaker turned out to be somebody the caller has atranscript.sentenceFull-replacement upsert of one sentence, keyed by `sentenceId`.transcript.translatedtranscript.voiceA spoken rendering of one definitive sentence (`SessionOptions::voice`).transcript.voiceStatusWhy a listener who picked a voice is not hearing it yet — or willtranscript.progressstream.pull`input.kind = "stream"`: how the engine's pull of the stream issource.progress`input.prepare`: the source on its way in. `phase` "fetching"source.prepared`input.prepare`: the source is stored and ready to transcribe.session.doneerrorsubscribe.readyFirst frame after the upgrade: where the live sequence stands, sorecording.stateRecording state changed (LIVE ⇄ PAUSED → ENDED → FINALIZED).recording.settingsCapture settings changed mid-recording (mode, language, labels).recording.silenceThe silence watchdog will pause the recording soon.recording.expiringThe max-duration cutoff is near.transcript.correctedA human correction was applied — distinct from an engine amend.transcript.speakerGenderA speaker's gender, once the pitch band settles on ittranscript.speakerIdentifiedA speaker and the saved voice they turn out to be.transcript.speakerNamedA per-recording speaker label.recording.startedBroadcast or transcription topic: a recording started in it (it isjob.progressA file / URL transcription job moved (both topics: the recording'sstream.ingestA stream source's server-side publisher moved (both topics): whatrecording.endedBroadcast or transcription topic: the recording that was live in itaudienceAdmin subscribers: the audience aggregate, every few seconds.subscribe.gapThe frame sequence jumped; the client should re-snapshot from its cursor.
transcriptionEvents /v1/transcriptions/{id}/events
What a screen waiting on a transcription needs: when a recording starts in it (`recording.started`: it is live), when that recording ends (`recording.ended`), a file job's progress (`job.progress`), and a pulled stream's state (`stream.ingest`). Each frame's `transcriptionId` is the transcription the recording is made in.
recording.startedrecording.endedjob.progressstream.ingest