API Guides

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 haveChooseCompletion signal
A short, complete, latency-sensitive audio unit such as one conversational turn for a voice agentFast transcriptiontranscription_result.is_final === true
PCM audio that is still arriving and needs textRealtime ASRWire terminal: is_final === true; speech boundary: is_speech_final === true
PCM audio that is still arriving and needs speaker turnsLive diarizationFinal input frame, then diarization_result.is_final === true or an app deadline
Text that needs generated speechVoice discovery, then TTSFinal 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_URL and API_KEY issued for the environment. Direct Socket.IO clients also set the path to /socket.io.
  • A server-side Socket.IO client. Keep API_KEY out 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-key and Origin as connection headers. The production edge runs a web app firewall that rejects a handshake without Origin; set it to the scheme and host of API_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:

  1. Register audio_file_upload_success, transcription_result, and error.
  2. Emit one audio_file binary packet.
  3. Match audio_file_upload_success.id to the request UUID; this acknowledges receipt, not transcription completion.
  4. Route result events by id, and treat their seq as opaque because the public Fast contract does not define ordering or aggregation semantics. Finish only when is_final is true.
  5. Keep or reuse the connection only under an app deadline; otherwise disconnect.

The audio_file packet has this exact variable-length layout:

OffsetSizeField
0..1516 bytesRequest UUID
161 byteLanguage: 0 Arabic, 1 English, 2 codeswitch, 255 auto
17..182 bytesasr_model_key byte length, unsigned 16-bit little-endian
next NN bytesUTF-8 asr_model_key; zero length selects the language default
next 22 bytesdia_model_key byte length, unsigned 16-bit little-endian
next NN bytesReserved dia_model_key; send zero length
next 2 + NvariableReserved itn_model_key; send zero length
next 2 + NvariableReserved redact_model_key; send zero length
remainingvariableComplete 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.

Live ASR input frame
UUID
bytes 0..15
Reuse for every frame in this stream.
Flags
byte 16
bit 0 start, bit 1 final, bit 2 diarization tee; bits 3..7 zero.
Language
byte 17
0 ar, 1 en, 2 codeswitch, 255 auto.
PCM
bytes 18..end
PCM16 LE, 16 kHz, mono.

Minimal sequence:

  1. Register transcription_result, optional diarization_result, and error.
  2. Emit exactly one start frame with flags byte 1.
  3. Emit intermediate frames with flags byte 0.
  4. Emit exactly one final frame with flags byte 2.
  5. Route text by id and observed arrival order. Keep server seq for 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 when is_final or is_speech_final is true.
  6. After the final input, a direct client waits for is_final: true until the app deadline. The released SDK close() helper waits for the same protocol-level is_final, a routed error, or its bounded timeout. is_speech_final does 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:

  1. Register diarization_result and error.
  2. Send one start frame, intermediate frames, and one final frame under the same UUID.
  3. Accumulate unseen final_segments additions and replace the current active_segments tail on every result.
  4. Treat is_final: true as the final server signal. If the deadline expires first, return the best-known reconciled timeline as incomplete.
  5. 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:

  1. Register tts_voice_list_result and error.
  2. Emit tts_voice_list with {}.
  3. Treat the response as an array of { id, label }; handle an empty array.

Then synthesize:

  1. Register tts_audio and error.
  2. Emit tts with id, text containing a Unicode letter or number after trimming, and explicit model: "nebula".
  3. For predictable voice selection, send either voice_id from discovery or one voice_references item shaped { audio, text }. Its audio is standard-base64 RIFF/WAVE with non-empty mono PCM16 data. The selectors are mutually exclusive.
  4. Match every binary response by the request UUID, append bytes 17..end, and stop when byte 16 bit 0 is set.
TTS output frame
UUID
bytes 0..15
Matches the TTS request id.
Header
byte 16
bit 0 end of stream; bits 1..7 zero.
PCM
bytes 17..end
PCM16 LE, 24 kHz, mono; no WAV header.

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.

CapabilityFinal signalDeadline and cleanup rule
Fast transcriptionis_final: trueNo JavaScript SDK timeout; bound the whole request and close the client
Realtime ASRWire terminal and SDK close signal: is_final: trueA resolved SDK close can mean its timeout expired; inspect tracked finality and always disconnect in finally
Live diarizationFinal input frame, then is_final: trueOn close timeout, keep the best-known timeline and mark it incomplete
Voice discoveryOne tts_voice_list_result, which can be emptyBound the wait; don't invent a voice ID
TTStts_audio header bit 0 setSDK 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.

On this page