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

# Use the API directly

export const AudioPlayer = ({src, title = "Audio", description, autoPlay = false, loop = false, variant = "default"}) => {
  const audioId = useId();
  const isCompact = variant === "compact";
  const audioRef = useRef(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const togglePlayback = () => {
    const audio = audioRef.current;
    if (!audio) return;
    if (audio.paused) {
      void audio.play();
      setIsPlaying(true);
      return;
    }
    audio.pause();
    setIsPlaying(false);
  };
  const handleSeek = event => {
    const audio = audioRef.current;
    if (!audio) return;
    const next = Number(event.target.value);
    audio.currentTime = next;
    setCurrentTime(next);
  };
  const formatTime = seconds => {
    if (!Number.isFinite(seconds)) return "0:00";
    const total = Math.floor(seconds);
    const mins = Math.floor(total / 60);
    const secs = total % 60;
    return `${mins}:${secs < 10 ? "0" : ""}${secs}`;
  };
  const progress = duration > 0 ? currentTime / duration * 100 : 0;
  return <div className={`audio-player ${isCompact ? "compact" : ""}`}>
      {!isCompact && <div className="meta">
          <div className="titles">
            <div className="title">{title}</div>
            {description && <div className="description">{description}</div>}
          </div>

          <a className="download" href={src} download>
            Download
          </a>
        </div>}

      {isCompact ? <>
          <button type="button" className="compact-button" onClick={togglePlayback} aria-label={isPlaying ? "Pause audio sample" : "Play audio sample"}>
            <span className="compact-icon" aria-hidden="true">
              {isPlaying ? "❚❚" : "▶"}
            </span>
          </button>
          <audio id={audioId} ref={audioRef} preload="metadata" loop={loop} autoPlay={autoPlay} aria-label={title} src={src} onEnded={() => setIsPlaying(false)}>
            Your browser does not support the audio element.
          </audio>
        </> : <>
          <div className="controls">
            <button type="button" className="play-button" onClick={togglePlayback} aria-label={isPlaying ? "Pause" : "Play"}>
              {isPlaying ? <svg viewBox="0 0 24 24" width="15" height="15" fill="currentColor" aria-hidden="true">
                  <path d="M6 5h4v14H6zM14 5h4v14h-4z" />
                </svg> : <svg viewBox="0 0 24 24" width="15" height="15" fill="currentColor" aria-hidden="true">
                  <path d="M8 5v14l11-7z" />
                </svg>}
            </button>

            <span className="time">{formatTime(currentTime)}</span>

            <input type="range" className="scrubber" min="0" max={duration || 0} step="0.01" value={currentTime} onChange={handleSeek} aria-label="Seek" style={{
    "--progress": `${progress}%`
  }} />

            <span className="time">{formatTime(duration)}</span>
          </div>

          <audio id={audioId} ref={audioRef} preload="metadata" loop={loop} autoPlay={autoPlay} aria-label={title} src={src} onLoadedMetadata={event => setDuration(event.currentTarget.duration)} onTimeUpdate={event => setCurrentTime(event.currentTarget.currentTime)} onEnded={() => setIsPlaying(false)}>
            Your browser does not support the audio element.
          </audio>
        </>}
    </div>;
};

Call the Text to Speech and Speech to Text APIs from your application. You do
not need to build an agent first.

The first HTTP example creates an audio file. The second returns a transcript.
For streaming, see [Stream in real time](#stream-in-real-time).

## Before you begin

Set `SLNG_API_KEY` in your environment. If you need a key, follow
[Create your API key](/guides/get-started/quickstart#create-your-api-key).
If you already have one, see
[Store and use your key](/guides/get-started/quickstart#store-and-use-your-key).

The model requests below go to `https://eu-west.slng.ai.ai` and send your key as a
bearer token.

## Synthesize speech

Text to speech takes some text and a voice and returns audio. Pick the model in
the request path and pass the text in the body. This example uses the Deepgram
Aura model, where you choose the voice with the `model` parameter in the body.
The endpoint returns binary audio, so write the response straight to a file.

<Tabs>
  <Tab title="curl" icon="terminal">
    ```bash theme={null}
    curl https://eu-west.slng.ai.ai/v1/tts/slng/deepgram/aura:2-en \
      -H "Authorization: Bearer $SLNG_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "aura-2-thalia-en",
        "text": "Hello from sunny Barcelona!"
      }' \
      --output hello.wav
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```js theme={null}
    const response = await fetch(
      "https://eu-west.slng.ai.ai/v1/tts/slng/deepgram/aura:2-en",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.SLNG_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          model: "aura-2-thalia-en",
          text: "Hello from sunny Barcelona!",
        }),
      },
    );

    const audioData = await response.arrayBuffer();
    // Play or save audioData
    ```
  </Tab>

  <Tab title="SDK" icon="package">
    The [`voiceai-sdk`](https://www.npmjs.com/package/voiceai-sdk) client reads
    `SLNG_API_KEY` from the environment and handles the endpoint for you.

    ```bash theme={null}
    npm install voiceai-sdk
    ```

    ```ts theme={null}
    import { writeFile } from "node:fs/promises";
    import Slng from "voiceai-sdk";

    const client = new Slng();

    const response = await client.textToSpeech.create("slng/deepgram/aura:2-en", {
      text: "Hello from sunny Barcelona!",
      voice: "aura-2-thalia-en",
    });

    await writeFile("hello.wav", Buffer.from(await response.arrayBuffer()));
    ```
  </Tab>

  <Tab title="Python" icon="python">
    ```python theme={null}
    import os
    import requests

    url = "https://eu-west.slng.ai.ai/v1/tts/slng/deepgram/aura:2-en"
    headers = {
        "Authorization": f"Bearer {os.environ['SLNG_API_KEY']}",
        "Content-Type": "application/json",
    }
    data = {
        "model": "aura-2-thalia-en",
        "text": "Hello from sunny Barcelona!",
    }

    response = requests.post(url, headers=headers, json=data)
    with open("hello.wav", "wb") as f:
        f.write(response.content)
    ```
  </Tab>

  <Tab title="CLI" icon="square-terminal">
    The [`voiceai`](https://www.npmjs.com/package/voiceai-cli) CLI wraps the same
    API. Run `voiceai login` once to store your key.

    ```bash theme={null}
    npm install -g voiceai-cli
    voiceai login
    voiceai tts "Hello from sunny Barcelona!" --out hello.wav
    ```
  </Tab>
</Tabs>

The call above produces this audio:

<AudioPlayer src="/audio/hello.wav" title="Hello from sunny Barcelona!" />

## Transcribe audio

Speech to text takes an audio file and returns the transcript. Send the file as
multipart form data and read the text from the first alternative. The examples
below transcribe this sample:

<AudioPlayer src="/audio/micro-machines.wav" title="Micro Machines sample" description="Download this file to use with the STT examples below." />

<Tabs>
  <Tab title="curl" icon="terminal">
    ```bash theme={null}
    curl https://eu-west.slng.ai.ai/v1/stt/slng/deepgram/nova:3-en \
      -H "Authorization: Bearer $SLNG_API_KEY" \
      -F "audio=@micro-machines.wav"
    ```
  </Tab>

  <Tab title="JavaScript" icon="js">
    ```js theme={null}
    const formData = new FormData();
    formData.append("audio", audioFile); // File from <input type="file">

    const response = await fetch(
      "https://eu-west.slng.ai.ai/v1/stt/slng/deepgram/nova:3-en",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.SLNG_API_KEY}`,
        },
        body: formData,
      },
    );

    const result = await response.json();
    console.log(result.results.channels[0].alternatives[0].transcript);
    ```
  </Tab>

  <Tab title="SDK" icon="package">
    The [`voiceai-sdk`](https://www.npmjs.com/package/voiceai-sdk) client takes a
    file stream and returns the transcript directly.

    ```ts theme={null}
    import fs from "node:fs";
    import Slng from "voiceai-sdk";

    const client = new Slng();

    const transcript = await client.speechToText.create("slng/deepgram/nova:3-en", {
      audio: fs.createReadStream("micro-machines.wav"),
    });

    console.log(transcript.alternatives[0]?.transcript);
    ```
  </Tab>

  <Tab title="Python" icon="python">
    ```python theme={null}
    import os
    import requests

    url = "https://eu-west.slng.ai.ai/v1/stt/slng/deepgram/nova:3-en"
    headers = {"Authorization": f"Bearer {os.environ['SLNG_API_KEY']}"}

    with open("micro-machines.wav", "rb") as audio_file:
        response = requests.post(url, headers=headers, files={"audio": audio_file})

    result = response.json()
    print(result["results"]["channels"][0]["alternatives"][0]["transcript"])
    ```
  </Tab>

  <Tab title="CLI" icon="square-terminal">
    ```bash theme={null}
    voiceai stt micro-machines.wav
    ```
  </Tab>
</Tabs>

The transcript comes back under
`results.channels[0].alternatives[0].transcript`.

## Change the model or parameters

The model is part of the request path. Swap it to change the voice engine or the
language, and keep the rest of the call the same. Prefer a variant under the
`slng/` prefix where one exists: those run on SLNG infrastructure in the region
closest to you, so each call skips the hop to an outside provider.

Each model has its own endpoint and its own parameters, so the field that picks
the voice differs by provider. Deepgram Aura uses `model`, Rime Arcana uses
`speaker`.

```bash highlight={2,7,9} theme={null}
# Rime Arcana instead of Deepgram Aura
curl https://eu-west.slng.ai.ai/v1/tts/slng/fish/tts:s2.1-pro \
  -H "Authorization: Bearer $SLNG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hello from sunny Barcelona!",
    "reference_id": "16cabdb7f8d240569aff36c9e480d783"
  }' \
  --output hello-arcana.wav
```

For speech to text, add optional fields to the form to tune the transcript:

* **`language`** sets the recognition language.
* **`diarize=true`** labels each speaker.
* **`punctuate=true`** adds punctuation.

See [WebSockets vs HTTP](/guides/models/websockets-vs-http) for request and
response formats, and the [Unified API guide](/guides/models/unified-api)
for more details.

## Stream in real time

For low-latency, turn-by-turn audio, connect over WebSocket at
`wss://eu-west.slng.ai.ai` instead of posting a whole file.

* [Text to speech over WebSocket](/api-reference/text-to-speech/overview)
* [Speech to text over WebSocket](/api-reference/speech-to-text/overview)
* [WebSockets vs HTTP](/guides/models/websockets-vs-http)

## Find other models and API details

* [Which models are available](/guides/models/which-models-are-available) and
  the [model catalog](/models/catalog/all-models), including views by
  [region](/models/catalog/by-region) and
  [language](/models/catalog/by-language).
* [Text to speech API](/api-reference/text-to-speech/overview) and
  [speech to text API](/api-reference/speech-to-text/overview).
* [Authentication](/api-reference/authentication),
  [rate limits](/api-reference/rate-limits), and
  [error codes](/api-reference/error-codes).

## Next steps

* Ready to build a full voice agent instead? See
  [create an agent](/guides/get-started/create-a-project/create-agent).
* Already run an agent elsewhere? See
  [improve an existing agent](/guides/get-started/create-a-project/improve-agent).
