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

# Generate speech

> Native speech synthesis with full control of container, sample rate, and encoding. Returns raw audio bytes; set stream true for progressive relay of WAV/PCM bytes.



## OpenAPI

````yaml /api-reference/openapi.json post /tts/bytes
openapi: 3.1.0
info:
  title: Hopper API
  version: 1.0.0
  description: >-
    Inference for voice agents: LLM, text to speech, and speech to text at
    api.withhopper.com. OpenAI-compatible routes are served under /v1; native
    routes are served at the root. All errors use the OpenAI envelope.
servers:
  - url: https://api.withhopper.com
security:
  - bearerAuth: []
tags:
  - name: LLM
    description: OpenAI-compatible chat completions and model listing.
  - name: Text to Speech
    description: >-
      Speech synthesis: native /tts routes and the OpenAI-compatible
      /v1/audio/speech.
  - name: Speech to Text
    description: Batch transcription. Streaming runs over WS /stt/websocket.
  - name: Voices
    description: Voice library, cloning, profiles, and localization.
  - name: Pronunciation
    description: Pronunciation dictionaries applied at synthesis time.
  - name: Jobs
    description: Status of async voice jobs.
  - name: Health
    description: Unauthenticated liveness check.
paths:
  /tts/bytes:
    post:
      tags:
        - Text to Speech
      summary: Generate speech
      description: >-
        Native speech synthesis with full control of container, sample rate, and
        encoding. Returns raw audio bytes; set stream true for progressive relay
        of WAV/PCM bytes.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TtsRequest'
      responses:
        '200':
          description: Audio bytes. Content-Type follows output_format.container.
          headers:
            x-hopper-request-cost-usd:
              $ref: '#/components/headers/XHopperRequestCostUsd'
            x-hopper-credits-remaining-usd:
              $ref: '#/components/headers/XHopperCreditsRemainingUsd'
          content:
            audio/wav:
              schema:
                type: string
                format: binary
            audio/mpeg:
              schema:
                type: string
                format: binary
            application/octet-stream:
              schema:
                type: string
                format: binary
        '400':
          description: >-
            Invalid body. Codes: invalid_json, invalid_output_format (mp3 with
            stream), invalid_generation_config (speed other than 1 with stream),
            transcript_too_long (dictionary alias expansion past 20,000
            characters).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  message: Streaming TTS does not support mp3; use wav or pcm/raw.
                  type: invalid_request_error
                  code: invalid_output_format
                  param: null
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          description: >-
            Unknown model, voice, or pronunciation dictionary. Codes:
            model_not_found, voice_not_found, dict_not_found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          $ref: '#/components/responses/VoiceProfileMissing'
        '429':
          $ref: '#/components/responses/RateLimited'
        '502':
          description: 'Upstream failed. Codes: upstream_unavailable, upstream_error.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: 'No healthy upstream for this model. Code: model_offline.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '504':
          description: 'Upstream timed out (300 s). Code: upstream_timeout.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    TtsRequest:
      type: object
      required:
        - model_id
        - transcript
        - voice
        - output_format
      properties:
        model_id:
          type: string
          description: TTS model id, e.g. omnivoice.
        transcript:
          type: string
          minLength: 1
          maxLength: 5000
          description: >-
            Text to synthesize, 1-5000 characters. Billed per character of the
            submitted transcript, before dictionary expansion.
        voice:
          type: object
          required:
            - mode
            - id
          properties:
            mode:
              type: string
              enum:
                - id
            id:
              type: string
              description: Voice id from GET /voices.
        language:
          type: string
          pattern: ^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})?$
          description: ISO language code.
        output_format:
          type: object
          required:
            - container
            - sample_rate
          properties:
            container:
              type: string
              enum:
                - wav
                - mp3
                - raw
              description: mp3 is batch-only; streaming supports wav and raw.
            sample_rate:
              type: integer
              enum:
                - 8000
                - 16000
                - 22050
                - 24000
                - 44100
                - 48000
            encoding:
              type: string
              enum:
                - pcm_f32le
                - pcm_s16le
                - pcm_mulaw
                - pcm_alaw
              default: pcm_s16le
              description: wav and raw only; rejected for mp3.
            bit_rate:
              type: integer
              enum:
                - 32000
                - 64000
                - 96000
                - 128000
                - 192000
                - 256000
                - 320000
              default: 128000
              description: mp3 only.
        generation_config:
          type: object
          properties:
            speed:
              type: number
              minimum: 0.6
              maximum: 1.5
              description: Playback speed. Streaming requires speed 1.
            volume:
              type: number
              minimum: 0.5
              maximum: 2
        pronunciation_dict_id:
          type: string
          description: Dictionary applied before synthesis; 404 dict_not_found if unknown.
        stream:
          type: boolean
          default: false
          description: >-
            On /tts/bytes: relay raw WAV/PCM bytes progressively as they are
            generated. Ignored on /tts/sse, which always streams.
    Error:
      type: object
      description: OpenAI error envelope, used by every error response.
      properties:
        error:
          type: object
          properties:
            message:
              type: string
            type:
              type: string
            code:
              type: string
            param:
              type:
                - string
                - 'null'
  headers:
    XHopperRequestCostUsd:
      description: >-
        Cost of this request, 6-decimal USD string (e.g. 0.000123). Absent on
        LLM streaming responses; the cost is unknown until the stream ends.
      schema:
        type: string
    XHopperCreditsRemainingUsd:
      description: >-
        Credit balance in USD, 6-decimal string. On LLM streaming responses this
        is the pre-request balance.
      schema:
        type: string
  responses:
    Unauthorized:
      description: >-
        Missing, malformed, or revoked API key. Codes: invalid_api_key,
        api_key_disabled.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              message: >-
                Incorrect API key provided. Check your key at
                https://withhopper.com/dashboard.
              type: invalid_request_error
              code: invalid_api_key
              param: null
    PaymentRequired:
      description: Credit balance is zero.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              message: You have run out of credits. Contact us to add more.
              type: insufficient_quota
              code: insufficient_quota
              param: null
    VoiceProfileMissing:
      description: >-
        The voice has no ready profile for this model. Prepare one with POST
        /voices/:id/profiles. Code: voice_profile_missing.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              message: Voice 'X' is not prepared for model 'Y'.
              type: invalid_request_error
              code: voice_profile_missing
              param: null
    RateLimited:
      description: >-
        Over 600 requests per minute on this key. Retry after the number of
        seconds in Retry-After.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              message: >-
                Rate limit reached: 600 requests per minute per key. Retry after
                21s.
              type: rate_limit_error
              code: rate_limit_exceeded
              param: null
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        API key in the Authorization header: Bearer sk_hopper_... Keys are
        minted in the dashboard at withhopper.com/console/keys and shown once at
        creation. WebSocket connections also accept ?api_key=.

````