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

# Speech-to-text

> Transcribe audio files with one HTTP call.

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
POST https://gateway.llm-stats.com/v1/stt/transcribe
```

Upload an audio file as multipart form data, get a JSON transcript back.

## Quickstart

<CodeGroup>
  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests

  with open("audio.mp3", "rb") as f:
      response = requests.post(
          "https://gateway.llm-stats.com/v1/stt/transcribe",
          headers={"Authorization": "Bearer YOUR_API_KEY"},
          files={"audio": f},
          data={"model_id": "whisper-1"},
      )

  print(response.json()["text"])
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const formData = new FormData();
  formData.append("audio", audioFile);
  formData.append("model_id", "whisper-1");

  const response = await fetch(
    "https://gateway.llm-stats.com/v1/stt/transcribe",
    {
      method: "POST",
      headers: { Authorization: "Bearer YOUR_API_KEY" },
      body: formData,
    },
  );

  const result = await response.json();
  console.log(result.text);
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl https://gateway.llm-stats.com/v1/stt/transcribe \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -F "audio=@audio.mp3" \
    -F "model_id=whisper-1"
  ```
</CodeGroup>

## Request

The body is `multipart/form-data` with the following fields:

<ParamField body="audio" type="file" required>
  Audio file. Up to 25 MB. Supported formats: `wav`, `mp3`, `m4a`, `mp4`,
  `webm`, `ogg`, `opus`, `flac`.
</ParamField>

<ParamField body="model_id" type="string" required>
  STT model ID (e.g. `whisper-1`, `deepgram-nova-3`).
</ParamField>

<ParamField body="language" type="string">
  ISO-639 language hint (e.g. `"en"`, `"es"`). Skips auto-detection where
  supported.
</ParamField>

<ParamField body="provider_id" type="string">
  Force a specific provider for this request. Bypasses the router — use
  sparingly, only when you need parity with a baseline.
</ParamField>

## Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "text": "Hello, this is a test transcription.",
  "duration": 2.45,
  "language": "en",
  "confidence": 0.97,
  "words": [
    { "word": "Hello", "start": 0.00, "end": 0.42, "confidence": 0.98 },
    { "word": "this",  "start": 0.55, "end": 0.74, "confidence": 0.97 }
  ],
  "model": "whisper-1"
}
```

<ResponseField name="text" type="string">
  Full transcript.
</ResponseField>

<ResponseField name="duration" type="number">
  Audio duration in seconds.
</ResponseField>

<ResponseField name="language" type="string | null">
  Detected (or supplied) language code.
</ResponseField>

<ResponseField name="confidence" type="number | null">
  Overall confidence between 0 and 1, when the provider exposes it.
</ResponseField>

<ResponseField name="words" type="array | null">
  Per-word timestamps and confidences, when the provider supports them.
</ResponseField>

## Streaming

For real-time transcription, open a WebSocket to
`wss://gateway.llm-stats.com/v1/stt/stream` and stream PCM audio frames. The
batch HTTP endpoint above is the right choice for files you already have on
disk.

## Errors

Failures use the [shared error envelope](/gateway/errors). Common ones:

| Status | `error.code`           | When                                           |
| ------ | ---------------------- | ---------------------------------------------- |
| `400`  | `invalid_input`        | Missing fields, unsupported format.            |
| `401`  | `unauthenticated`      | Missing or invalid API key.                    |
| `402`  | `insufficient_quota`   | Out of credit.                                 |
| `413`  | `invalid_input`        | File larger than 25 MB.                        |
| `429`  | `rate_limited`         | Quota exceeded — back off using `Retry-After`. |
| `502`  | `provider_unavailable` | Every STT provider for this model errored.     |
