API at a glance
The whole API on one screen: what it does, one request, one response, and every parameter.
Convert podcasts, videos and audio files to text over HTTP. Post the link a human would paste and get back a transcript with speaker labels and word-level timings.
- Speaker diarization: distinct speakers detected and labelled, on by default.
- Over 100 languages, auto-detected. Pass a hint only when you want to override it.
- One field for every source. No separate endpoint per platform, and no scraping on your side.
- Six output formats from the same transcript (JSON, TXT, SRT, VTT, DOCX, PDF) at no extra cost.
- One credit per minute of audio. Creator is $14 a month for 5 hours; a YouTube video with captions costs nothing at all.
API usage
You need an API key. Create one at your dashboard, then send it as a bearer token. There is no SDK to install.
API response
Creating a job answers immediately with an id. Transcription is asynchronous, so nothing here waits on the audio.
Then read it back. Without include=text you get metadata and a 500-character preview; with it, the whole body.
Branch on status, never on the status code. Create always answers 202, even when the work is already finished: a YouTube video with captions is read inline and comes back "status": "completed". That is a property of the video, not of your request.
API parameters
POST https://podcaststotext.com/api/v1/transcriptions takes the following:
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The thing to transcribe: a Spotify or Apple Podcasts episode link, a YouTube or TikTok URL, or a direct audio file. Required unless you send audio_url. |
audio_url | string | No | A direct audio file you have already resolved yourself. Skips resolution entirely. |
language | string | No | ISO code such as en or de. Omitted means autodetect, which is right almost always. |
speaker_labels | boolean | No | Detect and label distinct speakers. Defaults to true. Paid plans only. |
title | string | No | Overrides the title resolved from the platform. |
duration_seconds | number | No | Only with a direct audio_url, where the file would otherwise be probed for its length. |
And on the way back out, GET /api/v1/transcriptions/{id} takes include=text for the full body, or format= for a file:
| `format` | Content-Type | Timings | Needs a paid-plan transcript |
|---|---|---|---|
json | application/json | Yes | Yes |
txt | text/plain | No | No |
srt | application/x-subrip | Yes | Yes |
vtt | text/vtt | Yes | Yes |
docx | OOXML | Where present | No |
pdf | application/pdf | Where present | No |
json is the richest shape: segments with start, end, text and speaker. The last column is about the transcript, not your plan today: free-tier transcripts are stored without timings, so a time-coded export of one stays impossible after you upgrade.
Three things that are not standard
| What it means for your client | |
|---|---|
Every error carries how_to_fix | A concrete next action, not just a code. An automated client that reads it stops retrying calls that can never succeed. |
RateLimit-* headers on success | Pace on RateLimit-Remaining rather than waiting to be refused. A client that first learns its limit at the 429 is the retry storm the limit exists to stop. |
next_actions on success | The legal next call, in the response. An agent learns the flow without re-reading these docs mid-task. |
Where next
The machine-readable spec is at `/api/v1/openapi.json` — point a generator at it instead of writing a client.