Skip to content

YouTube API

Schedule and automate YouTube video uploads with Zernio API - Videos, Shorts, thumbnails, visibility, and COPPA settings

Quick Reference

PropertyValue
Title limit100 characters
Description limit5,000 characters
Tags limit500 characters total (all tags combined)
Videos per post1
Video formatsMP4, MOV, AVI, WMV, FLV, 3GP, WebM
Video max size256 GB
Video max duration15 min (unverified), 12 hours (verified)
Thumbnail formatsJPEG, PNG, GIF
Thumbnail max size2 MB
Post typesVideo, Shorts
SchedulingYes (uploads as private, goes public at scheduled time)
Inbox (Comments)Yes
Inbox (DMs)No (YouTube has no DM system)
AnalyticsYes

Before You Start

YouTube is video-only. Every post requires exactly one video file. Unverified channels are limited to 15-minute videos -- verify your channel via phone number to unlock longer uploads. If a YouTube channel is suspended, ALL uploads fail with a 403 error. Use the account health endpoint to check status before scheduling posts.

  • One video per post (no image-only or text-only posts)
  • Unverified channels have a 15-minute maximum video duration
  • YouTube has daily upload quotas that vary by channel
  • Shorts are auto-detected from duration and aspect ratio (not a separate post type)

Quick Start

Upload a video to YouTube:

typescript
const { post } = await zernio.posts.createPost({
  content: 'Video description here',
  mediaItems: [
    { type: 'video', url: 'https://example.com/video.mp4' }
  ],
  platforms: [{
    platform: 'youtube',
    accountId: 'YOUR_ACCOUNT_ID',
    platformSpecificData: {
      title: 'My Video Title',
      visibility: 'public'
    }
  }],
  publishNow: true
});
python
result = client.posts.create_post(
    content="Video description here",
    media_items=[
        {"type": "video", "url": "https://example.com/video.mp4"}
    ],
    platforms=[{
        "platform": "youtube",
        "accountId": "YOUR_ACCOUNT_ID",
        "platformSpecificData": {
            "title": "My Video Title",
            "visibility": "public"
        }
    }],
    publish_now=True
)
bash
curl -X POST https://zernio.com/api/v1/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Video description here",
    "mediaItems": [
      {"type": "video", "url": "https://example.com/video.mp4"}
    ],
    "platforms": [{
      "platform": "youtube",
      "accountId": "YOUR_ACCOUNT_ID",
      "platformSpecificData": {
        "title": "My Video Title",
        "visibility": "public"
      }
    }],
    "publishNow": true
  }'

Content Types

Regular Videos

Long-form content with a duration greater than 3 minutes or a horizontal aspect ratio. Regular videos support custom thumbnails and 16:9 is the recommended aspect ratio.

typescript
const { post } = await zernio.posts.createPost({
  content: 'In this tutorial, I walk through building a REST API from scratch.\n\n#programming #tutorial',
  mediaItems: [{
    type: 'video',
    url: 'https://example.com/long-form-video.mp4',
    thumbnail: 'https://example.com/thumbnail.jpg'
  }],
  platforms: [{
    platform: 'youtube',
    accountId: 'YOUR_ACCOUNT_ID',
    platformSpecificData: {
      title: 'Build a REST API from Scratch',
      visibility: 'public',
      categoryId: '27',
      madeForKids: false
    }
  }],
  publishNow: true
});
python
result = client.posts.create_post(
    content="In this tutorial, I walk through building a REST API from scratch.\n\n#programming #tutorial",
    media_items=[{
        "type": "video",
        "url": "https://example.com/long-form-video.mp4",
        "thumbnail": "https://example.com/thumbnail.jpg"
    }],
    platforms=[{
        "platform": "youtube",
        "accountId": "YOUR_ACCOUNT_ID",
        "platformSpecificData": {
            "title": "Build a REST API from Scratch",
            "visibility": "public",
            "categoryId": "27",
            "madeForKids": False
        }
    }],
    publish_now=True
)
bash
curl -X POST https://zernio.com/api/v1/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "In this tutorial, I walk through building a REST API from scratch.\n\n#programming #tutorial",
    "mediaItems": [{
      "type": "video",
      "url": "https://example.com/long-form-video.mp4",
      "thumbnail": "https://example.com/thumbnail.jpg"
    }],
    "platforms": [{
      "platform": "youtube",
      "accountId": "YOUR_ACCOUNT_ID",
      "platformSpecificData": {
        "title": "Build a REST API from Scratch",
        "visibility": "public",
        "categoryId": "27",
        "madeForKids": false
      }
    }],
    "publishNow": true
  }'

