Socket.IO API
Connect securely and complete fast transcription, live ASR, diarization, voice discovery, or TTS over Socket.IO.
Use this guide for the Socket.IO lifecycle: choose a capability, connect, register the minimum events, recognize its final signal, and always disconnect. Use the generated AsyncAPI pages for complete payload schemas.
For JavaScript and Python applications, prefer SDK 0.18.0; it builds binary
frames, routes UUIDs, normalizes errors, and provides close helpers. Build a
direct client only when you need wire-level control.
Choose a workflow
| Input you have | Choose | Completion signal |
|---|---|---|
| A short, complete, latency-sensitive audio unit such as one conversational turn for a voice agent | Fast transcription | transcription_result.is_final === true |
| PCM audio that is still arriving and needs text | Realtime ASR | Wire terminal: is_final === true; speech boundary: is_speech_final === true |
| PCM audio that is still arriving and needs speaker turns | Live diarization | Final input frame, then diarization_result.is_final === true or an app deadline |
| Text that needs generated speech | Voice discovery, then TTS | Final bit in a tts_audio frame |
Fast transcription receives the complete payload once. It isn't the path for long-form meetings, podcasts, or archive media; use batch transcription for those complete recordings.
Connection prerequisites
- The
API_URLandAPI_KEYissued for the environment. Direct Socket.IO clients also set the path to/socket.io. - A server-side Socket.IO client. Keep
API_KEYout of browser and mobile bundles. - Set
transports: ["websocket"]for the published, portable transport contract. Some deployments may route polling, but clients must not depend on it. - Send
x-api-keyandOriginas connection headers. The production edge runs a web app firewall that rejects a handshake withoutOrigin; set it to the scheme and host ofAPI_URL. - Event handlers registered before the connection or before sending a request.
- An overall app deadline for every request or stream.
Direct Socket.IO clients keep the path explicit. SDK 0.18.0 defaults to
/socket.io; pass api_path only when a self-hosted deployment or one behind a proxy
uses an override. The legacy sautech.humain.com endpoint requires
/realtime/socket.io.
Connect once and disconnect
One connection can multiplex multiple requests or streams. Give each one a UUID
and route every response by id before processing it.
import { io } from "socket.io-client";
const socket = io(process.env.API_URL!, {
path: process.env.API_PATH ?? "/socket.io",
transports: ["websocket"],
extraHeaders: {
"x-api-key": process.env.API_KEY!,
Origin: process.env.API_URL!,
},
});
try {
// Register handlers, wait for connect, and run one or more operations.
} finally {
socket.disconnect();
}Expected: the client emits its connection-success callback before any application request is sent. Treat connection failure as terminal for that attempt and clean up before retrying.
In python-socketio, transports is a connect() argument, not an
AsyncClient constructor argument.
Fast transcription of a complete audio unit
Fast transcription accepts one complete AAC, FLAC, MP3, MP4, or WAV payload.
An MP4 must have its moov atom at the front. Send raw binary, not JSON or
base64.
Minimal sequence:
- Register
audio_file_upload_success,transcription_result, anderror. - Emit one
audio_filebinary packet. - Match
audio_file_upload_success.idto the request UUID; this acknowledges receipt, not transcription completion. - Route result events by
id, and treat theirseqas opaque because the public Fast contract does not define ordering or aggregation semantics. Finish only whenis_finalis true. - Keep or reuse the connection only under an app deadline; otherwise disconnect.
The audio_file packet has this exact variable-length layout:
| Offset | Size | Field |
|---|---|---|
0..15 | 16 bytes | Request UUID |
16 | 1 byte | Language: 0 Arabic, 1 English, 2 codeswitch, 255 auto |
17..18 | 2 bytes | asr_model_key byte length, unsigned 16-bit little-endian |
next N | N bytes | UTF-8 asr_model_key; zero length selects the language default |
| next 2 | 2 bytes | dia_model_key byte length, unsigned 16-bit little-endian |
next N | N bytes | Reserved dia_model_key; send zero length |
next 2 + N | variable | Reserved itn_model_key; send zero length |
next 2 + N | variable | Reserved redact_model_key; send zero length |
| remaining | variable | Complete encoded audio-file bytes |
SDK 0.18.0 serializes the three reserved compatibility fields, but the
validated public Fast service does not apply them. Use Batch when diarization,
ITN, or redaction is required.
JavaScript SDK 0.18.0 has no fast-transcription timeout option. A routed
request error calls onError and then rejects with a generic message-only
Error. Don't blindly resend an ambiguous upload; there is no published
idempotency-key contract.
Realtime ASR framing and lifecycle
audio_stream carries PCM16 little-endian, 16 kHz, mono samples. Reuse one UUID
for the whole stream.
Minimal sequence:
- Register
transcription_result, optionaldiarization_result, anderror. - Emit exactly one start frame with flags byte
1. - Emit intermediate frames with flags byte
0. - Emit exactly one final frame with flags byte
2. - Route text by
idand observed arrival order. Keep serverseqfor diagnostics only because its ordering and uniqueness are not public guarantees. Replace provisional text while both final flags are false; commit the event's words once whenis_finaloris_speech_finalis true. - After the final input, a direct client waits for
is_final: trueuntil the app deadline. The released SDKclose()helper waits for the same protocol-levelis_final, a routed error, or its bounded timeout.is_speech_finaldoes not release that wait. Inspect the response state; a successful return can be a timeout and does not itself prove finality.
The tested SDK recipe sends 3,200 audio bytes, or 100 ms, per frame. This is a
practical cadence, not a throughput or latency guarantee. Set flags byte bit 2
only when you also want diarization_result events on the same connection.
Live diarization framing and lifecycle
diarization_stream uses the same 18-byte frame layout and required PCM format
as audio_stream. Its flags use bit 0 for start and bit 1 for final; keep other
bits zero.
Minimal sequence:
- Register
diarization_resultanderror. - Send one start frame, intermediate frames, and one final frame under the same UUID.
- Accumulate unseen
final_segmentsadditions and replace the currentactive_segmentstail on every result. - Treat
is_final: trueas the final server signal. If the deadline expires first, return the best-known reconciled timeline as incomplete. - Disconnect in cleanup.
The released SDK helper recommends 15,360 audio bytes per feed. Consume results
while sending; deferring consumption until after the feed can stall the
workflow. SDK close(5) returns the best-known timeline when its final wait
expires.
Voice discovery and TTS lifecycle
Discover a voice instead of guessing an ID:
- Register
tts_voice_list_resultanderror. - Emit
tts_voice_listwith{}. - Treat the response as an array of
{ id, label }; handle an empty array.
Then synthesize:
- Register
tts_audioanderror. - Emit
ttswithid,textcontaining a Unicode letter or number after trimming, and explicitmodel: "nebula". - For predictable voice selection, send either
voice_idfrom discovery or onevoice_referencesitem shaped{ audio, text }. Itsaudiois standard-base64 RIFF/WAVE with non-empty mono PCM16 data. The selectors are mutually exclusive. - Match every binary response by the request UUID, append bytes
17..end, and stop when byte16bit 0 is set.
The final bit is the TTS completion signal. Parse every tts_audio event with
this application header and never append its first 17 bytes. Use the
tested TTS-to-WAV recipe to create a
playable file. Disconnecting cancels the active synthesis requests owned by
that connection and suppresses their later audio and error events; it does not
close inference connections shared with other requests.
Structured errors, deadlines, and termination
The generated event contracts define error objects with required code,
message, retryable, and timestamp, plus request id when the payload can
be routed. Register both request-scoped and global error handling.
| Capability | Final signal | Deadline and cleanup rule |
|---|---|---|
| Fast transcription | is_final: true | No JavaScript SDK timeout; bound the whole request and close the client |
| Realtime ASR | Wire terminal and SDK close signal: is_final: true | A resolved SDK close can mean its timeout expired; inspect tracked finality and always disconnect in finally |
| Live diarization | Final input frame, then is_final: true | On close timeout, keep the best-known timeline and mark it incomplete |
| Voice discovery | One tts_voice_list_result, which can be empty | Bound the wait; don't invent a voice ID |
| TTS | tts_audio header bit 0 set | SDK timeouts are client controls; the server also enforces a non-resetting 25-second overall deadline and a 60-second inactivity watchdog. Disconnect cancels this connection's active requests. |
SDK 0.18.0 normalizes structured callbacks. A legacy non-object payload becomes
{ message }. Fast and TTS request promises reject with generic message-only
errors after their structured callbacks. A timeout doesn't prove finality: stop
sending, preserve confirmed results, record incomplete termination, and
disconnect.
Use retryable as one input to a bounded retry policy, not as permission for an
unlimited retry. Never replay an upload whose outcome is ambiguous without an
application duplication policy.
Generated event reference
This guide intentionally stops at lifecycle and framing. The generated AsyncAPI pages contain every field, required property, example, and schema constraint.
Fast transcription events
Inspect the complete audio packet and upload, result, and error schemas.
Realtime events
Inspect ASR, diarization, speaker, framing, and result schemas.
TTS events
Inspect voice discovery, synthesis, audio, and error schemas.
Released SDK
Use tested clients, routing, subtitles, deadlines, and cleanup helpers.