Message reference¶
Client → server¶
start¶
Sent once, straight after the socket opens and before any audio. On reconnect, send it again with encounter_id set.
{
"object": "start",
"prompt_id": "33907f11-7792-4b63-be9b-d0a3b6dc074c",
"consultation_name": "Follow-up: hypertension",
"show_transcript": true,
"encounter_id": null,
"ext_patient_id": "MRN-884213",
"visit_id": "VISIT-2211045",
"ext_user_id": "DR-10293"
}
| Field | Type | Required | Description |
|---|---|---|---|
object |
string | Yes | "start" |
prompt_id |
string (UUID) | Yes | Note template. Issued by Sahl AI for your organization. |
consultation_name |
string | Recommended | Human-readable label for the encounter. |
show_transcript |
boolean | Optional | Send live transcript_item messages. Default false. Requires the transcript feature on your account. |
encounter_id |
string | null | On reconnect | null for a new consultation. On reconnect, send the encounter_id you received to resume it instead of creating a duplicate. |
ext_patient_id |
string | Recommended | Your patient identifier (MRN). |
visit_id |
string | Recommended | Your encounter or visit identifier. |
ext_user_id |
string | Optional | Your clinician identifier. |
audio_chunk¶
| Field | Type | Description |
|---|---|---|
payload |
string | Base64 PCM-16, 16 kHz mono. See Audio format. |
seq_id |
integer | Starts at 1 and increases by one per chunk. Never reset it, not even across reconnects within the same consultation. |
pause¶
Stop sending audio after this, but keep the socket open and keep sending ping. To resume, send audio_chunk messages again, continuing the same seq_id sequence. There is no resume message. Do not send start again on the same socket.
end_transcript¶
Sent once, after the final audio chunk, with the next seq_id. The server finishes transcribing, acknowledges outstanding chunks, generates the note and sends task_status. Keep the socket open until task_status arrives. Closing early abandons delivery of the note.
ping¶
Send every 30 seconds for the whole life of the socket, including while paused and while you wait for the note. Idle connections are dropped after 100 seconds, and note generation can take longer than that.
Server → client¶
encounter_created¶
Sent once, shortly after start. Store it. It identifies the consultation and is required to resume after a reconnect.
ack¶
Confirms the server received the chunk with that seq_id. Remove it from your resend buffer. Acks can arrive out of order relative to transcripts.
transcript_item¶
{
"object": "transcript_item",
"id": "c1d6b1e4-…",
"text": "Have you had any chest pain since we last spoke?",
"start_offset_ms": 12400,
"end_offset_ms": 15980,
"timestamp": "2026-11-01T09:14:32.104Z"
}
One message per finalised speech segment, sent only when show_transcript is true. Offsets are milliseconds from the start of the consultation, and they continue across resumes.
task_status¶
The final message. The server closes the socket after sending it.
{
"object": "task_status",
"status": "SUCCESS",
"summary": [
{ "title": "Chief Complaint", "body": ["Intermittent chest tightness for two weeks."], "edited_body": null, "show": true },
{ "title": "Assessment and Plan", "body": ["Stable angina suspected; ECG and troponin ordered."], "edited_body": null, "show": true }
],
"errorMsg": ""
}
| Field | Type | Description |
|---|---|---|
status |
"SUCCESS" | "FAILED" |
Outcome. |
summary |
array | Ordered note sections (title, body[], edited_body, show). Your prompt_id defines the sections. Empty on failure. |
errorMsg |
string | Reason for the failure. Empty on success. |
On failure the transcript is still saved against the encounter_id. Contact Sahl AI support if the note needs to be regenerated.
warning_message¶
Not fatal. Keep streaming. You can show it to the clinician, for example as a microphone check.
| Code | Meaning |
|---|---|
1007 |
A segment contained no speech. Check that the microphone is not muted. |
INVALID_NOTE_CONFIG |
An optional note configuration in start was invalid and has been ignored. |
error¶
| Code | Meaning |
|---|---|
INVALID_MESSAGE |
The frame was not valid JSON or had no object field. |
UNKNOWN_MESSAGE_TYPE |
The object value is not recognised. |
PROCESSING_ERROR |
The server could not process the message. Report the encounter_id to support. |
TRANSCRIPTIONS_ERROR |
Transcription failed while finishing the consultation. |
pong¶
Reply to ping. Use it only to reset your liveness timer.