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

# Transcriptions API

> Turn speech into text, with segment and word timestamps

`POST https://api.pinference.ai/api/v1/audio/transcriptions` transcribes an audio file and returns its text, and optionally its segments and words with timestamps. Prime Inference serves six [speech-to-text models](https://docs.primeintellect.ai/inference/models/speech-to-text). They don't take Chat Completions requests.

```bash theme={null}
export PRIME_API_KEY="your-api-key"

curl https://api.pinference.ai/api/v1/audio/transcriptions \
  -H "Authorization: Bearer $PRIME_API_KEY" \
  -F model=qwen/qwen3-asr-1.7b \
  -F file=@meeting.wav
```

```json theme={null}
{
  "text": "The quick brown fox jumps over the lazy dog. Prime inference transcribes this clip.",
  "usage": {"type": "duration", "seconds": 4.86925}
}
```

The same request in Python, sending the audio as base64 in JSON:

```python theme={null}
import base64
import os
import requests

with open("meeting.wav", "rb") as f:
    audio = base64.b64encode(f.read()).decode()

response = requests.post(
    "https://api.pinference.ai/api/v1/audio/transcriptions",
    headers={"Authorization": f"Bearer {os.environ['PRIME_API_KEY']}"},
    json={
        "model": "qwen/qwen3-asr-1.7b",
        "input_audio": {"data": audio, "format": "wav"},
    },
    timeout=600,
)
response.raise_for_status()
print(response.json()["text"])
```

To charge a team, add `-H "X-Prime-Team-ID: your-team-id"` to each request. See [team billing](https://docs.primeintellect.ai/inference/overview.md#team-billing).

## Send the audio

A request carries its audio in exactly one of three ways:

| How | Request | Limit |
| - | - | - |
| Upload | `multipart/form-data` with a `file` field, as OpenAI's API takes it | 23 MiB of audio |
| Base64 in JSON | `input_audio: {"data": "<base64>", "format": "wav"}`, as OpenRouter's API takes it | 23 MiB of audio before encoding |
| URL | `audio_url`, a JSON field or a form field | 512 MiB, downloaded within 2 minutes |

Prime Inference downloads an `audio_url` itself, so the file must be reachable from the public internet over `http` or `https`. A signed URL from your storage provider works. URLs to private or internal addresses are refused, and the URL can be at most 2,048 characters. Prime Inference doesn't log audio URLs or transcripts.

Accepted formats are WAV, MP3, FLAC, Ogg (including Opus), AAC, M4A, AIFF, CAF, AMR, AU and WMA, and the audio track of MP4, MOV, MKV, WebM, AVI and 3GP video. With an upload, the file name's extension names the format. With base64, set `input_audio.format`.

### Long audio

Files up to several hours long are supported. Two hours of audio is usually 30 to 115 MB, more than an upload holds, so send long files by `audio_url`. A transcription runs for at most 10 minutes. As a guide, two hours of audio takes Qwen3-ASR 1.7B about 4 minutes, so set your client's timeout to 10 minutes for long files.

Long files need a direct request to Prime Inference. OpenRouter stops waiting for a transcription after 60 seconds and sends audio only as base64.

## Request fields

| Field | Type | Description |
| - | - | - |
| `model` | string | A [speech-to-text model ID](https://docs.primeintellect.ai/inference/models/speech-to-text), such as `qwen/qwen3-asr-1.7b`. |
| `file` | file | Multipart only. The audio file. |
| `input_audio` | object | JSON only. `data` is the audio as base64. `format` is optional and names the format, such as `wav` or `mp3`. |
| `audio_url` | string | The audio's `http` or `https` URL, in place of `file` or `input_audio`. |
| `response_format` | string | Optional. `json` (the default) returns the text. `verbose_json` adds the language, the duration and timestamped segments. |
| `timestamp_granularities` | array | Optional, with `verbose_json`. Add `word` to return word timestamps as well as segments. In a multipart request, send `timestamp_granularities[]` once per value. |
| `language` | string | Optional. The spoken language as an ISO-639 code, such as `en` or `pt`. Without it, the model detects the language. Parakeet models ignore it. |
| `temperature` | number | Optional, from 0 to 1. Parakeet models ignore it. |

## Response

With `response_format: "json"`:

| Field | Description |
| - | - |
| `text` | The transcript. |
| `usage.seconds` | The audio's duration in seconds, which the request is billed for. `usage.type` is `duration`. |

With `response_format: "verbose_json"` and `timestamp_granularities: ["segment", "word"]`:

```json theme={null}
{
  "task": "transcribe",
  "language": "en",
  "duration": 4.86925,
  "text": "The quick brown fox jumps over the lazy dog. Prime inference transcribes this clip.",
  "segments": [
    {"id": 0, "start": 0, "end": 4.8, "text": "The quick brown fox jumps over the lazy dog. Prime inference transcribes this clip."}
  ],
  "words": [
    {"word": "The", "start": 0, "end": 0.08},
    {"word": "quick", "start": 0.08, "end": 0.32},
    {"word": "brown", "start": 0.4, "end": 0.72}
  ],
  "usage": {"type": "duration", "seconds": 4.86925}
}
```

`words` is shortened here. `start` and `end` are in seconds from the start of the audio. `language` is the detected or requested language, and is `null` for models that don't report one. How a transcript splits into segments depends on the model. Each response also has an `X-Inference-Id` header; share it with support to trace a request.

## Usage and billing

Transcription is billed per second of audio, `usage.seconds`, at the price in the [model catalog](https://app.primeintellect.ai/dashboard/inference?tab=models). There is no charge for the text returned.

## Errors

Most errors return an `error` object with `message`, `type` and `code`, as the [Chat Completions API](https://docs.primeintellect.ai/api-reference/inference-chat-completions.md) does. A 401, a 404, or a 503 while authentication is unavailable returns a `detail` message instead.

| Status | Cause |
| - | - |
| 400 | The request breaks a rule above. The message names the rule, as in `Invalid transcription request (response_format).` The rules are `audio_sources` (more than one of `file`, `input_audio` and `audio_url`), `no_audio`, `audio_url`, `response_format`, `timestamp_granularities`, `language` and `temperature`. `Invalid transcription request (audio).` means the model couldn't read the audio, or Qwen3-ASR couldn't place word timestamps for its language; retry without word timestamps. `Invalid transcription request (audio_url).` with a valid URL means the file couldn't be downloaded or read. |
| 401 | The API key is missing or invalid. |
| 402 | The billed account has insufficient funds. See [troubleshooting](https://docs.primeintellect.ai/inference/troubleshooting.md). |
| 404 | The request didn't name a speech-to-text model. A misspelled model ID returns a `detail` of `Not Found`. |
| 413 | The uploaded or base64 audio is larger than 23 MiB. Send it by `audio_url` instead. |
| 429 | The model has no free capacity. Retry after the number of seconds in the `Retry-After` header. |
| 502 or 503 | The model failed to answer. Retry the request. |

## Compatibility

A multipart request takes the same fields as [OpenAI's transcription API](https://platform.openai.com/docs/api-reference/audio/createTranscription), so an OpenAI client works after you change its base URL and API key. A JSON request takes the `input_audio` shape that OpenRouter sends. `audio_url` is specific to Prime Inference. `response_format` takes `json` and `verbose_json` only.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.