How to Bulk Upload YouTube Shorts via API

15 min read AgenciesUpdated 2026-05-06

YouTube's Data API v3 gives each Google Cloud project a default budget of 10,000 quota units per day, and every API call draws from it. All YouTube channels connect to CodivUpload through CodivUpload's single Google Cloud project, and CodivUpload manages that quota for its users — you never supply your own Google credentials. This guide covers connecting your channel, formatting Shorts, uploading via POST /v1/posts, adding uploads to a playlist, and pacing a bulk upload script.

Prerequisites

  • A YouTube channel
  • A CodivUpload profile with the channel connected
  • An API key from Dashboard → API Keys

Step-by-step

  1. 1

    Connect your YouTube channel

    In Dashboard → Profiles → Connect → YouTube, approve the Google OAuth flow. The channel connects through CodivUpload's Google Cloud project, so there is no Google Cloud setup on your side. After connecting, you can upload immediately.

  2. 2

    Format your video as a Short

    YouTube auto-classifies a video as a Short if it meets three criteria: vertical aspect ratio (9:16), under 60 seconds duration, and the title or description contains #Shorts. CodivUpload appends #Shorts to the title automatically when you set youtube_type=shorts, but you should still ensure the source video is vertical and trimmed under 60 seconds. Horizontal videos with #Shorts in the title are still treated as regular videos by the algorithm.

  3. 3

    Upload via POST /v1/posts

    Set post_type=video, profile_name to your profile, platforms=["youtube"], and youtube_type=shorts. Pass the video URL in media_urls. CodivUpload handles the resumable upload protocol behind the scenes — you don't need to chunk the file or handle retries.

    curl -X POST https://api.codivupload.com/v1/posts \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "post_type": "video",
        "profile_name": "my_brand",
        "platforms": ["youtube"],
        "media_urls": ["https://your-cdn.example.com/short.mp4"],
        "title": "Quick tip for creators",
        "description": "How to save 4 hours/week on social — full guide in the comments.",
        "youtube_type": "shorts",
        "youtube_privacy_status": "public",
        "youtube_tags": ["productivity", "creators", "shorts", "automation"],
        "youtube_category_id": "27"
      }'
  4. 4

    Add to a playlist programmatically

    If you have an existing Shorts playlist, set youtube_playlist_id to add the upload to it automatically. Each playlistItems.insert call costs 50 quota units. For longer-form videos use the same field; YouTube doesn't distinguish between Shorts playlists and regular playlists at the API level.

  5. 5

    Loop through a video list (Python example)

    Wrap the upload in a Python or Node script. Pause 30 seconds between uploads to stay under YouTube's per-minute rate limits — firing too fast can trigger temporary throttling. The script below reads a list of {url, title} dicts and posts each one through CodivUpload.

    import os, time, requests
    
    API = "https://api.codivupload.com/v1/posts"
    KEY = os.environ["CODIVUPLOAD_API_KEY"]
    PROFILE = "my_brand"
    
    videos = [
        {"url": "https://cdn.example.com/v1.mp4", "title": "Tip 1: batch your content"},
        {"url": "https://cdn.example.com/v2.mp4", "title": "Tip 2: use a content bank"},
        # ...
    ]
    
    for v in videos:
        r = requests.post(API, headers={
            "Authorization": f"Bearer {KEY}",
            "Content-Type": "application/json",
        }, json={
            "post_type": "video",
            "profile_name": PROFILE,
            "platforms": ["youtube"],
            "media_urls": [v["url"]],
            "title": v["title"],
            "description": v["title"] + " — full breakdown in our newsletter.",
            "youtube_type": "shorts",
            "youtube_privacy_status": "public",
            "youtube_tags": ["productivity", "creator-tips"],
        })
        r.raise_for_status()
        print(v["title"], "→", r.json()["post_id"])
        time.sleep(30)

Frequently asked

Why does YouTube reject some of my uploads with invalidTags?+

YouTube's tags field has a hard 500-character limit, counting commas and quote-marks for multi-word tags. CodivUpload sanitizes tags automatically — overflowing entries are truncated from the end of the list — but if you bypass the sanitizer with a custom override, you can hit the cap. Other common rejections: title over 100 characters, description over 5,000 characters, or quota exhaustion (status quotaExceeded in destinations).

Can I upload faster than 30 seconds per post?+

Technically yes — YouTube's resumable upload protocol supports parallel sessions, but per-minute rate limits start kicking in around 5-10 sessions per minute. 30 seconds is the safe pacing.

What's the difference between youtube_type=shorts and youtube_type=video?+

youtube_type=shorts triggers the Shorts classification rules: title gets #Shorts appended, custom thumbnails are skipped (Shorts auto-extract from the first frame), and the video lands in the Shorts shelf on the channel page. youtube_type=video uses the standard video flow with full thumbnail support and lands in the Videos tab.

How do I disclose AI-generated content?+

Set youtube_contains_synthetic_media=true. YouTube adds an automatic disclosure label to the video page. As of 2025 this is required for any content that uses generative AI to manipulate footage of real people — failing to disclose can result in age-restriction or removal under YouTube's misleading content policy.

Custom thumbnails for Shorts — supported?+

No. YouTube's Shorts player extracts the first frame as the thumbnail and ignores any uploaded image. CodivUpload's youtube_thumbnail_url field is silently dropped when youtube_type=shorts. For long-form videos (youtube_type=video), the field is honored.

Can I cross-post the same Short to TikTok and Instagram Reels?+

Yes. Add tiktok and instagram to platforms in the same call: "platforms": ["youtube", "tiktok", "instagram"]. Use platform-specific overrides where the formats differ (e.g. instagram_share_to_feed=true if you also want it on the IG grid). One caveat: the source video must satisfy the strictest platform's constraints — TikTok wants 9:16 portrait under 180 seconds, which is a superset of YouTube Shorts and Instagram Reels, so a 9:16/60-second master file works everywhere.

Related guides

Ready to automate?

Free plan includes 10 uploads/month across 10+ platforms. No credit card required.

See pricing