YouTube Shorts

YouTube automatically detects Shorts based on duration and aspect ratio. A video that is 3 minutes or shorter AND has a vertical (9:16) aspect ratio is classified as a Short. There is no separate post type or flag to set -- just upload a short vertical video and YouTube handles the rest.

  • Videos under 15 seconds loop automatically
  • Custom thumbnails are not supported for Shorts via the API
  • No code changes are needed compared to regular videos; the detection is entirely automatic

Media Requirements

Video Requirements

PropertyShortsRegular Video
Max Duration3 minutes12 hours (verified), 15 min (unverified)
Min Duration1 second1 second
Max File Size256 GB256 GB
FormatsMP4, MOV, AVI, WMV, FLV, 3GP, WebMMP4, MOV, AVI, WMV, FLV, 3GP, WebM
Aspect Ratio9:16 (vertical)16:9 (horizontal)
Resolution1080 x 1920 px1920 x 1080 px (1080p)
PropertyShortsRegular Video
Resolution1080 x 1920 px3840 x 2160 px (4K)
Frame Rate30 fps24-60 fps
CodecH.264H.264 or H.265
AudioAAC, 128 kbpsAAC, 384 kbps
Bitrate10 Mbps35-68 Mbps (4K)

Custom Thumbnails

Custom thumbnails are supported for regular videos only (not Shorts).

PropertyRequirement
FormatJPEG, PNG, GIF
Max Size2 MB
Recommended Resolution1280 x 720 px (16:9)
Min Width640 px
typescript
const { post } = await zernio.posts.createPost({
  content: 'My Video Description',
  mediaItems: [{
    type: 'video',
    url: 'https://example.com/video.mp4',
    thumbnail: 'https://example.com/thumbnail.jpg'
  }],
  platforms: [{
    platform: 'youtube',
    accountId: 'YOUR_ACCOUNT_ID',
    platformSpecificData: {
      title: 'My Video Title',
      visibility: 'public'
    }
  }],
  publishNow: true
});
python
result = client.posts.create_post(
    content="My Video Description",
    media_items=[{
        "type": "video",
        "url": "https://example.com/video.mp4",
        "thumbnail": "https://example.com/thumbnail.jpg"
    }],
    platforms=[{
        "platform": "youtube",
        "accountId": "YOUR_ACCOUNT_ID",
        "platformSpecificData": {
            "title": "My Video Title",
            "visibility": "public"
        }
    }],
    publish_now=True
)
bash
curl -X POST https://zernio.com/api/v1/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "My Video Description",
    "mediaItems": [{
      "type": "video",
      "url": "https://example.com/video.mp4",
      "thumbnail": "https://example.com/thumbnail.jpg"
    }],
    "platforms": [{
      "platform": "youtube",
      "accountId": "YOUR_ACCOUNT_ID",
      "platformSpecificData": {
        "title": "My Video Title",
        "visibility": "public"
      }
    }],
    "publishNow": true
  }'

Platform-Specific Fields

