Videos & Shorts
Publish a video or a Short to YouTube, add it to a playlist, schedule it, edit a published video, and every platformSpecificData field.
A plain post becomes a public video. Its title is the first line of content, and its description is the whole of content.
YouTube classifies it as a Short on its own when it is 3 minutes or shorter and vertical.
Video
Long-form content: longer than 3 minutes or horizontal.
16:9 is the recommended aspect ratio. A thumbnail on the media item sets the custom cover.
import Zernio from '@zernio/node';
const zernio = new Zernio();
const { data: published } = await zernio.posts.createPost({
body: {
content: 'In this tutorial, I walk through building a REST API from scratch.\n\n#programming #tutorial',
tags: ['rest api', 'node.js', 'backend tutorial'],
mediaItems: [{
type: 'video',
url: 'https://cdn.example.com/long-form-video.mp4',
thumbnail: 'https://cdn.example.com/thumbnail.jpg'
}],
platforms: [{
platform: 'youtube',
accountId: '66b2e19d8c3f5a7e9d0b1c2d',
platformSpecificData: {
title: 'Build a REST API from scratch',
visibility: 'public',
categoryId: '27',
madeForKids: false
}
}],
publishNow: true
}
});
console.log(published.post.platforms[0].platformPostUrl);Response (201):
{
"post": {
"_id": "65f1c0a9e2b5af0012ab34cd",
"status": "published",
"platforms": [
{
"platform": "youtube",
"status": "published",
"platformPostUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
]
}
}tags sits at the top level of the request, alongside content. It reaches YouTube as snippet.tags on the upload.
Zernio cleans the list before upload:
- Strips a leading
#. - Splits a comma-joined entry into separate tags.
- Drops duplicates.
- Keeps tags in order until the combined length would pass 500 characters.
A single tag longer than 100 characters is skipped.
Every sample below changes only the platforms entry of this request.
Shorts
YouTube detects Shorts on its own: a video that is 3 minutes or shorter and vertical (9:16) is classified as a Short.
There is no post type or flag to set. The request is the one above with a short vertical video.
Videos under 15 seconds loop automatically. Custom thumbnails are not supported for Shorts through the API.
Playlists
Create a playlist with POST /v1/accounts/{accountId}/youtube-playlists (Create YouTube playlist).
Only title is required. privacy defaults to private and also accepts public or unlisted.
const { data: created } = await zernio.connect.createYoutubePlaylist({
path: { accountId: '66b2e19d8c3f5a7e9d0b1c2d' },
body: { title: 'Tutorials', description: 'Step-by-step video tutorials', privacy: 'private' }
});
console.log(created.playlist.id);Response (201):
{
"playlist": {
"id": "PLxxxxxxxxxxxxx",
"title": "Tutorials",
"description": "Step-by-step video tutorials",
"privacy": "private",
"itemCount": 0,
"thumbnailUrl": ""
}
}Creation costs 50 YouTube quota units and requires the youtube or youtube.force-ssl OAuth scope.
The playlist starts empty and does not become the account's default. Use the returned playlist.id in platformSpecificData.playlistId when publishing a video.
Playlist creation is not idempotent. Repeating a request can create another playlist, including after a timeout. Zernio does not automatically retry creation; list the channel's playlists before retrying an ambiguous failure.
Official series. YouTube's public API does not expose the official series setting. After creating a playlist, enable Set as official series for this playlist manually in YouTube's desktop playlist settings.
See YouTube's series playlist requirements.
playlistId adds the video to an existing playlist after upload, for immediate and scheduled uploads alike. Without it, the video is uploaded normally.
List the channel's playlists with GET /v1/accounts/{accountId}/youtube-playlists (List YouTube playlists):
const { data: playlists } = await zernio.connect.getYoutubePlaylists({
path: { accountId: '66b2e19d8c3f5a7e9d0b1c2d' }
});
console.log(playlists.playlists);Response (200):
{
"playlists": [
{
"id": "PLxxxxxxxxxxxxx",
"title": "Tutorials",
"privacy": "public",
"itemCount": 12
}
],
"defaultPlaylistId": null
}Then pass the id when creating the post:
{
"platform": "youtube",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"platformSpecificData": {
"title": "Build a REST API from scratch",
"visibility": "public",
"playlistId": "PLxxxxxxxxxxxxx"
}
}Default playlist. PUT /v1/accounts/{accountId}/youtube-playlists (Set default YouTube playlist) stores a default playlist on the account to prefill your own UI.
It does not apply to posts that omit playlistId:
const { data: saved } = await zernio.connect.updateYoutubeDefaultPlaylist({
path: { accountId: '66b2e19d8c3f5a7e9d0b1c2d' },
body: { defaultPlaylistId: 'PLxxxxxxxxxxxxx', defaultPlaylistName: 'Tutorials' }
});
console.log(saved.success);Response (200):
{ "success": true }Scheduling
A post with scheduledFor in the future runs in this order:
- Zernio uploads the video ahead of its scheduled time, so YouTube has finished processing it before the video goes live.
- A video targeting
"public"goes up as"private"and carries YouTube's ownpublishAt, so YouTube releases it at the scheduled second. A video targeting"private"or"unlisted"is uploaded with that visibility and never changes. - A video URL exists as soon as the upload finishes, but the video is not publicly accessible before the release.
firstCommentis posted at the scheduled time, not at upload time.
{
"platform": "youtube",
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"scheduledFor": "2027-01-01T12:00:00",
"platformSpecificData": {
"title": "Build a REST API from scratch",
"visibility": "public",
"firstComment": "Chapters and source code are in the description."
}
}Set timezone on the request so the scheduled time is read in the right zone; see post lifecycle.
Edit a published video
Edit post replaces the video description only.
There is no time window and no limit on the number of edits. The video id does not change, so the video keeps its URL.
The title is left exactly as it was, including when it was derived from the first line of content at publish time.
Title, tags, thumbnail and visibility changes go through Update post metadata. It also works on videos uploaded outside Zernio when you pass videoId and accountId with _ as the post id.
const { data: edited } = await zernio.posts.editPost({
path: { postId: '65f1c0a9e2b5af0012ab34cd' },
body: {
platform: 'youtube',
content: 'Updated description with corrected chapter timestamps.'
}
});
console.log(edited.url);Response (200):
{
"success": true,
"id": "dQw4w9WgXcQ",
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"message": "youtube post edited successfully"
}The new description is sanitized before it is written:
- angle brackets (
<and>) are stripped - anything past 5,000 characters is truncated
Neither one fails the call. A request that hits either rule still returns success with the video id and URL.
Several channels. If the post was published to several YouTube channels, pass accountId to pick which copy to edit. Without it, the first youtube entry on the post is edited.
Platform fields
All fields go in platformSpecificData on the YouTube entry.
| Field | Type | Default | Description |
|---|---|---|---|
title | string | First line of content, or "Untitled Video" | Video title, at most 100 characters. |
visibility | "public" | "private" | "unlisted" | "public" | Who can see the video. |
madeForKids | boolean | false | Marks the video as child-directed for COPPA. true permanently disables comments, the notification bell, personalized ads, end screens and cards on the video. YouTube may block views when the flag is never set. |
containsSyntheticMedia | boolean | false | Discloses that the video contains synthetic content that could be mistaken for real. YouTube may add a label to the video. |
categoryId | string | "22" (People & Blogs) | Video category. Common values: "1" Film, "10" Music, "20" Gaming, "22" People & Blogs, "27" Education, "28" Science & Technology. |
playlistId | string | Playlist to add the video to after upload. See Playlists. | |
firstComment | string | Posted and pinned as the first comment, at most 10,000 characters. Posted immediately with publishNow, at the scheduled time otherwise. |