> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.milliseconds.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.milliseconds.ai/_mcp/server.

# Transcribe

## The request

```
POST https://api.milliseconds.ai/v1/rakeaudio/transcribe?diarize=true
```

| Part              | Value                                                                                                     |
| ----------------- | --------------------------------------------------------------------------------------------------------- |
| Body              | The audio file bytes, unchanged. Not JSON, not base64, not a URL                                          |
| `Content-Type`    | `audio/*` (for example `audio/mpeg`, `audio/wav`, `audio/mp4`, `audio/ogg`) or `application/octet-stream` |
| `Authorization`   | `Bearer test_sk-...` or `Bearer prod_sk-...`. See [Authentication](/authentication)                       |
| `diarize` (query) | `false` (default) returns the transcript without speakers. `true` labels speakers, at the higher price    |

The API decodes every common audio format: mp3, m4a, wav, ogg, opus, flac and webm. You do not need to convert the file.

**`curl`**

```bash title="curl"
curl -X POST "https://api.milliseconds.ai/v1/rakeaudio/transcribe?diarize=true" \
  -H "authorization: Bearer test_sk-..." \
  -H "Content-Type: audio/wav" \
  --data-binary @call.wav
```

**`Python`**

```python title="Python"
import requests

with open("call.wav", "rb") as audio:
    response = requests.post(
        "https://api.milliseconds.ai/v1/rakeaudio/transcribe",
        params={"diarize": "true"},
        headers={"authorization": "Bearer test_sk-...", "Content-Type": "audio/wav"},
        data=audio,
        timeout=300,
    )
response.raise_for_status()
transcript = response.json()

for segment in transcript["segments"]:
    print(segment.get("speaker"), segment["start"], segment["text"])
```

**`TypeScript`**

```typescript title="TypeScript"
import { readFile } from "node:fs/promises";

const response = await fetch(
  "https://api.milliseconds.ai/v1/rakeaudio/transcribe?diarize=true",
  {
    method: "POST",
    headers: { authorization: "Bearer test_sk-...", "Content-Type": "audio/wav" },
    body: await readFile("call.wav"),
    signal: AbortSignal.timeout(300_000),
  },
);

if (!response.ok) throw new Error(`HTTP ${response.status}`);
const transcript = await response.json();

for (const segment of transcript.segments) {
  console.log(segment.speaker, segment.start, segment.text);
}
```

The SDKs cover `decision-machine-1` only. Call `rakeaudio` with any HTTP client, as above.

## The response

This is a real response to a 19-second support call with two speakers. The word lists are cut short.

```json
{
  "language": null,
  "segments": [
    {
      "start": 0,
      "end": 2.4,
      "text": "Hello, thanks for calling support.",
      "words": [
        { "word": "Hello,", "start": 0, "end": 0.72, "speaker": "SPEAKER_00" },
        { "word": "thanks", "start": 0.72, "end": 1.04, "speaker": "SPEAKER_00" },
        { "word": "for", "start": 1.04, "end": 1.2, "speaker": "SPEAKER_00" }
      ],
      "speaker": "SPEAKER_00"
    },
    {
      "start": 4,
      "end": 10.24,
      "text": "Hi, my invoice for September shows two charges of $49, and I only have one account.",
      "words": [
        { "word": "Hi,", "start": 4, "end": 4.56, "speaker": "SPEAKER_01" },
        { "word": "my", "start": 4.56, "end": 4.8, "speaker": "SPEAKER_01" }
      ],
      "speaker": "SPEAKER_01"
    }
  ],
  "duration": 19.0075,
  "text": "Hello, thanks for calling support. How can I help you today? Hi, my invoice for September shows two charges of $49, and I only have one account. I see the duplicate charge. I will refund one of them now. You should see it in three to five business days. Great. Thank you very much for your help."
}
```

The full response held eight segments. The agent spoke as `SPEAKER_00` and the customer as `SPEAKER_01`.

| Field                     | Meaning                                                            |
| ------------------------- | ------------------------------------------------------------------ |
| `text`                    | The whole transcript: the segment texts joined with spaces         |
| `segments[]`              | Sentence-like parts of the transcript, in time order               |
| `segments[].start`, `end` | Seconds from the start of the file                                 |
| `segments[].speaker`      | The speaker who says most of the segment. Only with `diarize=true` |
| `segments[].words[]`      | Every word of the segment, with `word`, `start` and `end`          |
| `words[].speaker`         | The speaker of the word. Only with `diarize=true`                  |
| `duration`                | The audio duration in seconds. Billing uses it                     |
| `language`                | Always `null`                                                      |

With `diarize=false`, the response has the same shape without any `speaker` field.

> **Note**
>
> Speaker labels are per call. `SPEAKER_00` is the first voice in this file. It does not identify a person across files.

## Response headers

| Header           | Meaning                                                                |
| ---------------- | ---------------------------------------------------------------------- |
| `x-input-tokens` | The input tokens billed for this call. The example above billed 15,840 |
| `x-inference-ms` | The model processing time in milliseconds. The example above took 282  |

## Next

* [Limits and errors](/rakeaudio/limits-and-errors)
* [Pricing](/rakeaudio/pricing)
* [API Reference](/api)