API reference
Endpoint reference
A dedicated endpoint per source, fetch one video, list a channel, playlist, or search, and batch up to 50 transcripts in a single call. All requests and responses are JSON, and every authenticated endpoint expects a bearer token.
POST/api/v1/transcripts/videoidempotent
Returns a transcript - text plus timestamped segments. Accepts YouTube, TikTok, and Instagram URLs (or a bare TikTok video id), direct media file URLs, and podcast links (Spotify, Apple Podcasts, or an RSS feed), which resolve to the episode's audio automatically and come back with a podcast block naming the show and episode. Podcast transcriptions include best-effort speaker diarization: each segment carries a `speaker` integer (0, 1, ...) identifying who is talking, and a top-level `diarized: true` marks transcripts where labels were produced. Speaker ids are hints from voice separation, not named identification, and non-podcast sources never carry them. When no captions exist the audio is transcribed automatically: for media under 20 minutes the request simply waits and returns the finished transcript, so no polling is needed. Longer media, or a transcription still running after 45 seconds, returns 202 with a job to poll instead - the work continues either way, so the same request is safe to retry and will hit the cache once it finishes. Supply callback_url to have the finished transcript POSTed to you instead of polling. Every failure carries an ai_fallback block saying whether captions were definitively unavailable and whether retrying would work.
Body parameters
videostringrequired
A video URL or 11-character YouTube video ID. Accepts YouTube (watch, youtu.be, /shorts/), TikTok, and Instagram URLs, plus direct media file URLs (mp4/mp3/wav/…). Also accepts podcast links: a Spotify or Apple Podcasts episode URL, or a podcast RSS feed URL, which is resolved to that episode's audio automatically. Videos without captions fall back to AI transcription.
mode"captions" | "audio" | "auto"optional
Where the text may come from. "captions" reads an existing caption track and fails if there is none, which is the only way to guarantee a synchronous answer. "audio" skips captions and transcribes the audio. "auto" (the default) tries captions first and transcribes the audio when there are none. Anything that transcribes audio returns 202 with a job to poll, and is charged only on delivery.
timestampsbooleanoptional
Which form the transcript comes back in. true (the default) returns the `segments` array, each with start, duration and text (podcast episodes transcribed from audio may also carry a `speaker` id per segment - see the podcast notes). false returns a single joined `text` string instead. Exactly one of the two is present, never both, since segments already contain every word the joined text does. The older strings "segment" and "none" mean the same two things and are still accepted.
callback_urlstring (https URL)optional
Where to POST the finished transcript when a request escalates to audio transcription, instead of polling the job. The body is the same envelope the poll URL returns, signed with HMAC-SHA256 over the exact bytes in an X-TranscriptFetch-Signature: sha256=<hex> header so you can verify it came from us. Must be a public https URL on the standard port. The job stays pollable either way, so a missed delivery is never a lost transcript.
ai_fallbackbooleanoptional
Legacy alias for "mode", still supported. true is identical to "mode": "audio"; omitted or false is "mode": "auto". Send one or the other, not both. Note that false never disabled the fallback - audio was still transcribed when no captions existed - which is why the field was replaced.
Example request
Response
{
"ok": true,
"request_id": "req_…",
"data": {
"kind": "transcript",
"video_id": "dQw4w9WgXcQ",
"platform": "youtube",
"title": "Example video",
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/mqdefault.jpg",
"segments": [
{
"start": 0,
"duration": 3.5,
"text": "We're no strangers to love"
}
]
},
"usage": {
"credits_spent": 1,
"balance": 99,
"bytes": 14233
}
}POST/api/v1/transcripts/channelidempotent
Resolve a channel into a paginated list of videos (metadata only), newest first. Pass since_video_id to get back only the uploads newer than one you've already seen - a page with nothing new is free, which makes this safe to poll on a schedule.
Body parameters
channelstringrequired
Channel @handle, /channel/UC… URL, or UC… ID.
limitinteger (1–50)optional
Max videos to return per page. Defaults to 5.
cursorstringoptional
Opaque pagination cursor from a previous response's next_cursor. Omit for the first page.
since_video_idstringoptional
Newest video ID you have already seen. The response is trimmed to videos newer than it, and a page with nothing newer costs no credits - so you can poll a channel for new uploads for free.
Example request
Response
{
"ok": true,
"request_id": "req_…",
"data": {
"kind": "video_list",
"source": "channel_videos",
"videos": [
{
"videoId": "dQw4w9WgXcQ",
"title": "Example video",
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/mqdefault.jpg",
"duration": 212,
"channel": "Example Channel"
}
],
"next_cursor": "eyJvIjoxMH0"
},
"usage": {
"credits_spent": 1,
"balance": 98,
"bytes": 0
}
}POST/api/v1/transcripts/playlistidempotent
Resolve a playlist into a paginated list of videos (metadata only).
Body parameters
playliststringrequired
Playlist URL or playlist ID.
limitinteger (1–50)optional
Max videos to return per page. Defaults to 5.
cursorstringoptional
Opaque pagination cursor from a previous response's next_cursor. Omit for the first page.
Example request
Response
{
"ok": true,
"request_id": "req_…",
"data": {
"kind": "video_list",
"source": "playlist",
"videos": [
{
"videoId": "dQw4w9WgXcQ",
"title": "Example video",
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/mqdefault.jpg",
"duration": 212,
"channel": "Example Channel"
}
],
"next_cursor": "eyJvIjoxMH0"
},
"usage": {
"credits_spent": 1,
"balance": 98,
"bytes": 0
}
}POST/api/v1/transcripts/searchidempotent
Resolve a keyword search into a paginated list of videos (metadata only).
Body parameters
querystringrequired
Keyword search query.
limitinteger (1–50)optional
Max videos to return per page. Defaults to 5.
cursorstringoptional
Opaque pagination cursor from a previous response's next_cursor. Omit for the first page.
Example request
Response
{
"ok": true,
"request_id": "req_…",
"data": {
"kind": "video_list",
"source": "search",
"videos": [
{
"videoId": "dQw4w9WgXcQ",
"title": "Example video",
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/mqdefault.jpg",
"duration": 212,
"channel": "Example Channel"
}
],
"next_cursor": "eyJvIjoxMH0"
},
"usage": {
"credits_spent": 1,
"balance": 98,
"bytes": 0
}
}GET/api/v1/transcripts/jobs/{jobId}
Returns the state of a transcription job created when a request escalated to audio. Always 200: read the status field, which is "processing" while the job is running, "completed" with the transcript in data, or "failed" with an error. The job_id and a ready-to-use poll_url come back in the 202 that started it. Free to poll on our side - credits are charged once, on delivery. NOTE for RapidAPI subscribers: every poll is still a billable request on your Hub plan, so prefer callback_url, or simply re-send the original request once the job has had time to finish (the result is cached, so it returns instantly and costs one credit, not two). Most transcriptions never reach this endpoint at all: media under 20 minutes is returned synchronously.
Body parameters
No request body, this endpoint takes no parameters.
Example request
Response
{
"ok": true,
"request_id": "req_01HZY4T7Q2",
"status": "completed",
"job_id": "asr_01HZY4T7Q2",
"data": {
"kind": "transcript",
"video_id": "dQw4w9WgXcQ",
"platform": "youtube",
"title": "Example video",
"thumbnailUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/mqdefault.jpg",
"segments": [
{
"start": 0,
"duration": 3.5,
"text": "We're no strangers to love"
}
]
},
"usage": {
"credits_spent": 1,
"balance": 942,
"bytes": 18244
}
}POST/api/v1/transcripts/batchidempotent
Fetch up to 50 transcripts concurrently. Accepts the same inputs as /transcripts/video - YouTube, TikTok and Instagram URLs as well as bare YouTube IDs. Charges 1 credit per successfully fetched transcript; failed or blocked videos are free.
Body parameters
video_idsstring[] (1–50)required
Video URLs or bare YouTube IDs, from any supported platform. Also accepted as the legacy key videoIds (send one or the other, not both).
Example request
Response
{
"ok": true,
"request_id": "req_…",
"data": {
"kind": "transcript_batch",
"results": [
{
"video_id": "dQw4w9WgXcQ",
"outcome": "ok",
"title": "Example video",
"text": "Full transcript text …",
"segments": [
{
"start": 0,
"duration": 3.5,
"text": "Full transcript …"
}
],
"cached": true,
"bytes": 14233
},
{
"video_id": "9bZkp7q19f0",
"outcome": "no_transcript",
"title": null,
"text": null,
"segments": null,
"cached": false,
"bytes": 0
}
]
},
"usage": {
"credits_spent": 1,
"balance": 97
}
}GET/api/v1/me
Validates the API key and returns the account's remaining credit balance. Free - never billed. Useful for programmatic balance checks and as a credential test in integrations.
Body parameters
No request body, this endpoint takes no parameters.
Example request
Response
{
"ok": true,
"request_id": "req_…",
"data": {
"kind": "me",
"user_id": "user_…",
"credits": 250
},
"usage": {
"credits_spent": 0,
"balance": 250,
"bytes": 0
}
}GET/api/v1/healthno auth
Public liveness probe for uptime monitoring. Returns 200 whenever the API is serving. No authentication required and no credits used.
Body parameters
No request body, this endpoint takes no parameters.
Example request
Response
{
"status": "ok",
"service": "transcriptfetch-api",
"version": "1.0.0",
"time": "2026-06-16T00: 00: 00.000Z"
}