Realtime API reference

This endpoint is a long-lived WebSocket connection. The gateway relays the Bailian Qwen-Omni-Realtime protocol verbatim in both directions with no protocol translation; the full field definitions and the tool-calling (Function Calling / MCP) events follow Bailian's official client events and server events. This page covers the handshake, auth, event list, and audio conventions needed to integrate.

Request

ItemValue
MethodGET (WebSocket upgrade)
Path/api-ws/v1/realtime
Full URL{{ ws_endpoint }}/api-ws/v1/realtime?model=<logical model>
Querymodel (required) — the platform logical model, not the upstream model
HeaderAuthorization: Bearer <mgk_ API Key> (required)
HeaderX-Request-ID (optional) — propagated to the call log; the request_id starts with gw_rt_

Only a logical model whose public_protocols includes dashscope_realtime can use this surface.

Handshake errors

Failures before the WebSocket upgrade are returned as HTTP status codes with a body of:

json
{"error":{"type":"invalid_request_error","code":"unauthorized","message":"unauthorized: api_key_not_found"}}
HTTPcodeTriggerExample message
401unauthenticatedno API keymissing api key
401unauthorizedinvalid / disabled keyunauthorized: api_key_not_found
404model_not_foundmodel not in catalogunknown model: <model>
403model_protocol_not_offeredmodel does not advertise dashscope_realtimemodel <model> is not offered on the realtime protocol
404no_routeno route for the model in the policy (including its fallback chain)no route for model <model>
503no_providera route exists but no provider instance is availableno provider available for <model>
402insufficient_funds / budget_exceededpreauthorization failed (balance / budget)billing: insufficient funds

After a successful upgrade (HTTP 101), later problems are delivered as an in-band error event, then the connection closes:

json
{"type":"error","error":{"type":"upstream_error","code":"provider_unavailable","message":"upstream connection failed"}}

Session configuration session.update

After connecting, the server first sends session.created; the client overrides with session.update, and a valid update is acknowledged with session.updated. Common fields:

FieldValuesDefault
modalities["text","audio"] / ["text"]["text","audio"]
voice / audio.output.voicesee Bailian's voice listTina
turn_detection{"type":"server_vad"} / {"type":"semantic_vad"} / nullserver VAD
audio.input.format{"type":"pcm","sample_rate":16000}pcm / 16000
audio.output.format{"type":"pcm","sample_rate":24000}pcm / 24000
instructionsany textempty
input_audio_transcription{"model":"qwen3-asr-flash-realtime"} / nullenabled

turn_detection: null disables the server VAD so the client commits and triggers responses manually.

Client events

EventPurpose
session.updateUpdate session config (modalities, voice, audio format, VAD, instructions, …)
input_audio_buffer.appendAppend Base64 audio to the input buffer
input_image_buffer.appendAppend a Base64 image (JPG/JPEG; audio must have been sent first)
input_audio_buffer.commitCommit the audio buffer in manual mode (does not trigger a response)
input_audio_buffer.clearClear the audio buffer
conversation.item.createCreate an item: plain text input, function_call_output, mcp_approval_response
response.createTrigger one model response
response.cancelCancel the in-progress response (interruption)

Server events

EventMeaning
session.created / session.updatedSession created / config applied
input_audio_buffer.speech_started / speech_stoppedVAD detected the user starting / stopping (interruption trigger)
input_audio_buffer.committed / clearedAudio buffer committed / cleared
conversation.item.createdAn item was created
conversation.item.input_audio_transcription.delta / .completedInput speech transcription (streaming preview / final)
response.createdA response turn began
response.output_item.added / response.content_part.addedOutput item / content part began
response.text.delta / response.text.doneText-only streaming / full text
response.audio_transcript.delta / .doneTranscript of the audio output
response.audio.delta / response.audio.doneBase64 output audio (24 kHz PCM) / end of audio
response.output_item.done / response.content_part.doneOutput item / content part completed
response.doneResponse turn ended; response.usage carries per-modality token usage

Tool-calling events (response.function_call_arguments.delta / .done) and the MCP events (mcp_*) are documented in Bailian's server-events reference.

Example event order for one voice turn:

text
session.created
session.updated
input_audio_buffer.speech_started
input_audio_buffer.speech_stopped
input_audio_buffer.committed
conversation.item.input_audio_transcription.completed
response.created
response.output_item.added
response.audio_transcript.delta …
response.audio.delta …
response.done

Audio formats

DirectionFormatField
Uplink (input)16000 Hz, 16-bit little-endian, mono PCM, Base64audio of input_audio_buffer.append
Downlink (output)24000 Hz, 16-bit little-endian, mono PCM, Base64delta of response.audio.delta

Send input audio in full 100 ms frames (3200 bytes per frame) for best reliability. input_audio_buffer.append only buffers; whether it is committed is decided by VAD or by a client input_audio_buffer.commit.

VAD and interruption

  • With a non-null turn_detection, the server auto-detects speech boundaries and, after silence_duration_ms of silence (default 800 ms), auto-commits and triggers a response.
  • When the user speaks again: the server emits input_audio_buffer.speech_started → the client stops playback and sends response.cancel → response.done (cancelled) arrives → a new turn begins.
  • turn_detection: null is manual mode: after recording, the client sends input_audio_buffer.commit (wait for input_audio_buffer.committed) then response.create.

Usage and billing

Each turn's response.done.response.usage carries per-modality tokens:

json
{
  "type": "response.done",
  "response": {
    "status": "completed",
    "usage": {
      "total_tokens": 843,
      "input_tokens": 693,
      "output_tokens": 150,
      "input_tokens_details": { "text_tokens": 693 },
      "output_tokens_details": { "text_tokens": 28, "audio_tokens": 122 }
    }
  }
}

The gateway settles the accumulated session usage at close: a session-level estimate is held at connect (currently about ¥1.2; insufficient balance fails the handshake with 402), then refund/top-up applies based on actual usage; a session with no usage releases the hold. See the guide.

Limits

ItemValue
Max single connection30 minutes (gateway-enforced)
Total input tokens196,608
Max output tokens65,536
Upstream rate limit60 RPM

Related