asyncapi: '2.6.0' id: 'urn:com:cartesia:api:v1:websocket' info: title: Cartesia Realtime WebSocket API (TTS + STT) version: '2026-03-01' description: | AsyncAPI 2.6 description of Cartesia's **documented public WebSocket API**. Unlike most providers in this catalog, Cartesia publishes a real, bidirectional WebSocket protocol - not Server-Sent Events - for its two core realtime audio surfaces: - **Text-to-Speech WebSocket** at `wss://api.cartesia.ai/tts/websocket` (https://docs.cartesia.ai/api-reference/tts/websocket): a multiplexed, bidirectional connection where clients send generation requests keyed by a `context_id` and receive base64-encoded audio chunks, word/phoneme timestamps, flush acknowledgements, and completion/error messages. A single connection scales to dozens of concurrent generation contexts. - **Speech-to-Text WebSocket** at `wss://api.cartesia.ai/stt/websocket` (https://docs.cartesia.ai/api-reference/stt/websocket): clients stream raw binary audio and receive incremental and final transcript messages. A companion "Auto" variant at `/stt/turns/websocket` (https://docs.cartesia.ai/api-reference/stt/turns/websocket) adds built-in turn detection so the server itself decides when an utterance ends, instead of the client issuing manual `finalize` commands. Both protocols authenticate with either an `X-API-Key` header or an `access_token` query parameter (for browser clients that cannot set custom headers), plus a `cartesia_version` query parameter. REST equivalents (single-shot bytes and Server-Sent Events) for both TTS and STT are modeled separately in the companion OpenAPI document at `openapi/cartesia-ai-openapi.yml`; SSE there is one-way HTTP streaming and is not part of this WebSocket document. contact: name: API Evangelist email: kin@apievangelist.com url: https://apievangelist.com license: name: API documentation - Cartesia Terms of Service url: https://cartesia.ai/terms-of-service x-transport-notes: transport: WebSocket protocol: wss direction: bidirectional confirmed: true source: - https://docs.cartesia.ai/api-reference/tts/websocket - https://docs.cartesia.ai/api-reference/stt/websocket - https://docs.cartesia.ai/api-reference/stt/turns/websocket defaultContentType: application/json servers: ttsWebsocket: url: 'api.cartesia.ai/tts/websocket?cartesia_version=2026-03-01' protocol: wss description: | Bidirectional TTS streaming connection. Authenticate with an `X-API-Key` header or an `access_token` query parameter. security: - apiKeyHeader: [] - accessTokenQuery: [] sttWebsocket: url: 'api.cartesia.ai/stt/websocket?model=ink-whisper&encoding=pcm_s16le&sample_rate=16000&cartesia_version=2026-03-01' protocol: wss description: | Realtime, manual-finalization speech-to-text connection. Query params `model`, `encoding`, `sample_rate`, and `cartesia_version` are required. An "Auto" variant with built-in turn detection is available at the same host under `/stt/turns/websocket`. security: - apiKeyHeader: [] - accessTokenQuery: [] channels: /tts/websocket: servers: - ttsWebsocket description: | Multiplexed realtime TTS generation. The client opens one WebSocket and may run many concurrent generations, each identified by a unique `context_id`. Sending additional messages with `continue: true` on the same `context_id` extends that context's generation while preserving prosody. A `cancel: true` message stops a context's generation early. bindings: ws: bindingVersion: '0.1.0' publish: operationId: sendTtsGenerationRequest summary: Send a TTS generation (or cancel) request. description: | JSON text message. A generation request must include `model_id`, `transcript`, `voice`, `output_format`, and `context_id`. A cancel request includes only `context_id` and `cancel: true`. message: oneOf: - $ref: '#/components/messages/TtsGenerationRequest' - $ref: '#/components/messages/TtsCancelRequest' subscribe: operationId: receiveTtsStreamEvents summary: Receive audio chunks, timestamps, and control messages for a context. description: | Every server message carries the `context_id` it corresponds to, so clients can demultiplex responses across concurrently running generations on the same connection. message: oneOf: - $ref: '#/components/messages/TtsAudioChunk' - $ref: '#/components/messages/TtsWordTimestamps' - $ref: '#/components/messages/TtsPhonemeTimestamps' - $ref: '#/components/messages/TtsFlushDone' - $ref: '#/components/messages/TtsDone' - $ref: '#/components/messages/TtsError' /stt/websocket: servers: - sttWebsocket description: | Realtime speech-to-text without automatic turn detection. The client streams binary audio frames (100ms chunks recommended) and sends text commands (`finalize`, `close`) to control finalization; the server returns incremental and final transcript messages. The connection-level query parameters `model`, `encoding`, and `sample_rate` are required and cannot be changed mid-connection. The `/stt/turns/websocket` variant (not separately channeled here) accepts the same audio and message shapes but adds server-driven turn detection so `finalize` is optional. bindings: ws: bindingVersion: '0.1.0' publish: operationId: sendSttAudioAndCommands summary: Stream binary audio frames and send finalize/close commands. message: oneOf: - $ref: '#/components/messages/SttAudioFrame' - $ref: '#/components/messages/SttFinalizeCommand' - $ref: '#/components/messages/SttCloseCommand' subscribe: operationId: receiveSttTranscripts summary: Receive incremental/final transcripts and control messages. message: oneOf: - $ref: '#/components/messages/SttTranscript' - $ref: '#/components/messages/SttFlushDone' - $ref: '#/components/messages/SttDone' - $ref: '#/components/messages/SttError' components: securitySchemes: apiKeyHeader: type: httpApiKey name: X-API-Key in: header description: Standard Cartesia API key (sk_car_...), sent as a header when opening the WebSocket connection. accessTokenQuery: type: userPassword description: | Short-lived access token (minted via POST /access-token) passed as the `access_token` query parameter, for browser clients that cannot set custom headers on a WebSocket handshake. messages: TtsGenerationRequest: name: TtsGenerationRequest title: TTS generation request contentType: application/json payload: $ref: '#/components/schemas/TtsGenerationRequestPayload' examples: - name: basicGeneration payload: model_id: sonic-3.5 transcript: 'Hello, world!' voice: mode: id id: a0e99841-438c-4a64-b679-ae501e7d6091 output_format: container: raw encoding: pcm_s16le sample_rate: 16000 context_id: unique-context-identifier language: en continue: false max_buffer_delay_ms: 3000 add_timestamps: false add_phoneme_timestamps: false TtsCancelRequest: name: TtsCancelRequest title: TTS cancel request contentType: application/json payload: $ref: '#/components/schemas/TtsCancelRequestPayload' examples: - name: cancel payload: context_id: context-to-cancel cancel: true TtsAudioChunk: name: TtsAudioChunk title: Streamed audio chunk contentType: application/json payload: $ref: '#/components/schemas/TtsAudioChunkPayload' examples: - name: chunk payload: type: chunk data: base64-encoded-audio-data done: false status_code: 206 step_time: 123 context_id: context-id TtsWordTimestamps: name: TtsWordTimestamps title: Word-level timestamps contentType: application/json payload: $ref: '#/components/schemas/TtsWordTimestampsPayload' examples: - name: timestamps payload: type: timestamps done: false status_code: 206 context_id: context-id word_timestamps: words: [Hello, world] start: [0, 0.5] end: [0.4, 0.9] TtsPhonemeTimestamps: name: TtsPhonemeTimestamps title: Phoneme-level timestamps contentType: application/json payload: $ref: '#/components/schemas/TtsPhonemeTimestampsPayload' examples: - name: phonemeTimestamps payload: type: phoneme_timestamps done: false status_code: 206 context_id: context-id phoneme_timestamps: phonemes: [h, "ə", l] start: [0.093, 0.174, 0.255] end: [0.174, 0.255, 0.337] TtsFlushDone: name: TtsFlushDone title: Flush acknowledgement contentType: application/json payload: $ref: '#/components/schemas/FlushDonePayload' examples: - name: flushDone payload: type: flush_done done: false flush_done: true flush_id: 1 status_code: 206 context_id: context-id TtsDone: name: TtsDone title: Generation completion signal contentType: application/json payload: $ref: '#/components/schemas/DonePayload' examples: - name: done payload: type: done done: true status_code: 206 context_id: context-id TtsError: name: TtsError title: Error response contentType: application/json payload: $ref: '#/components/schemas/ErrorPayload' examples: - name: error payload: type: error done: true title: Invalid model message: The model is not valid... error_code: model_not_found status_code: 400 doc_url: https://docs.cartesia.ai/api-reference/tts/websocket request_id: unique-request-id context_id: context-id SttAudioFrame: name: SttAudioFrame title: Binary audio frame contentType: application/octet-stream payload: type: string format: binary description: >- Raw audio bytes matching the connection's `encoding` and `sample_rate` query parameters, sent as a WebSocket binary frame. 100ms chunks are recommended. SttFinalizeCommand: name: SttFinalizeCommand title: Finalize command contentType: text/plain payload: type: string enum: - finalize description: Text command instructing the server to transcribe currently buffered audio. SttCloseCommand: name: SttCloseCommand title: Close command contentType: text/plain payload: type: string enum: - close description: Text command instructing the server to flush remaining audio and terminate the session. SttTranscript: name: SttTranscript title: Transcript chunk contentType: application/json payload: $ref: '#/components/schemas/SttTranscriptPayload' examples: - name: partial payload: type: transcript is_final: false text: Hello wor words: - word: Hello start: 0 end: 0.4 request_id: req_01jbd6g2qdfw2adyrt2az8hz4w - name: final payload: type: transcript is_final: true text: Hello world words: - word: Hello start: 0 end: 0.4 - word: world start: 0.5 end: 0.9 request_id: req_01jbd6g2qdfw2adyrt2az8hz4w SttFlushDone: name: SttFlushDone title: Finalize acknowledgement contentType: application/json payload: $ref: '#/components/schemas/FlushDonePayload' SttDone: name: SttDone title: Close acknowledgement contentType: application/json payload: $ref: '#/components/schemas/DonePayload' SttError: name: SttError title: Error response contentType: application/json payload: $ref: '#/components/schemas/ErrorPayload' schemas: TtsGenerationRequestPayload: type: object required: - model_id - transcript - voice - output_format - context_id properties: model_id: type: string enum: [sonic-3.5, sonic-3, sonic-latest] transcript: type: string voice: type: object required: [mode, id] properties: mode: type: string enum: [id] id: type: string format: uuid output_format: type: object required: [container, encoding, sample_rate] properties: container: type: string enum: [raw] encoding: type: string enum: [pcm_f32le, pcm_s16le, pcm_mulaw, pcm_alaw] sample_rate: type: integer enum: [8000, 16000, 22050, 24000, 44100, 48000] context_id: type: string description: Unique identifier correlating requests/responses and preserving prosody across continued chunks. language: type: string description: One of 40+ supported language codes. continue: type: boolean default: false description: Set true if more transcript chunks follow on this context_id; false on the final chunk. flush: type: boolean description: Trigger a context flush. max_buffer_delay_ms: type: integer minimum: 0 maximum: 5000 default: 3000 add_timestamps: type: boolean default: false add_phoneme_timestamps: type: boolean default: false pronunciation_dict_id: type: string nullable: true generation_config: type: object properties: volume: type: number minimum: 0.5 maximum: 2.0 default: 1 speed: type: number minimum: 0.6 maximum: 1.5 default: 1 emotion: type: string enum: [neutral, calm, angry, content, sad] TtsCancelRequestPayload: type: object required: - context_id - cancel properties: context_id: type: string cancel: type: boolean enum: [true] TtsAudioChunkPayload: type: object required: - type - data - context_id properties: type: type: string enum: [chunk] data: type: string description: Base64-encoded audio data. done: type: boolean status_code: type: integer step_time: type: integer description: Milliseconds taken to generate this chunk. context_id: type: string TtsWordTimestampsPayload: type: object required: - type - context_id properties: type: type: string enum: [timestamps] done: type: boolean status_code: type: integer context_id: type: string word_timestamps: type: object properties: words: type: array items: type: string start: type: array items: type: number end: type: array items: type: number TtsPhonemeTimestampsPayload: type: object required: - type - context_id properties: type: type: string enum: [phoneme_timestamps] done: type: boolean status_code: type: integer context_id: type: string phoneme_timestamps: type: object properties: phonemes: type: array items: type: string start: type: array items: type: number end: type: array items: type: number FlushDonePayload: type: object required: - type - context_id properties: type: type: string enum: [flush_done] done: type: boolean flush_done: type: boolean flush_id: type: integer description: Increments with each flush command, correlating with transcript batches. status_code: type: integer context_id: type: string DonePayload: type: object required: - type - done - context_id properties: type: type: string enum: [done] done: type: boolean enum: [true] status_code: type: integer context_id: type: string ErrorPayload: type: object required: - type - error_code - status_code properties: type: type: string enum: [error] done: type: boolean title: type: string message: type: string error_code: type: string status_code: type: integer doc_url: type: string request_id: type: string context_id: type: string SttTranscriptPayload: type: object required: - type - is_final - text properties: type: type: string enum: [transcript] is_final: type: boolean description: Whether this chunk represents a finalized segment of the transcript. text: type: string description: Delta text since the last finalized chunk. words: type: array items: type: object properties: word: type: string start: type: number end: type: number request_id: type: string x-maintainers: - FN: Kin Lane email: kin@apievangelist.com