Get a YouTube video transcript
Returns the caption track YouTube already holds for one of the connected channel's own videos, as plain text plus timed cues. Use it instead of downloading and transcribing the video yourself.
Auto-generated (ASR) tracks are included: YouTube serves them to the channel owner, which is what the connected account is. Uploaded tracks win over auto-generated ones when both exist for a language.
Caching: downloading a transcript costs 200 of the 10,000 daily YouTube Data API quota units your integration shares with publishing, so the body is stored on first read and served from there afterwards. source tells you which happened. Pass refresh=true only when the captions changed on YouTube. A cached read still costs 51 units (it re-checks the video and lists the tracks), so store the transcript on your side rather than polling this endpoint.
Notes:
- Only videos owned by this connected channel. Anything else returns 404.
contentDetails.captionin YouTube's own API readsfalseon videos that DO have a serving auto-generated track, so it is not a usable availability signal. Call this endpoint and handle the 404.- YouTube generates auto-captions only for videos with recognisable speech, and can take a few hours after upload to publish them.
API key authentication - use your Zernio API key as a Bearer token
In: header
Path Parameters
The connected YouTube account.
Query Parameters
The YouTube video id (the platformPostId on a synced external post).
BCP-47 language tag as YouTube labels the track. en also matches an en-GB track. Omit to take the best available track.
json returns timed cues; srt returns the raw SubRip body instead. text is present either way.
"json""json" | "srt"Re-download from YouTube instead of serving the stored copy. Spends 200 quota units.
falseResponse Body
application/json
application/json
application/json
application/json
import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.connect.getYoutubeCaptions({ path: { accountId: 'account_abc123', }, query: { videoId: 'video_abc123', },});console.log(data);{
"accountId": "68a1f2c3d4e5f6a7b8c9d0e1",
"videoId": "sdw1FML60tM",
"language": "en",
"trackId": "AUieDaanCEjmJQdL7wfZbe1QDQTbseX-hToYw99pmOJitlJz868",
"trackKind": "asr",
"source": "cache",
"fetchedAt": "2026-08-27T21:09:54.000Z",
"text": "Hey, this is Mickey. I'm the founder of this portfolio of three websites which are mainly monetized via AdSense.",
"cues": [
{
"start": 1.6,
"end": 8.88,
"text": "Hey, this is Mickey. I'm the founder of"
},
{
"start": 5.04,
"end": 12.8,
"text": "this portfolio of three websites"
}
],
"availableTracks": [
{
"trackId": "AUieDaanCEjmJQdL7wfZbe1QDQTbseX-hToYw99pmOJitlJz868",
"language": "en",
"trackKind": "asr",
"name": ""
}
]
}{
"error": "string",
"type": "invalid_request_error",
"code": "string",
"param": "string",
"platform": "string",
"platformError": {},
"details": {}
}{
"error": "Unauthorized"
}{
"error": "This video has no caption tracks. YouTube generates them only for videos with recognisable speech, and it can take a few hours after upload.",
"type": "not_found",
"code": "captions_not_found",
"param": "videoId"
}Get Shopify OAuth connect URL GET
Initiate the Shopify OAuth flow for a store. Shopify is a connect-only platform: the connected account does not publish social posts, it powers the Blogs API (`/v1/accounts/{accountId}/blogs`). Returns an `authUrl` to redirect the merchant to; after they approve the install, Shopify redirects their browser to Zernio's callback, the account is created on the profile (platform `shopify`), and the browser is redirected to `redirect_url` (or the Zernio dashboard when omitted). Requested scopes are `read_content` and `write_content` (content only; no customer or order data). Connecting the same profile to a store again refreshes the stored token in place.
List posts GET
Returns a paginated list of posts. Published posts include platformPostUrl with the public URL on each platform.