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

# TTS in five minutes

> Generate your first Rime TTS audio clip in five minutes using cURL, Python, JavaScript, or TypeScript.

Generate a WAV file with one authenticated request to Rime's text-to-speech API. Choose a language tab, copy the complete script, and run it from your terminal.

## Prerequisites

You need:

* **A Rime API token:** Create a free [Rime account](https://app.rime.ai/signup/) and copy your API key from the [API Tokens](https://app.rime.ai/tokens/) page.
* A language runtime, depending on which tab you follow:
  * **cURL**: a terminal with cURL installed (included with macOS and most Linux distributions).
  * **Python**: [Python 3.10](https://www.python.org/downloads/release/python-3100/) or later.
  * **JavaScript**: [Node.js 18](https://nodejs.org/) or later.
  * **TypeScript**: Node.js 18+ plus [tsx](https://github.com/privatenumber/tsx) (`npm install -g tsx`).

Code blocks in this guide are tabbed. Pick cURL, Python, JavaScript, or TypeScript in each block to follow your preferred language.

<Info>
  These examples call Rime's HTTPS API with a standard library or built-in `fetch`. Rime does not publish an npm or PyPI SDK. Framework-specific starters are available for [Next.js](/docs/voice-agent-nextjs), [Vite](/docs/voice-agent-vite), [Express](/docs/voice-agent-express), [plain Node](/docs/voice-agent-node), and [FastAPI](/docs/voice-agent-fastapi).
</Info>

## Copy the request

Create a file called `rime_hello_world.py`, `rime_hello_world.js`, or `rime_hello_world.ts` (or run the cURL version directly in your terminal) and paste the full script:

<Accordion title="Full script (copy/paste)">
  <CodeGroup>
    ```bash cURL theme={null}
    curl --request POST \
      --url https://users.rime.ai/v1/rime-tts \
      --header 'Authorization: Bearer your_api_key_here' \
      --header 'Content-Type: application/json' \
      --header 'Accept: audio/wav' \
      --output output.wav \
      --data '{
        "text": "Hello! This is Rime speaking.",
        "speaker": "celeste",
        "modelId": "coda"
      }'
    ```

    ```python Python theme={null}
    import json
    import urllib.request

    RIME_API_KEY = "your_api_key_here"

    headers = {
        "Accept": "audio/wav",
        "Authorization": f"Bearer {RIME_API_KEY}",
        "Content-Type": "application/json"
    }

    payload = {
        "text": "Hello! This is Rime speaking.",
        "speaker": "celeste",
        "modelId": "coda"
    }

    data = json.dumps(payload).encode("utf-8")

    request = urllib.request.Request(
        "https://users.rime.ai/v1/rime-tts",
        data=data,
        headers=headers,
        method="POST"
    )

    with urllib.request.urlopen(request) as response:
        with open("output.wav", "wb") as f:
            while chunk := response.read(4096):
                f.write(chunk)

    print("Audio saved to output.wav")
    ```

    ```javascript JavaScript theme={null}
    const fs = require("fs");

    const RIME_API_KEY = "your_api_key_here";

    const headers = {
        "Accept": "audio/wav",
        "Authorization": `Bearer ${RIME_API_KEY}`,
        "Content-Type": "application/json"
    };

    const payload = {
        text: "Hello! This is Rime speaking.",
        speaker: "celeste",
        modelId: "coda"
    };

    async function generateSpeech() {
        const response = await fetch("https://users.rime.ai/v1/rime-tts", {
            method: "POST",
            headers: headers,
            body: JSON.stringify(payload)
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const buffer = await response.arrayBuffer();
        fs.writeFileSync("output.wav", Buffer.from(buffer));
        console.log("Audio saved to output.wav");
    }

    generateSpeech();
    ```

    ```typescript TypeScript theme={null}
    import * as fs from "fs";

    const RIME_API_KEY: string = "your_api_key_here";

    const headers: Record<string, string> = {
        "Accept": "audio/wav",
        "Authorization": `Bearer ${RIME_API_KEY}`,
        "Content-Type": "application/json"
    };

    const payload = {
        text: "Hello! This is Rime speaking.",
        speaker: "celeste",
        modelId: "coda"
    };

    async function generateSpeech(): Promise<void> {
        const response = await fetch("https://users.rime.ai/v1/rime-tts", {
            method: "POST",
            headers: headers,
            body: JSON.stringify(payload)
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const buffer = await response.arrayBuffer();
        fs.writeFileSync("output.wav", Buffer.from(buffer));
        console.log("Audio saved to output.wav");
    }

    generateSpeech();
    ```
  </CodeGroup>
</Accordion>

## Run it

The cURL tab runs the request directly. For Python, JavaScript, or TypeScript, run:

<CodeGroup>
  ```bash Python theme={null}
  python rime_hello_world.py
  ```

  ```bash JavaScript theme={null}
  node rime_hello_world.js
  ```

  ```bash TypeScript theme={null}
  npx tsx rime_hello_world.ts
  ```
</CodeGroup>

A successful request writes `output.wav` and prints:

```bash theme={null}
Audio saved to output.wav
```

<Accordion title="How the request works">
  ### Build the request step by step

  Create a file called `rime_hello_world.py`, `rime_hello_world.js`, or `rime_hello_world.ts` and import the required library modules:

  <CodeGroup>
    ```python Python theme={null}
    import json
    import urllib.request
    ```

    ```javascript JavaScript theme={null}
    const fs = require("fs");
    ```

    ```typescript TypeScript theme={null}
    import * as fs from "fs";
    ```
  </CodeGroup>

  Set the request headers with your Rime API key and the expected audio format:

  <CodeGroup>
    ```python Python theme={null}
    RIME_API_KEY = "your_api_key_here"

    headers = {
        "Accept": "audio/wav",
        "Authorization": f"Bearer {RIME_API_KEY}",
        "Content-Type": "application/json"
    }
    ```

    ```javascript JavaScript theme={null}
    const RIME_API_KEY = "your_api_key_here";

    const headers = {
        "Accept": "audio/wav",
        "Authorization": `Bearer ${RIME_API_KEY}`,
        "Content-Type": "application/json"
    };
    ```

    ```typescript TypeScript theme={null}
    const RIME_API_KEY: string = "your_api_key_here";

    const headers: Record<string, string> = {
        "Accept": "audio/wav",
        "Authorization": `Bearer ${RIME_API_KEY}`,
        "Content-Type": "application/json"
    };
    ```
  </CodeGroup>

  Set the text, speaker, and model in the request body:

  <CodeGroup>
    ```python Python theme={null}
    payload = {
        "text": "Hello! This is Rime speaking.",
        "speaker": "celeste",
        "modelId": "coda"
    }
    ```

    ```javascript JavaScript theme={null}
    const payload = {
        text: "Hello! This is Rime speaking.",
        speaker: "celeste",
        modelId: "coda"
    };
    ```

    ```typescript TypeScript theme={null}
    const payload = {
        text: "Hello! This is Rime speaking.",
        speaker: "celeste",
        modelId: "coda"
    };
    ```
  </CodeGroup>

  This payload includes the three required parameters:

  * `text` is the content to synthesize.
  * `speaker` selects a voice from the [voice catalog](/docs/voices).
  * `modelId` selects the model. Use `coda` for the flagship voice lineup or `mistv3` for the lowest time to first audio.

  The [Coda API reference](/api-reference/coda/http) lists the optional request parameters.

  Send the `POST` request and write the streamed audio response to a file:

  <CodeGroup>
    ```python Python theme={null}
    data = json.dumps(payload).encode("utf-8")

    request = urllib.request.Request(
        "https://users.rime.ai/v1/rime-tts",
        data=data,
        headers=headers,
        method="POST"
    )

    with urllib.request.urlopen(request) as response:
        with open("output.wav", "wb") as f:
            while chunk := response.read(4096):
                f.write(chunk)

    print("Audio saved to output.wav")
    ```

    ```javascript JavaScript theme={null}
    async function generateSpeech() {
        const response = await fetch("https://users.rime.ai/v1/rime-tts", {
            method: "POST",
            headers: headers,
            body: JSON.stringify(payload)
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const buffer = await response.arrayBuffer();
        fs.writeFileSync("output.wav", Buffer.from(buffer));
        console.log("Audio saved to output.wav");
    }

    generateSpeech();
    ```

    ```typescript TypeScript theme={null}
    async function generateSpeech(): Promise<void> {
        const response = await fetch("https://users.rime.ai/v1/rime-tts", {
            method: "POST",
            headers: headers,
            body: JSON.stringify(payload)
        });

        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }

        const buffer = await response.arrayBuffer();
        fs.writeFileSync("output.wav", Buffer.from(buffer));
        console.log("Audio saved to output.wav");
    }

    generateSpeech();
    ```
  </CodeGroup>

  These examples stream the response but write each chunk to disk. Interactive applications can play chunks as they arrive so speech begins before the complete response is generated. The [LiveKit quickstart](/docs/quickstart-livekit) shows this pattern in a conversational agent.
</Accordion>

## Choose a voice

Change the `speaker` parameter to use another voice:

<CodeGroup>
  ```python Python theme={null}
  payload = {
      "text": "Hello! This is Rime speaking.",
      "speaker": "orion",  # Try different voices here
      "modelId": "coda"
  }
  ```

  ```javascript JavaScript theme={null}
  const payload = {
      text: "Hello! This is Rime speaking.",
      speaker: "orion",  // Try different voices here
      modelId: "coda"
  };
  ```

  ```typescript TypeScript theme={null}
  const payload = {
      text: "Hello! This is Rime speaking.",
      speaker: "orion",  // Try different voices here
      modelId: "coda"
  };
  ```
</CodeGroup>

Browse all available voices on the [Voices](/docs/voices) page.

## Custom pronunciation

<Note>Custom pronunciation is supported on **Mist v1 and Mist v2** only. Coda, Arcana, and Mist v3 do not support [`phonemizeBetweenBrackets`](/docs/custom-pronunciation).</Note>

The `mistv2` model lets you specify the pronunciation of brand names or uncommon words using the [Rime phonetic alphabet](/platform/rime-phonetic-alphabet). Add the custom pronunciation in curly brackets and set [`phonemizeBetweenBrackets`](/docs/custom-pronunciation) to `true`:

<CodeGroup>
  ```python Python theme={null}
  payload = {
      "text": "Welcome to {r1Ym} labs.",
      "speaker": "peak",
      "modelId": "mistv2",
      "phonemizeBetweenBrackets": True
  }
  ```

  ```javascript JavaScript theme={null}
  const payload = {
      text: "Welcome to {r1Ym} labs.",
      speaker: "peak",
      modelId: "mistv2",
      phonemizeBetweenBrackets: true
  };
  ```

  ```typescript TypeScript theme={null}
  const payload = {
      text: "Welcome to {r1Ym} labs.",
      speaker: "peak",
      modelId: "mistv2",
      phonemizeBetweenBrackets: true
  };
  ```
</CodeGroup>

See the [Rime phonetic alphabet](/platform/rime-phonetic-alphabet) for the full symbol reference, and [Pronunciation control](/platform/pronunciation-control) for an overview of all the ways to control pronunciation.

## Production choices

The [LiveKit quickstart](/docs/quickstart-livekit) extends the same streaming API into a real-time voice agent. These references cover the main model, voice, latency, and transport decisions:

<Columns cols={2}>
  <Card title="Models" icon="microchip" href="/docs/models">
    Compare Coda (flagship) and Mist v3 (fast)
  </Card>

  <Card title="Voices" icon="waveform" href="/docs/voices">
    Browse all available voice options
  </Card>

  <Card title="Latency" icon="gauge-high" href="/docs/latency">
    Optimize for real-time performance
  </Card>

  <Card title="Coda Streaming API" icon="bolt" href="/api-reference/coda/http">
    Stream audio with our flagship model
  </Card>
</Columns>