FieldTypeDefaultDescription
titlestringFirst line of content, or "Untitled Video"Video title. Maximum 100 characters.
visibility"public" | "private" | "unlisted""public"Controls who can see the video.
madeForKidsbooleanfalseCOPPA compliance flag. Setting to true permanently disables comments, notification bell, personalized ads, end screens, and cards on the video. COPPA violations carry fines of $42,000 or more.
containsSyntheticMediabooleanfalseAI-generated content disclosure. YouTube is increasingly enforcing this requirement.
categoryIdstring"22" (People & Blogs)Video category. Common values: "1" Film, "10" Music, "20" Gaming, "22" People & Blogs, "27" Education, "28" Science & Technology.
playlistIdstring--Optional YouTube playlist ID to add the video to after upload (e.g. "PLxxxxxxxxxxxxx"). Use GET /v1/accounts/{accountId}/youtube-playlists to list available playlists.
firstCommentstring--Auto-posted and pinned comment. Maximum 10,000 characters. For publishNow: posted immediately. For scheduled posts: posted when the video goes live.

YouTube Playlists

Use playlists to automatically add an uploaded video to a specific YouTube playlist.

> Note: playlistId is optional. If omitted, the video is uploaded normally and is not added to any playlist.

1) List available playlists

Fetch playlists for a connected YouTube account to get a playlistId.

bash
curl "https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/youtube-playlists" \
  -H "Authorization: Bearer YOUR_API_KEY"
typescript
const result = await zernio.request({
  method: 'GET',
  path: `/v1/accounts/${accountId}/youtube-playlists`
});

console.log(result.playlists);
python
result = client.request(
    method="GET",
    path=f"/v1/accounts/{account_id}/youtube-playlists"
)

print(result["playlists"])

2) Create a post with playlistId

bash
curl -X POST https://zernio.com/api/v1/posts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Video description here",
    "mediaItems": [
      {"type": "video", "url": "https://example.com/video.mp4"}
    ],
    "platforms": [{
      "platform": "youtube",
      "accountId": "YOUR_ACCOUNT_ID",
      "platformSpecificData": {
        "title": "My Video Title",
        "visibility": "public",
        "playlistId": "PLxxxxxxxxxxxxx"
      }
    }],
    "publishNow": true
  }'
typescript
const { post } = await zernio.posts.createPost({
  content: 'Video description here',
  mediaItems: [
    { type: 'video', url: 'https://example.com/video.mp4' }
  ],
  platforms: [{
    platform: 'youtube',
    accountId: 'YOUR_ACCOUNT_ID',
    platformSpecificData: {
      title: 'My Video Title',
      visibility: 'public',
      playlistId: 'PLxxxxxxxxxxxxx'
    }
  }],
  publishNow: true
});
python
result = client.posts.create_post(
    content="Video description here",
    media_items=[
        {"type": "video", "url": "https://example.com/video.mp4"}
    ],
    platforms=[{
        "platform": "youtube",
        "accountId": "YOUR_ACCOUNT_ID",
        "platformSpecificData": {
            "title": "My Video Title",
            "visibility": "public",
            "playlistId": "PLxxxxxxxxxxxxx"
        }
    }],
    publish_now=True
)

3) (Optional) Store a default playlist (client-side convenience)

You can store a default playlist for an account to prefill UI selections. This does not automatically apply to posts that omit playlistId.

bash
curl -X PUT https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/youtube-playlists \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "defaultPlaylistId": "PLxxxxxxxxxxxxx",
    "defaultPlaylistName": "Tutorials"
  }'
typescript
const result = await zernio.request({
  method: 'PUT',
  path: `/v1/accounts/${accountId}/youtube-playlists`,
  body: {
    defaultPlaylistId: 'PLxxxxxxxxxxxxx',
    defaultPlaylistName: 'Tutorials'
  }
});

console.log(result.success);
python
result = client.request(
    method="PUT",
    path=f"/v1/accounts/{account_id}/youtube-playlists",
    body={
        "defaultPlaylistId": "PLxxxxxxxxxxxxx",
        "defaultPlaylistName": "Tutorials"
    }
)

print(result["success"])

Scheduling Behavior

