> 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 audio

POST https://api.milliseconds.ai/v1/rakeaudio/transcribe
Content-Type: audio/*

Send one audio file as the raw request body. Any format ffmpeg decodes works (mp3, m4a, wav, ogg, opus, flac, webm). The call is synchronous and returns the whole transcript, with word timestamps and, when `diarize` is true, speaker labels. One call takes up to 60 minutes of audio. Price: $0.12 per audio hour with diarization, $0.10 without, per second rounded up. The response carries `x-input-tokens` (input tokens billed) and `x-inference-ms`.

Reference: https://docs.milliseconds.ai/api/rakeaudio/post-v-1-rakeaudio-transcribe

## Authentication

- `Authorization` header (bearer token, required) — A milliseconds API key, test\_sk-\{namespace}-\{entropy} or prod\_sk-\{namespace}-\{entropy}. Every /v1 route requires it.

## Request

### Query parameters

- `diarize` (boolean, optional, default: false) — Label speakers (SPEAKER_00 to SPEAKER_03). Default false. Send true for speaker labels, at the higher price.

### Body (audio/*)

This endpoint expects binary data of type audio/*.

- Binary request body.

## Response

### 200

The transcript

- `language` (any, required) — Always null: the model does not report a language code.
- `segments` (list of TranscriptSegmentsItems, required)
- `duration` (double, required) — Audio duration in seconds. Billing uses it.
- `text` (string, required) — The segment texts joined with spaces.

## Errors

### 400 Bad Request Error

invalid_audio, audio_too_long or invalid_request

- `error` (ErrorError, required)

### 415 Unsupported Media Type Error

The content type is not audio/* or application/octet-stream

- `error` (ErrorError, required)

### 502 Bad Gateway Error

Inference failed twice

- `error` (ErrorError, required)

### 503 Service Unavailable Error

The model is not available. Retry later.

- `error` (ErrorError, required)

## Types

### TranscriptSegmentsItems

- `start` (double, required)
- `end` (double, required)
- `text` (string, required)
- `words` (list of TranscriptSegmentsItemsWordsItems, required)
- `speaker` (string, optional) — The majority speaker of the segment. Only with diarize=true.

### ErrorError

- `code` (string, required)
- `message` (string, required)

### TranscriptSegmentsItemsWordsItems

- `word` (string, required)
- `start` (double, required) — Seconds from the start of the file.
- `end` (double, required)
- `speaker` (string, optional) — SPEAKER_00 to SPEAKER_03. Only with diarize=true.

## Examples

**Response**

```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."
}
```

**SDK Code**

```python rakeaudio_postV1RakeaudioTranscribe_example
import requests

url = "https://api.milliseconds.ai/v1/rakeaudio/transcribe"

headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "audio/*"
}

response = requests.post(url, headers=headers)

print(response.json())
```

```javascript rakeaudio_postV1RakeaudioTranscribe_example
const url = 'https://api.milliseconds.ai/v1/rakeaudio/transcribe';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'audio/*'}
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go rakeaudio_postV1RakeaudioTranscribe_example
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.milliseconds.ai/v1/rakeaudio/transcribe"

	req, _ := http.NewRequest("POST", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "audio/*")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby rakeaudio_postV1RakeaudioTranscribe_example
require 'uri'
require 'net/http'

url = URI("https://api.milliseconds.ai/v1/rakeaudio/transcribe")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'audio/*'

response = http.request(request)
puts response.read_body
```

```java rakeaudio_postV1RakeaudioTranscribe_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.milliseconds.ai/v1/rakeaudio/transcribe")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "audio/*")
  .asString();
```

```php rakeaudio_postV1RakeaudioTranscribe_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.milliseconds.ai/v1/rakeaudio/transcribe', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'audio/*',
  ],
]);

echo $response->getBody();
```

```csharp rakeaudio_postV1RakeaudioTranscribe_example
using RestSharp;

var client = new RestClient("https://api.milliseconds.ai/v1/rakeaudio/transcribe");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "audio/*");
IRestResponse response = client.Execute(request);
```

```swift rakeaudio_postV1RakeaudioTranscribe_example
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "audio/*"
]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.milliseconds.ai/v1/rakeaudio/transcribe")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```