> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nineninesix.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Text-to-Speech (WebSocket)

> Real-time, low-latency TTS over a persistent WebSocket connection.



## AsyncAPI

````yaml api-reference/asyncapi.yaml tts
id: tts
title: WebSocket Streaming
description: |
  Bidirectional streaming channel. Contexts are multiplexed by `context_id`;
  rotate the id per turn so you can cancel and route independently.

  **Connect** — `wss://api.nineninesix.ai/tts/websocket?api_key=sk_996_...`
  (`?cartesia_version=` is accepted and ignored).

  **Turn model** — send generation requests with `continue: true` to stream
  sentences in; a final `continue: false` (an empty `transcript` works) ends
  the turn and triggers `done`. There is no separate flush message.

  **`output_format`** is resolved once per connection from the first request
  that carries it (default `raw` / `pcm_s16le` / `22050`); streaming is
  `raw`-only. Each generated `transcript` is billed independently — confirmed
  on `done`, refunded on `error`.

  ### Error codes

  | Error | Status | Effect |
  |---|---|---|
  | `unknown_model` | 400 | Gateway · closes socket |
  | `concurrent_limit` | 429 | Gateway · drops only that context |
  | `insufficient_credits` | 402 | Gateway · closes socket |
  | `voice_not_found` | 404 | Upstream · closes socket |
  | `unsupported_container` | 400 | Upstream · closes socket |
  | `unsupported_encoding` | 400 | Upstream · closes socket |
  | `invalid_sample_rate` | 400 | Upstream · closes socket |
  | `generation_failed` | 500 | Upstream · context ends, socket stays open |
  | `not_initialized` | 503 | Upstream · closes socket |

  On `concurrent_limit`, retry the rejected turn on a fresh `context_id`.

  ### Not supported

  No `flush_done`, no word/phoneme timestamps (`add_timestamps` is accepted
  but inert), and no binary frames — audio is base64 inside the text `chunk`
  frame.
servers:
  - id: production
    protocol: wss
    host: api.nineninesix.ai
    bindings: []
    variables: []
