API documentation · Podcast endpoints
Podcast transcripts API endpoint
/api/v1/podcast-transcripts/
Cursor pagination · newest first
All requests go to https://subalytics.com/api/v1/ with your key in the
X-API-key header. Authentication,
pagination, date filters
and responses & errors apply to every endpoint.
By default returns transcript summaries without speakers or text, which are cheap to page through to find what's new. Add full=true to get the complete transcript.
Query parameters
| Parameter | Type | Description |
|---|---|---|
episode_sub_id | string | The transcript of one episode |
sub_id | string | Transcripts of one podcast |
full | string | true = include speakers and segments; anything else or omitted = summary only |
updated_from | date | Last changed on or after (use for sync) |
updated_to | date | Last changed on or before |
limit | int | Results per page (default 25, max 100). With full=true: default 10, max 10, since a full transcript can be 1–2 MB |
cursor | string | next_cursor from the previous page |
Response fields
| Field | Type | Description |
|---|---|---|
episode_sub_id | string | The episode this transcript belongs to |
podcast | object | {sub_id, podcast_name} |
episode | object | {episode_sub_id, episode_title, published_at, audio_url, link, image_url}, for convenience; the episodes endpoint is the source of truth. audio_url, link and image_url are always present, null when the feed has none. image_url is the episode's artwork, else the podcast's. audio_url is passed through from the feed as-is and may be a tracking or redirect URL |
language | string | null | Language detected from the audio, e.g. en (may differ from the podcast's declared language) |
duration_seconds | number | null | Measured audio length |
speakers_identified | boolean | false = speaker names haven't been identified (yet); labels still work, names are null |
created_at | date | When the transcript was first produced |
updated_at | date | Last change (re-transcription or speakers identified) |
speakers | object | full=true only. Speaker label → {name, role, title, company} |
segments | array | full=true only. {start, end, text, speaker} in order; start/end in seconds from the start of the audio |
Speakers
Each segment's speaker (e.g. SPEAKER_00) is a key into speakers. Labels are per transcript: SPEAKER_00 in one episode is unrelated to SPEAKER_00 in another. Identification is automatic and best-effort: any of name, role, title and company may be null. role is the speaker's part in the conversation (host, co-host, guest, …). A segment's speaker may be missing where speakers couldn't be separated.
A transcript can change after it is first published, for example when speaker names are filled in later. Its updated_at changes, so an updated_from sync picks it up again.
Example: one full transcript
GET /api/v1/podcast-transcripts/?episode_sub_id=c41f7a09e2b85d13&full=true
{
"success": true,
"results": [
{
"episode_sub_id": "c41f7a09e2b85d13",
"podcast": {
"sub_id": "a1b2c3d4e5",
"podcast_name": "Example Business Show"
},
"episode": {
"episode_sub_id": "c41f7a09e2b85d13",
"episode_title": "Rate Cuts, Robotaxis and the Week in Markets",
"published_at": "2026-09-24T16:38:09Z",
"audio_url": "https://media.example.com/c41f7a09e2b85d13.mp3",
"link": "https://podcasts.example.com/episodes/c41f7a09e2b85d13",
"image_url": "https://images.example.com/c41f7a09e2b85d13.jpg"
},
"language": "en",
"duration_seconds": 6875.2,
"speakers_identified": true,
"speakers": {
"SPEAKER_00": { "name": "Jane Host", "role": "host", "title": "journalist", "company": "Example Media" },
"SPEAKER_01": { "name": "Sam Guest", "role": "guest", "title": "economist", "company": null }
},
"segments": [
{ "start": 1.0, "end": 9.72, "text": "Welcome back to the show. Big week in markets.", "speaker": "SPEAKER_00" },
{ "start": 10.1, "end": 17.4, "text": "It really was. Let's start with the rate decision.", "speaker": "SPEAKER_01" }
],
"created_at": "2026-09-25T06:12:47Z",
"updated_at": "2026-09-27T05:48:31Z"
}
],
"returned_results": 1,
"limit": 10,
"next_cursor": null
}
Without full=true, each result has the same fields except speakers and segments.
This page as Markdown: /docs/podcast-transcripts.md.
All docs in one file: /llms-full.txt.