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

# Synthesize speech (async)

> Submit a synthesis job that runs in the background and immediately receive a [long-running operation](https://google.aip.dev/151). Poll the operation via the Get operation endpoint until `done` is `true`, then download the results from the time-limited signed URLs in its `response`. The request body is identical to synchronous synthesis. Unlike the synchronous endpoints, a job never returns audio with requested timestamps silently missing: `timestampType` in a language without alignment support is rejected at submit, and an alignment failure during synthesis fails the operation.



## OpenAPI

````yaml post /tts/v1/voice:synthesizeAsync
openapi: 3.0.0
info:
  title: Inworld Text-to-Speech API
  version: v1
  contact:
    name: Inworld AI
    url: https://inworld.ai
    email: support@inworld.ai
servers:
  - url: https://api.inworld.ai
security:
  - inworld_basic: []
tags:
  - name: TextToSpeech
  - name: AudioPromptPreparationService
  - name: SpeechToPhonemesService
paths:
  /tts/v1/voice:synthesizeAsync:
    post:
      tags:
        - TextToSpeech
      summary: Synthesize speech (async)
      description: >-
        Submit a synthesis job that runs in the background and immediately
        receive a [long-running operation](https://google.aip.dev/151). Poll the
        operation via the Get operation endpoint until `done` is `true`, then
        download the results from the time-limited signed URLs in its
        `response`. The request body is identical to synchronous synthesis.
        Unlike the synchronous endpoints, a job never returns audio with
        requested timestamps silently missing: `timestampType` in a language
        without alignment support is rejected at submit, and an alignment
        failure during synthesis fails the operation.
      operationId: TextToSpeech_SynthesizeSpeechAsync
      requestBody:
        $ref: '#/components/requestBodies/ttsv1SynthesizeSpeechRequest'
      responses:
        '200':
          description: >-
            The job was accepted. The returned operation is not yet done; poll
            it to track progress.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/longrunningOperation'
              examples:
                submitted:
                  summary: Job accepted
                  value:
                    name: >-
                      workspaces/{workspace}/ttsAsyncJobs/8f14e45f-ceea-4673-93d8-04f724c8a1b2/operations/1784837936461-p0sEhU
                    metadata: null
                    done: false
        4XX:
          description: An unexpected error response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/rpcStatus'
      x-codeSamples:
        - lang: bash
          label: cURL
          source: >-
            curl --location
            'https://api.inworld.ai/tts/v1/voice:synthesizeAsync' \

            --header "Authorization: Basic $INWORLD_API_KEY" \

            --header 'Content-Type: application/json' \

            --data '{
              "text": "Hello, world! What a wonderful day to be a text-to-speech model!",
              "voiceId": "Dennis",
              "modelId": "inworld-tts-2",
              "audioConfig": {
                "audioEncoding": "MP3"
              },
              "timestampType": "WORD"
            }'
        - lang: python
          label: Python
          source: |-
            import requests

            url = "https://api.inworld.ai/tts/v1/voice:synthesizeAsync"
            headers = {
                "Authorization": "Basic <api-key>",
                "Content-Type": "application/json"
            }
            payload = {
                "text": "Hello, world! What a wonderful day to be a text-to-speech model!",
                "voiceId": "Dennis",
                "modelId": "inworld-tts-2",
                "audioConfig": {"audioEncoding": "MP3"},
                "timestampType": "WORD"
            }

            operation = requests.post(url, json=payload, headers=headers).json()
            print(operation["name"])  # poll this via GET /lro/v1alpha/{name}
        - lang: javascript
          label: JavaScript
          source: >-
            const url = 'https://api.inworld.ai/tts/v1/voice:synthesizeAsync';


            const response = await fetch(url, {
              method: 'POST',
              headers: {
                'Authorization': 'Basic <api-key>',
                'Content-Type': 'application/json',
              },
              body: JSON.stringify({
                text: 'Hello, world! What a wonderful day to be a text-to-speech model!',
                voiceId: 'Dennis',
                modelId: 'inworld-tts-2',
                audioConfig: { audioEncoding: 'MP3' },
                timestampType: 'WORD',
              }),
            });


            const operation = await response.json();

            console.log(operation.name); // poll this via GET
            /lro/v1alpha/{name}
components:
  requestBodies:
    ttsv1SynthesizeSpeechRequest:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ttsv1SynthesizeSpeechRequest'
          example:
            text: Hello, world! What a wonderful day to be a text-to-speech model!
            voiceId: Dennis
            modelId: inworld-tts-2
            audioConfig:
              audioEncoding: LINEAR16
              sampleRateHertz: 22050
            deliveryMode: BALANCED
            applyTextNormalization: 'ON'
      required: true
  schemas:
    longrunningOperation:
      type: object
      description: >-
        A [google.longrunning.Operation](https://google.aip.dev/151) tracking an
        asynchronous or batch synthesis job.
      properties:
        name:
          type: string
          description: >-
            Server-assigned operation resource name, in the format
            `workspaces/{workspace}/ttsAsyncJobs/{job}/operations/{operation}`
            for async jobs or
            `workspaces/{workspace}/ttsBatchJobs/{batch}/operations/{operation}`
            for batch jobs. Pass it verbatim as the path of the Get operation
            endpoint to poll for completion.
          example: >-
            workspaces/{workspace}/ttsAsyncJobs/8f14e45f-ceea-4673-93d8-04f724c8a1b2/operations/1784837936461-p0sEhU
        metadata:
          description: >-
            Service-specific metadata associated with the operation. Not
            populated for TTS jobs yet; job metadata is planned for a later
            release, so do not write code that depends on this field staying
            absent.
          nullable: true
          allOf:
            - $ref: '#/components/schemas/protobufAny'
        done:
          type: boolean
          description: >-
            If `false`, the job is still running. If `true`, the job has
            finished and exactly one of `error` or `response` is set.
        error:
          $ref: '#/components/schemas/rpcStatus'
        response:
          description: >-
            Set when the job succeeded. Its `@type` identifies which kind: an
            async job carries SynthesizeSpeechAsyncResponse, a batch job
            SynthesizeSpeechBatchResponse.
          oneOf:
            - $ref: '#/components/schemas/ttsv1SynthesizeSpeechAsyncResponse'
            - $ref: '#/components/schemas/ttsv1SynthesizeSpeechBatchResponse'
    rpcStatus:
      type: object
      properties:
        code:
          type: integer
          format: int32
          description: >-
            The error code, as specified by [gRPC status
            codes](https://grpc.io/docs/guides/status-codes/).
          example: 5
        message:
          type: string
          description: A short description of the error.
          example: 'Unknown voice: John not found!'
        details:
          type: array
          items:
            $ref: '#/components/schemas/protobufAny'
          example: []
    ttsv1SynthesizeSpeechRequest:
      type: object
      properties:
        text:
          type: string
          description: >-
            The text to be synthesized into speech. Maximum input of 2,000
            characters.
        voiceId:
          type: string
          description: The ID of the voice to use for synthesizing speech.
        audioConfig:
          $ref: '#/components/schemas/ttsv1AudioConfig'
        modelId:
          type: string
          description: >-
            The ID of the model to use for synthesizing speech. See
            [Models](../../../tts/tts-models) for available models.
        language:
          type: string
          description: >-
            BCP-47 language tag (e.g., `en-US`, `fr-FR`, `ja-JP`) specifying the
            language that the given voice should speak the text in. Matching is
            case- and separator-insensitive for standard two-part tags (`en-gb`,
            `EN_GB`, and `en-GB` are equivalent); longer tags with extension
            subtags must match a catalog entry exactly. If a localized voice
            prompt exists for the language, it will be used. When omitted, the
            original voice prompt will be used and the language will be
            auto-detected from the input text. If an invalid language code is
            provided, an error will be returned.


            See [Languages](../../../tts/capabilities/multilingual) for more
            details.
        deliveryMode:
          type: string
          enum:
            - DELIVERY_MODE_UNSPECIFIED
            - STABLE
            - BALANCED
            - CREATIVE
          default: DELIVERY_MODE_UNSPECIFIED
          description: >-
            *Only supported by `inworld-tts-2`. The field is ignored on other
            models.*


            Controls how varied the output is. 


            - `DELIVERY_MODE_UNSPECIFIED`: Defaults to `BALANCED` behavior.

            - `STABLE`: Optimizes for more consistent, predictable output.

            - `BALANCED`: Balanced between stability and diversity.

            - `CREATIVE`: Optimizes for increased emotional range and variation.
        instruction:
          type: string
          description: >-
            *Only supported by `inworld-tts-2`. The field is ignored on other
            models.*


            Speaking-style instruction for this request — for example `speak
            loudly and urgently` or `sound out of breath`. Applies to the whole
            request. Write it in English, even when `text` is in another
            language. An empty string means unset.


            You can also change the instruction mid-text with inline `[bracket]`
            tags. A tag applies from where it appears until you change it, so it
            overrides this field from that point on; `[reset]` removes the
            instruction for the rest of the text. Prefer one approach or the
            other rather than combining them.


            See [Steering](../../../tts/capabilities/steering) for the full
            guide.
        temperature:
          type: number
          format: float
          default: 1
          description: >-
            *Ignored on `inworld-tts-2`. Use
            [`deliveryMode`](#body-delivery-mode) instead.*


            Determines the degree of randomness when sampling audio tokens to
            generate the response.


            Defaults to 1.0. Accepts values between 0 (exclusive) and 2
            (inclusive). Higher values will make the output more random and can
            lead to more expressive results. Lower values will make it more
            deterministic. If 0 is provided, the default value will be used.


            For the most stable results, we recommend using the default value.
        timestampType:
          type: string
          enum:
            - TIMESTAMP_TYPE_UNSPECIFIED
            - WORD
            - CHARACTER
          default: TIMESTAMP_TYPE_UNSPECIFIED
          description: >-
            Controls timestamp metadata returned with the audio. When enabled,
            the response includes timing arrays, which can be useful for
            word-highlighting, karaoke-style captions, and lipsync.


            - WORD: Output arrays under `timestampInfo.wordAlignment` (words,
            wordStartTimeSeconds, wordEndTimeSeconds).

            - CHARACTER: Output arrays under `timestampInfo.characterAlignment`
            (characters, characterStartTimeSeconds, characterEndTimeSeconds).

            - TIMESTAMP_TYPE_UNSPECIFIED: Do not compute alignment; timestamp
            arrays will be empty or omitted.


            **Phonetic details:** `phoneticDetails` is currently only returned
            for **WORD** alignment (not CHARACTER).


            **Latency note:** Alignment adds additional computation. Enabling
            alignment can increase latency.
        applyTextNormalization:
          type: string
          enum:
            - APPLY_TEXT_NORMALIZATION_UNSPECIFIED
            - 'ON'
            - 'OFF'
          default: APPLY_TEXT_NORMALIZATION_UNSPECIFIED
          description: >-
            When enabled, text normalization automatically expands and
            standardizes things like numbers, dates, times, and abbreviations
            before converting them to speech. For example, Dr. Smith becomes
            Doctor Smith, and 3/10/25 is spoken as March tenth, twenty
            twenty-five. Turning this off may reduce latency, but the speech
            output will read the text exactly as written. Defaults to
            automatically deciding whether to apply text normalization.
        enhanceGeneration:
          type: boolean
          default: false
          description: >-
            When `true`, applies denoising to the synthesized audio to reduce
            background noise and artifacts, improving the overall audio quality
            of the generation. Defaults to `false` (no denoising).
        synthesisContext:
          $ref: '#/components/schemas/ttsv1SynthesisContext'
      required:
        - text
        - voiceId
        - modelId
    protobufAny:
      type: object
      properties:
        '@type':
          type: string
      additionalProperties: {}
    ttsv1SynthesizeSpeechAsyncResponse:
      type: object
      description: >-
        Result of a completed asynchronous synthesis job, packed into the
        operation's `response` field. The download URLs are pre-signed and
        time-limited: fetch them without an `Authorization` header, and before
        `expireTime`.
      properties:
        '@type':
          type: string
          description: >-
            Type of the serialized message, always
            `type.googleapis.com/ai.inworld.tts.v1.SynthesizeSpeechAsyncResponse`.
          example: type.googleapis.com/ai.inworld.tts.v1.SynthesizeSpeechAsyncResponse
        audioUri:
          type: string
          description: >-
            Pre-signed download URL for the synthesized audio, in the format
            requested via `audioConfig.audioEncoding`.
          example: https://storage.googleapis.com/…/audio.mp3?X-Goog-Signature=…
        timestampsUri:
          type: string
          description: >-
            Pre-signed download URL for the timestamp alignment JSON. Only
            present when `timestampType` was set in the request.
          example: https://storage.googleapis.com/…/timestamps.json?X-Goog-Signature=…
        expireTime:
          type: string
          format: date-time
          description: >-
            Time at which the download URLs expire, approximately 7 days after
            job completion.
          example: '2026-07-30T12:00:00Z'
    ttsv1SynthesizeSpeechBatchResponse:
      type: object
      description: >-
        Result of a completed batch, packed into the operation's `response`
        field. A batch's per-item URLs do not fit in one response, so this names
        a results *file* instead. The URL is pre-signed and time-limited: fetch
        it without an `Authorization` header, and before `expireTime`.
      properties:
        '@type':
          type: string
          description: >-
            Type of the serialized message, always
            `type.googleapis.com/ai.inworld.tts.v1.SynthesizeSpeechBatchResponse`.
          example: type.googleapis.com/ai.inworld.tts.v1.SynthesizeSpeechBatchResponse
        resultsUri:
          type: string
          description: >-
            Pre-signed download URL for the results file, whose contents are
            described by SynthesizeSpeechBatchResults.
          example: https://storage.googleapis.com/…/results.json?X-Goog-Signature=…
        expireTime:
          type: string
          format: date-time
          description: >-
            Time at which the results file and every audio URL inside it expire,
            approximately 7 days after the batch completes.
          example: '2026-08-13T18:13:47Z'
    ttsv1AudioConfig:
      type: object
      properties:
        audioEncoding:
          $ref: '#/components/schemas/v1AudioConfigAudioEncoding'
        bitRate:
          type: integer
          format: int32
          description: >-
            Bits per second of the audio. Only for compressed audio formats
            (`MP3`, `OGG_OPUS`). The default is 128,000.
        sampleRateHertz:
          type: integer
          format: int32
          description: >-
            The synthesis sample rate (in hertz) for this audio. Accepts values
            within the range [8000, 48000]. Supported sample rates are: 8000,
            16000, 22050, 24000, 32000, 44100, 48000.

             When this is specified, if this is different from the voice's natural sample rate, then the audio will be converted to the desired sample rate (which might result in worse audio quality), unless the specified sample rate is not supported for the encoding chosen, in which case it will fail the request and return an error. The default is 48,000.
        speakingRate:
          type: number
          format: double
          description: >-
            Speaking rate/speed, in the range [0.5, 1.5]. The default is 1.0,
            which is the normal native speed supported by the specific voice. We
            recommend using values above 0.8 to ensure high quality.
      description: Configurations to use when synthesizing speech.
    ttsv1SynthesisContext:
      type: object
      description: >-
        Context for the current synthesis request. Supplying the text of earlier
        requests from the same session or conversation gives the model
        additional context and can improve the quality of the generation,
        especially for short or ambiguous input text.
      properties:
        previousRequests:
          type: array
          description: >-
            Previous requests from the same session or conversation, in the
            order they were synthesized.
          items:
            type: object
            properties:
              text:
                type: string
                description: The text that was synthesized in the previous request.
    v1AudioConfigAudioEncoding:
      type: string
      enum:
        - LINEAR16
        - MP3
        - OGG_OPUS
        - ALAW
        - MULAW
        - FLAC
        - PCM
        - WAV
      default: MP3
      description: |-
        The desired output format of the synthesized audio. Defaults to `MP3`.
         - `LINEAR16`: Uncompressed 16-bit signed little-endian samples (Linear PCM). For non-streaming, the WAV header is included in the response. For streaming, the WAV header is included in every audio chunk.
         - `MP3`: MP3 audio.
         - `OGG_OPUS`: Opus encoded audio wrapped in an ogg container. The result will be a file which can be played natively on Android, and in browsers (at least Chrome and Firefox). The quality of the encoding is considerably higher than MP3 while using approximately the same bitrate.
         - `ALAW`: ALAW encoded audio. 8-bit companded PCM.
         - `MULAW`: MULAW encoded audio. 8-bit companded PCM.
         - `FLAC`: FLAC encoded audio. Lossless audio format.
         - `PCM`: PCM audio. Uncompressed 16-bit signed little-endian samples with no WAV header.
         - `WAV`: WAV audio. Uncompressed 16-bit signed little-endian samples. For non-streaming, the WAV header is included in the response. For streaming, the WAV header is included in the first audio chunk only.
  securitySchemes:
    inworld_basic:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Your [authentication](../../../api-reference/introduction) credentials.
        For Basic authentication, please populate `Basic $INWORLD_API_KEY`. You
        can create a key in one command with the [Inworld
        CLI](../../../tts/resources/inworld-cli): `inworld workspace add-key`.

````