Transcription API
Send a voice message, a recording or a video file from your own code and get the transcript back as JSON, with the language detected and, if you ask, translated. The same engine as the website, for your apps, bots and scripts.
Quick start
- 1 Buy any credit package once.
- 2 Create an API key in Settings.
- 3 Send your first request with one of the examples below.
What it does
- Speech to text for audio and video files, with the spoken language detected for you.
- Translations into up to 5 languages in the same call.
- One synchronous request: you get the answer as soon as the transcript is ready, for a voice message usually within seconds.
- The same file sent again is answered from the stored transcript, without waiting for a second transcription.
Authentication
Every request carries a personal API key as a Bearer token in the Authorization header. Create one in Settings under API keys. It is shown once, so store it where your code can read it, and never in a browser or an app you ship. A key only works for the endpoints on this page.
API keys are for paying accounts: an account that has bought credits at least once, or a premium account.
Authorization: Bearer YOUR_API_KEY
Pricing
Paid from your credit balance, per started minute of audio, after the transcript is ready. A call that fails costs nothing.
Example: a 77 second voice message counts as 2 minutes, so 20 credits, or 30 credits with one translation.
Asking for the language the recording is already in is not a translation and costs nothing.
Sending the same file twice is charged twice, because you receive the transcript twice. To retry safely after a timeout, send an Idempotency-Key header: a key you already used returns the first answer and charges nothing.
Endpoints
POST /api/v1/transcriptions Create a transcription
A multipart upload. The response comes with status 201 once the transcript is ready.
curl -X POST https://audiocap.app/api/v1/transcriptions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Idempotency-Key: 6f1c2b7e-voice-0001" \
-F "file=@voice-message.ogg" \
-F "translate=de"
import { openAsBlob } from 'node:fs';
const form = new FormData();
form.append('file', await openAsBlob('voice-message.ogg'), 'voice-message.ogg');
form.append('translate', 'de');
const res = await fetch('https://audiocap.app/api/v1/transcriptions', {
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Idempotency-Key': '6f1c2b7e-voice-0001',
},
body: form,
});
console.log(await res.json());
import requests
res = requests.post(
"https://audiocap.app/api/v1/transcriptions",
headers={"Authorization": "Bearer YOUR_API_KEY", "Idempotency-Key": "6f1c2b7e-voice-0001"},
files={"file": open("voice-message.ogg", "rb")},
data={"translate": "de"},
)
print(res.json())
<?php
$client = new GuzzleHttp\Client();
$res = $client->request('POST', 'https://audiocap.app/api/v1/transcriptions', [
'headers' => [
'Authorization' => 'Bearer YOUR_API_KEY',
'Idempotency-Key' => '6f1c2b7e-voice-0001',
],
'multipart' => [
['name' => 'file', 'contents' => fopen('voice-message.ogg', 'r')],
['name' => 'translate', 'contents' => 'de'],
],
]);
echo $res->getBody();
{
"data": {
"id": 1234,
"slug": "k3v9q2m7x1ab",
"file": "voice-message.ogg",
"status": "completed",
"language": "en",
"seconds": 6.4000000000000003552713678800500929355621337890625,
"text": "Hi, it's me. I'm running ten minutes late, see you at the station.",
"error": null,
"translations": {
"de": "Hallo, ich bin es. Ich komme zehn Minuten später, wir sehen uns am Bahnhof."
}
},
"billing": {
"credits_charged": 15,
"minutes": 1,
"transcription": 10,
"translation": 5,
"translated_languages": [
"de"
],
"balance": 485,
"receipt_id": 42,
"replayed": false
}
}
GET /api/v1/transcriptions/{id} Fetch a transcription
Returns a transcription this account created or paid for, with every translation that already exists. Free, and it never starts a new translation.
curl https://audiocap.app/api/v1/transcriptions/1234 \
-H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch('https://audiocap.app/api/v1/transcriptions/1234', {
method: 'GET',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
},
});
console.log(await res.json());
import requests
res = requests.get(
"https://audiocap.app/api/v1/transcriptions/1234",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(res.json())
<?php
$client = new GuzzleHttp\Client();
$res = $client->request('GET', 'https://audiocap.app/api/v1/transcriptions/1234', [
'headers' => [
'Authorization' => 'Bearer YOUR_API_KEY',
],
]);
echo $res->getBody();
{
"data": {
"id": 1234,
"slug": "k3v9q2m7x1ab",
"file": "voice-message.ogg",
"status": "completed",
"language": "en",
"seconds": 6.4000000000000003552713678800500929355621337890625,
"text": "Hi, it's me. I'm running ten minutes late, see you at the station.",
"error": null,
"translations": {
"de": "Hallo, ich bin es. Ich komme zehn Minuten später, wir sehen uns am Bahnhof."
}
}
}
Errors
Every error answers with JSON that has a stable error code and a readable message.
{
"error": "payment_required",
"message": "Not enough credits for this file. Top up and send it again; it will not be transcribed twice.",
"reason": "insufficient_credits",
"balance": 5,
"cost": 20,
"credits_per_minute": 10,
"translation_per_minute": 5,
"buy_url": "https://audiocap.app/developers?buy=credits"
}
Limits
- Up to 100 MB per file
- 20 requests per minute and account
- Up to 5 translation languages per request
- Up to 120 minutes per file, 240 minutes on a premium account