When you schedule a YouTube video for a future time, the following sequence occurs:

  1. The video uploads immediately as "private" regardless of your target visibility
  2. A video URL exists right away, but the video is not publicly accessible
  3. At the scheduled time, visibility changes to your target setting (usually "public")
  4. The firstComment is posted at the scheduled time, not at upload time

Media URL Requirements

  • The URL must return actual video bytes (not an HTML page)
  • No authentication or expired links -- the URL must be publicly accessible
  • Large videos (1 GB or more) can take 30-60+ minutes to process on YouTube's side
  • During processing, the video shows a "processing" state -- do not retry the upload

Analytics

> Included — Analytics is bundled with every paid account on the Usage plan.

Available metrics via the Analytics API:

MetricAvailable
Likes
Comments
Shares✅ (via Daily Views only)
Views

YouTube also provides a dedicated Daily Views API with detailed daily breakdowns including watch time, subscriber changes, and per-day likes/comments/shares. Data has a 2-3 day delay.

For channel-level aggregates (views, watch time, average view duration, subscribers gained/lost) without looping through every video, see the Channel Insights API. Impressions and impressions click-through rate (the thumbnail metrics from YouTube Studio) are not exposed by YouTube's Analytics API v2 for any principal type; the only way to get those is manual Studio CSV export.

The Demographics API returns audience breakdowns by age, gender, and country. Age and gender values are viewer percentages (0-100), country values are view counts. Data is based on signed-in viewers only, with a 2-3 day delay.

typescript
const analytics = await zernio.analytics.getAnalytics({
  platform: 'youtube',
  fromDate: '2024-01-01',
  toDate: '2024-01-31'
});
console.log(analytics.posts);
python
analytics = client.analytics.get_analytics(
    platform="youtube",
    from_date="2024-01-01",
    to_date="2024-01-31"
)
print(analytics["posts"])
bash
curl "https://zernio.com/api/v1/analytics?platform=youtube&fromDate=2024-01-01&toDate=2024-01-31" \
  -H "Authorization: Bearer YOUR_API_KEY"

What You Can't Do

  • Create Community posts
  • Go Live or schedule Premieres
  • Add end screens, cards, or chapters (timestamps in the description do work)
  • Manage monetization settings
  • Create or delete playlists (you can list playlists and add videos to an existing playlist)
  • Like or dislike videos
  • Upload captions or subtitles

Common Errors

ErrorMeaningFix
"The YouTube account of the authenticated user is suspended." (403)YouTube channel is suspended by YouTubeCheck channel status on YouTube. Use the account health endpoint.
"Social account not found"Connected account was disconnected or deleted from ZernioReconnect the YouTube account. Subscribe to the account.disconnected webhook.
"Account was deleted"User deleted the social accountReconnect the account.
"Failed to fetch video from URL: 404"Video URL returned a 404Verify the URL is still valid and publicly accessible. Links expire on some hosting services.
"YouTube permission error: Ensure the channel has required scopes and features enabled."Missing OAuth scopesReconnect the YouTube account with all required permissions.
"YouTube upload initialization failed: 403"Upload rejected before file transfer beganCheck whether the channel is suspended, the upload quota has been hit, or permissions are missing.

Inbox

> Included — Inbox (DMs, comments, reviews) is bundled with every paid account on the Usage plan.

YouTube supports comments only (no DMs available on the platform).

Comments

FeatureSupported
List comments on videos
Reply to comments
Delete comments
Like comments❌ (no API available)

Limitations

  • No DMs - YouTube does not have a direct messaging system
  • No comment likes - No public API endpoint available for liking comments

See Comments API Reference for endpoint details.

  • Connect YouTube Account - OAuth flow
  • List YouTube Playlists - Get playlist IDs for playlistId
  • Set Default YouTube Playlist - Store a default playlist selection
  • Create Post - Post creation and scheduling
  • Upload Media - Video uploads
  • Analytics - Performance metrics
  • YouTube Daily Views - Daily view statistics
  • YouTube Demographics - Audience age, gender, and country breakdowns
  • Comments - Read and reply to comments