Transcription API

POST an audio or video file, poll for the transcript. Whisper large-v3, 100+ languages, speaker labels, files up to 10 hours. Results as JSON, plain text, SRT or VTT.

Authentication

Every account has an API token — it's on your account page. Send it as a Bearer header on every request.

Create an account to get your token

1. Submit a file

POST https://transcribe.free/api/v1/transcribe/
Authorization: Bearer YOUR_API_TOKEN
Content-Type: multipart/form-data

file          the audio/video file          (required)
language      ISO code, or omit to auto-detect
diarization   "true" for speaker labels     (optional)
timestamps    "false" to skip segment times (optional)

Returns 202 with the job uuid. The job goes straight onto the priority queue — API jobs are never behind free web uploads.

{
  "ok": true,
  "uuid": "0f2c…",
  "status": "queued",
  "credits_used": 12,
  "status_url": "https://transcribe.free/api/v1/transcribe/0f2c…/"
}

2. Poll for the transcript

GET https://transcribe.free/api/v1/transcribe/<uuid>/?format=json
Authorization: Bearer YOUR_API_TOKEN

format is json (default, structured segments), txt, srt or vtt. Poll every few seconds until status is completed.

{
  "ok": true,
  "uuid": "0f2c…",
  "status": "completed",
  "duration_seconds": 742.5,
  "language": "en",
  "transcript": "Full text…",
  "segments": [
    {"start": 0.0, "end": 4.2, "text": "Welcome back.", "confidence": 0.98}
  ]
}

cURL

UUID=$(curl -s https://transcribe.free/api/v1/transcribe/ \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "file=@interview.mp3" \
  -F "language=en" \
  -F "diarization=true" | jq -r .uuid)

curl -s "https://transcribe.free/api/v1/transcribe/$UUID/?format=srt" \
  -H "Authorization: Bearer YOUR_API_TOKEN" | jq -r .transcript > interview.srt

Python

import time, requests

H = {"Authorization": "Bearer YOUR_API_TOKEN"}
API = "https://transcribe.free/api/v1/transcribe/"

job = requests.post(API, headers=H,
                    files={"file": open("interview.mp3", "rb")},
                    data={"language": "en", "diarization": "true"}).json()

while True:
    r = requests.get(API + job["uuid"] + "/", headers=H).json()
    if r["status"] in ("completed", "failed"):
        break
    time.sleep(5)

print(r["transcript"])

Node.js

const H = {Authorization: "Bearer YOUR_API_TOKEN"};
const API = "https://transcribe.free/api/v1/transcribe/";

const form = new FormData();
form.append("file", new Blob([await fs.readFile("interview.mp3")]), "interview.mp3");
form.append("language", "en");

const {uuid} = await (await fetch(API, {method: "POST", headers: H, body: form})).json();

let job;
do {
  await new Promise(r => setTimeout(r, 5000));
  job = await (await fetch(`${API}${uuid}/?format=vtt`, {headers: H})).json();
} while (job.status !== "completed" && job.status !== "failed");

console.log(job.transcript);

List your jobs

curl -s "https://transcribe.free/api/v1/transcriptions/?limit=20" \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Errors

Errors come back with ok:false and a code: unauthorized (401), missing_file / unsupported_format / file_too_large / file_too_long / bad_format (400), insufficient_credits (402), not_found (404), queue_failed (502). A job that fails after queueing reports status:failed with an error field, and its credits are refunded.

API pricing

The API bills exactly like the web app: 1 credit per minute of audio, rounded up. Pro ($10/month or $60/year) covers fair-use unlimited minutes and is the cheapest option for steady volume; credit packs start at $5 and never expire. There is no free API tier — the free daily allowance is web-only.

  • Files to 10 hours / 5 GB, priority queue, speaker labels
  • Whisper large-v3, 100+ languages, auto-detect
  • No per-request fee, no minimum, no expiry on packs
See pricing →