[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"article-doc:docs\u002Fapi-reference\u002F4.server-events":3},"---\ntitle: Server Events\ndescription: All Lanson → client events pushed over WebSocket.\n---\nEvents the server pushes over the WebSocket connection.\n\n## Overview\n\n| type | Source | Description |\n|---|---|---|\n| `session.created` | Gateway | Sent on connection establishment |\n| `session.updated` | Upstream | Confirms session parameter update |\n| `input_audio_buffer.speech_started` | Upstream | Speech segment detected |\n| `input_audio_buffer.speech_stopped` | Upstream | Speech segment ended |\n| `conversation.item.input_audio_transcription.completed` | Upstream | A speech segment has been transcribed (**primary output**) |\n| `lanson.throttled` | Gateway | Throttle notification (max once per second) |\n| `error` | Gateway \u002F upstream | Error event |\n\n## session.created\n\nSent by the gateway immediately after connection.\n\n```json\n{\n  \"type\": \"session.created\",\n  \"request_id\": \"...\",\n  \"session_id\": \"sess_...\",\n  \"audio\": { \"format\": \"pcm_s16le\", \"sample_rate\": 16000, \"channels\": 1 },\n  \"turn_detection\": { \"type\": \"server_vad\" },\n  \"plan\": \"free\",\n  \"limits\": {\n    \"max_concurrent_utterances\": 2,\n    \"max_session_seconds\": 900,\n    \"idle_timeout_seconds\": 60,\n    \"remaining_audio_seconds\": 3600\n  }\n}\n```\n\n| Field | Type | Description |\n|---|---|---|\n| `session_id` | string | Session identifier |\n| `audio.format` | string | Fixed: `pcm_s16le` |\n| `audio.sample_rate` | number | Fixed: 16000 |\n| `audio.channels` | number | Fixed: 1 |\n| `turn_detection.type` | string | Fixed: `server_vad` |\n| `plan` | string | Current plan |\n| `limits.max_concurrent_utterances` | number | Max concurrent utterances |\n| `limits.max_session_seconds` | number | Max session duration (seconds) |\n| `limits.idle_timeout_seconds` | number | Idle timeout (seconds) |\n| `limits.remaining_audio_seconds` | number \\| null | Remaining audio budget (null when unlimited) |\n\n## session.updated\n\nConfirms that a `session.update` message has taken effect.\n\n```json\n{\n  \"type\": \"session.updated\",\n  \"request_id\": \"...\",\n  \"language\": \"zh\",\n  \"turn_detection\": { \"type\": \"server_vad\" }\n}\n```\n\n## input_audio_buffer.speech_started\n\nVAD detected the start of a speech segment.\n\n```json\n{\n  \"type\": \"input_audio_buffer.speech_started\",\n  \"request_id\": \"...\",\n  \"utterance_index\": 0\n}\n```\n\n## input_audio_buffer.speech_stopped\n\nVAD detected the end of a speech segment.\n\n```json\n{\n  \"type\": \"input_audio_buffer.speech_stopped\",\n  \"request_id\": \"...\",\n  \"utterance_index\": 0,\n  \"reason\": \"end_of_speech\",\n  \"audio_duration_ms\": 3200,\n  \"speech_duration_ms\": 2800\n}\n```\n\n| Field | Type | Description |\n|---|---|---|\n| `utterance_index` | number | Speech segment number |\n| `reason` | string | Stop reason |\n| `audio_duration_ms` | number | Total audio duration |\n| `speech_duration_ms` | number? | Actual speech duration |\n| `split_offset_ms` | number? | Split offset |\n| `split_rms` | number? | Split RMS value |\n\n## conversation.item.input_audio_transcription.completed\n\n**Primary output event.** A speech segment has been transcribed.\n\n```json\n{\n  \"type\": \"conversation.item.input_audio_transcription.completed\",\n  \"request_id\": \"...\",\n  \"utterance_index\": 0,\n  \"text\": \"The weather is nice today\",\n  \"language\": \"zh\",\n  \"audio_duration_ms\": 3200,\n  \"latency_ms\": 480,\n  \"segments\": [],\n  \"verbose\": {}\n}\n```\n\n| Field | Type | Description |\n|---|---|---|\n| `utterance_index` | number | Speech segment number |\n| `text` | string | Transcribed text |\n| `language` | string | Detected language |\n| `audio_duration_ms` | number | Audio duration |\n| `latency_ms` | number | Processing latency |\n| `segments` | array | Segment details |\n| `verbose` | object | Upstream additional info |\n\n## lanson.throttled\n\nGateway throttle notification, sent at most once per second.\n\n```json\n{\n  \"type\": \"lanson.throttled\",\n  \"reason\": \"concurrent_utterance_limit\",\n  \"dropped_audio_frames\": 3,\n  \"in_flight_utterances\": 2\n}\n```\n\n| `reason` value | Meaning |\n|---|---|\n| `concurrent_utterance_limit` | Concurrent utterance limit exceeded |\n| `upstream_backpressure` | Upstream backpressure |\n| `upstream_connecting` | Upstream still connecting |\n\n## error\n\nError event. Can be sent at any time during the WebSocket connection.\n\n```json\n{\n  \"type\": \"error\",\n  \"code\": \"audio_frame_too_large\",\n  \"message\": \"Audio frame exceeds maximum size.\",\n  \"request_id\": \"...\"\n}\n```\n\nError codes are listed in [Errors](\u002Fdocs\u002Fapi-reference\u002Ferrors).\n\n## Event ordering\n\n```\nsession.created\n  → [audio frames...]\n  → input_audio_buffer.speech_started\n  → [more audio...]\n  → input_audio_buffer.speech_stopped\n  → conversation.item.input_audio_transcription.completed\n  → [repeat...]\n  → session close\n```\n\n## Related\n\n- [Client Messages](\u002Fdocs\u002Fapi-reference\u002Fclient-messages) — client-sent messages\n- [Errors](\u002Fdocs\u002Fapi-reference\u002Ferrors) — full error reference\n- [Transcript Lifecycle](\u002Fdocs\u002Frealtime\u002Ftranscript-lifecycle) — state transitions\n",1790059118944]