address: /tts/websocket
parameters: []
bindings: []
operations:
  - &ref_8
    id: sendRequest
    title: Send
    description: Client → server. A generation request or a cancel context request.
    type: receive
    messages:
      - &ref_10
        id: generationRequest
        contentType: application/json
        payload:
          - name: Generation request
            description: Speak a transcript within a context.
            type: object
            properties:
              - name: model_id
                type: string
                description: >
                  Send `gepard-1.0` or omit. Validated at the gateway on the
                  first request; an unknown id → `unknown_model` (400) and the
                  socket closes.
                enumValues:
                  - gepard-1.0
                required: false
              - name: transcript
                type: string
                description: >
                  The text to speak. May be "" — an empty transcript with
                  `continue: false` is a pure end-of-turn marker. Trimmed
                  server-side.
                examples: &ref_0
                  - Hello there.
                required: true
              - name: context_id
                type: string
                description: >
                  Turn identifier. If omitted the server assigns a random uuid,
                  but you then can't cancel or route it — send one and rotate it
                  per turn.
                examples: &ref_1
                  - t1
                required: false
              - name: continue
                type: boolean
                description: >
                  `true` = more transcripts for this context are coming (stream
                  sentences in). `false` = end of turn → the server emits `done`
                  after the queued sentences finish.
                required: false
              - name: voice
                type: object
                description: >
                  Omit (or use any other mode) for the default voice. Validated
                  on every request that names a voice.
                required: false
                properties:
                  - name: mode
                    type: string
                    enumValues:
                      - id
                    required: false
                  - name: id
                    type: string
                    description: >-
                      Saved voice id. Unknown id → `voice_not_found` (404) and
                      the socket closes.
                    examples: &ref_2
                      - a0e99841-438c-4a64-b679-ae501e7d6091
                    required: false
              - name: output_format
                type: object
                description: >
                  Resolved once per connection from the first request that
                  carries it, then held constant.
                required: false
                properties:
                  - name: container
                    type: string
                    description: raw only — a stream can't frame a wav/mp3 file.
                    enumValues:
                      - raw
                    required: false
                  - name: encoding
                    type: string
                    enumValues:
                      - pcm_s16le
                      - pcm_mulaw
                      - pcm_alaw
                    required: false
                  - name: sample_rate
                    type: integer
                    description: Model is native 22050 Hz; 8000/16000 are resampled.
                    enumValues:
                      - 8000
                      - 16000
                      - 22050
                    required: false
        headers: []
        jsonPayloadSchema:
          type: object
          required:
            - transcript
          properties:
            model_id:
              type: string
              enum:
                - gepard-1.0
              description: >
                Send `gepard-1.0` or omit. Validated at the gateway on the first
                request; an unknown id → `unknown_model` (400) and the socket
                closes.
              x-parser-schema-id: <anonymous-schema-2>
            transcript:
              type: string
              description: >
                The text to speak. May be "" — an empty transcript with
                `continue: false` is a pure end-of-turn marker. Trimmed
                server-side.
              examples: *ref_0
              x-parser-schema-id: <anonymous-schema-3>
            context_id:
              type: string
              description: >
                Turn identifier. If omitted the server assigns a random uuid,
                but you then can't cancel or route it — send one and rotate it
                per turn.
              examples: *ref_1
              x-parser-schema-id: <anonymous-schema-4>
            continue:
              type: boolean
              default: false
              description: >
                `true` = more transcripts for this context are coming (stream
                sentences in). `false` = end of turn → the server emits `done`
                after the queued sentences finish.
              x-parser-schema-id: <anonymous-schema-5>
            voice:
              type: object
              description: >
                Omit (or use any other mode) for the default voice. Validated on
                every request that names a voice.
              properties:
                mode:
                  type: string
                  enum:
                    - id
                  x-parser-schema-id: <anonymous-schema-7>
                id:
                  type: string
                  description: >-
                    Saved voice id. Unknown id → `voice_not_found` (404) and the
                    socket closes.
                  examples: *ref_2
                  x-parser-schema-id: <anonymous-schema-8>
              x-parser-schema-id: <anonymous-schema-6>
            output_format:
              type: object
              description: >
                Resolved once per connection from the first request that carries
                it, then held constant.
              properties:
                container:
                  type: string
                  enum:
                    - raw
                  default: raw
                  description: raw only — a stream can't frame a wav/mp3 file.
                  x-parser-schema-id: <anonymous-schema-10>
                encoding:
                  type: string
                  enum:
                    - pcm_s16le
                    - pcm_mulaw
                    - pcm_alaw
                  default: pcm_s16le
                  x-parser-schema-id: <anonymous-schema-11>
                sample_rate:
                  type: integer
                  enum:
                    - 8000
                    - 16000
                    - 22050
                  default: 22050
                  description: Model is native 22050 Hz; 8000/16000 are resampled.
                  x-parser-schema-id: <anonymous-schema-12>
              x-parser-schema-id: <anonymous-schema-9>
          x-parser-schema-id: <anonymous-schema-1>
        title: Generation request
        description: Speak a transcript within a context.
        example: |-
          {
            "model_id": "<string>",
            "transcript": "<string>",
            "context_id": "<string>",
            "continue": true,
            "voice": {
              "mode": "<string>",
              "id": "<string>"
            },
            "output_format": {
              "container": "<string>",
              "encoding": "<string>",
              "sample_rate": 123
            }
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: generationRequest
      - &ref_11
        id: cancelRequest
        contentType: application/json
        payload:
          - name: Cancel context request
            description: >
              Stop a context's in-flight generation and drop its queued
              sentences. Silent — the server sends no acknowledgement; chunks
              for that context simply stop. Other contexts keep running.
            type: object
            properties:
              - name: context_id
                type: string
                examples: &ref_3
                  - t2
                required: true
              - name: cancel
                type: boolean
                description: true
                required: true
        headers: []
        jsonPayloadSchema:
          type: object
          required:
            - context_id
            - cancel
          properties:
            context_id:
              type: string
              examples: *ref_3
              x-parser-schema-id: <anonymous-schema-14>
            cancel:
              type: boolean
              const: true
              x-parser-schema-id: <anonymous-schema-15>
          x-parser-schema-id: <anonymous-schema-13>
        title: Cancel context request
        description: >
          Stop a context's in-flight generation and drop its queued sentences.
          Silent — the server sends no acknowledgement; chunks for that context
          simply stop. Other contexts keep running.
        example: |-
          {
            "context_id": "<string>",
            "cancel": true
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: cancelRequest
    bindings: []
    extensions: &ref_7
      - id: x-parser-unique-object-id
        value: tts
  - &ref_9
    id: receiveAudio
    title: Receive
    description: Server → client. An audio chunk, a done frame, or an error.
    type: send
    messages:
      - &ref_12
        id: chunk
        contentType: application/json
        payload:
          - name: Audio chunk
            description: One audio segment.
            type: object
            properties:
              - name: type
                type: string
                description: chunk
                required: false
              - name: context_id
                type: string
                required: false
              - name: done
                type: boolean
                description: false
                required: false
              - name: status_code
                type: integer
                description: 206
                required: false
              - name: data
                type: string
                description: >
                  Base64 of raw PCM in the negotiated encoding (default
                  `pcm_s16le` @ 22050 Hz). Not a wav container — decode per the
                  `output_format` you set.
                required: false
        headers: []
        jsonPayloadSchema:
          type: object
          properties:
            type:
              type: string
              const: chunk
              x-parser-schema-id: <anonymous-schema-17>
            context_id:
              type: string
              x-parser-schema-id: <anonymous-schema-18>
            done:
              type: boolean
              const: false
              x-parser-schema-id: <anonymous-schema-19>
            status_code:
              type: integer
              const: 206
              x-parser-schema-id: <anonymous-schema-20>
            data:
              type: string
              description: >
                Base64 of raw PCM in the negotiated encoding (default
                `pcm_s16le` @ 22050 Hz). Not a wav container — decode per the
                `output_format` you set.
              x-parser-schema-id: <anonymous-schema-21>
          x-parser-schema-id: <anonymous-schema-16>
        title: Audio chunk
        description: One audio segment.
        example: |-
          {
            "type": "<string>",
            "context_id": "<string>",
            "done": true,
            "status_code": 123,
            "data": "<string>"
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: chunk
      - &ref_13
        id: done
        contentType: application/json
        payload:
          - name: Done
            description: >-
              The context/turn is complete, after a `continue: false` and all
              queued sentences render.
            type: object
            properties:
              - name: type
                type: string
                description: done
                required: false
              - name: context_id
                type: string
                required: false
              - name: done
                type: boolean
                description: true
                required: false
              - name: status_code
                type: integer
                description: 200
                required: false
        headers: []
        jsonPayloadSchema:
          type: object
          properties:
            type:
              type: string
              const: done
              x-parser-schema-id: <anonymous-schema-23>
            context_id:
              type: string
              x-parser-schema-id: <anonymous-schema-24>
            done:
              type: boolean
              const: true
              x-parser-schema-id: <anonymous-schema-25>
            status_code:
              type: integer
              const: 200
              x-parser-schema-id: <anonymous-schema-26>
          x-parser-schema-id: <anonymous-schema-22>
        title: Done
        description: >-
          The context/turn is complete, after a `continue: false` and all queued
          sentences render.
        example: |-
          {
            "type": "<string>",
            "context_id": "<string>",
            "done": true,
            "status_code": 123
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: done
      - &ref_14
        id: error
        contentType: application/json
        payload:
          - name: Error
            description: >-
              Full Cartesia-shaped error envelope. See the error-code catalog
              above.
            type: object
            properties:
              - name: type
                type: string
                description: error
                required: false
              - name: context_id
                type: &ref_4
                  - string
                  - 'null'
                required: false
              - name: done
                type: boolean
                description: true
                required: false
              - name: error_code
                type: string
                examples: &ref_5
                  - insufficient_credits
                required: false
              - name: status_code
                type: integer
                examples: &ref_6
                  - 402
                required: false
              - name: title
                type: string
                required: false
              - name: message
                type: string
                required: false
              - name: doc_url
                type: string
                required: false
              - name: request_id
                type: string
                required: false
        headers: []
        jsonPayloadSchema:
          type: object
          properties:
            type:
              type: string
              const: error
              x-parser-schema-id: <anonymous-schema-28>
            context_id:
              type: *ref_4
              x-parser-schema-id: <anonymous-schema-29>
            done:
              type: boolean
              const: true
              x-parser-schema-id: <anonymous-schema-30>
            error_code:
              type: string
              examples: *ref_5
              x-parser-schema-id: <anonymous-schema-31>
            status_code:
              type: integer
              examples: *ref_6
              x-parser-schema-id: <anonymous-schema-32>
            title:
              type: string
              x-parser-schema-id: <anonymous-schema-33>
            message:
              type: string
              x-parser-schema-id: <anonymous-schema-34>
            doc_url:
              type: string
              x-parser-schema-id: <anonymous-schema-35>
            request_id:
              type: string
              x-parser-schema-id: <anonymous-schema-36>
          x-parser-schema-id: <anonymous-schema-27>
        title: Error
        description: Full Cartesia-shaped error envelope. See the error-code catalog above.
        example: |-
          {
            "type": "<string>",
            "done": true,
            "error_code": "<string>",
            "status_code": 123,
            "title": "<string>",
            "message": "<string>",
            "doc_url": "<string>",
            "request_id": "<string>"
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: error
    bindings: []
    extensions: *ref_7
sendOperations:
  - *ref_8
receiveOperations:
  - *ref_9
sendMessages:
  - *ref_10
  - *ref_11
receiveMessages:
  - *ref_12
  - *ref_13
  - *ref_14
extensions:
  - id: x-parser-unique-object-id
    value: tts
securitySchemes:
  - id: apiKey
    name: api_key
    type: httpApiKey
    description: >
      Your Nineninesix API key (`sk_996_...`), sent as the `api_key` query
      parameter on the connection URL.
    in: query
    extensions: []

````