Cartesia · AsyncAPI Specification

Cartesia Realtime WebSocket API (TTS + STT)

Version 2026-03-01

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.

View Spec View on GitHub AIVoice AIText to SpeechSpeech to TextRealtimeWebSocketVoice CloningVoice AgentsAsyncAPIWebhooksEvents

Channels

/tts/websocket
publish sendTtsGenerationRequest
Send a TTS generation (or cancel) request.
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.
/stt/websocket
publish sendSttAudioAndCommands
Stream binary audio frames and send finalize/close commands.
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.

Messages

TtsGenerationRequest
TTS generation request
TtsCancelRequest
TTS cancel request
TtsAudioChunk
Streamed audio chunk
TtsWordTimestamps
Word-level timestamps
TtsPhonemeTimestamps
Phoneme-level timestamps
TtsFlushDone
Flush acknowledgement
TtsDone
Generation completion signal
TtsError
Error response
SttAudioFrame
Binary audio frame
SttFinalizeCommand
Finalize command
SttCloseCommand
Close command
SttTranscript
Transcript chunk
SttFlushDone
Finalize acknowledgement
SttDone
Close acknowledgement
SttError
Error response

Servers

wss
ttsWebsocket api.cartesia.ai/tts/websocket?cartesia_version=2026-03-01
Bidirectional TTS streaming connection. Authenticate with an `X-API-Key` header or an `access_token` query parameter.
wss
sttWebsocket api.cartesia.ai/stt/websocket?model=ink-whisper&encoding=pcm_s16le&sample_rate=16000&cartesia_version=2026-03-01
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`.

AsyncAPI Specification

Raw ↑
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