Docs › API reference › Videos

Videos API: upload to YouTube or TikTok

Upload a video to one channel with typed settings for its platform, publish it now or later, and poll for the result.

Updated

A video goes to one channel at a time, and its settings are typed for that channel's platform. Text posts, and posts sent to several channels at once, use Posts instead. A video is still a post underneath (a post with one target), so scheduling, idempotency, limits, cancel and retry all work the same way.

Publish a video

Upload the file with POST /v1/media first (see Media), then pass its id to POST /v1/videos:

Leave out scheduledFor to publish now. The answer is 201 with the video. Its id also works on /v1/groups/{id}, so you can cancel, retry or edit it there.

curl https://omniposts.dev/v1/videos \
  -H "Authorization: Bearer omniposts_..." \
  -H "Idempotency-Key: tutorial-video-1" \
  -H "Content-Type: application/json" \
  -d '{
    "channelId": "0192a3b4-0000-7000-8000-000000000001",
    "mediaId": "0192a3b4-0000-7000-8000-000000000002",
    "description": "In this video I show how to post with the OmniPosts API.\n\n0:00 Intro\n1:30 First call",
    "scheduledFor": "2026-10-20T09:30:00Z",
    "settings": {
      "type": "youtube",
      "title": "How to post with the OmniPosts API",
      "visibility": "private",
      "madeForKids": false,
      "tags": ["omniposts", "api", "tutorial"],
      "format": "video"
    }
  }'

Request fields

Field Type Meaning
channelId id Required. The channel to upload to. Its platform must match settings.type
mediaId id Required. A video uploaded with POST /v1/media
description string The video's description. On YouTube: up to 5,000 bytes, and no < or >
scheduledFor time When to publish. Leave it out to publish now
timezone string The time zone the schedule was picked in, for display
settings object Required. The platform's settings, chosen by settings.type

YouTube settings

Send these with "type": "youtube". Any other key is refused with a 400, so a typo can't quietly drop a setting. Each one is a field of YouTube's own upload call (videos.insert).

Field Type Meaning
type youtube Required
title string Required. Up to 100 characters, and no < or >
visibility private, unlisted or public Defaults to private. Providers shows whether only private is allowed for now (lockedValue)
madeForKids boolean Required. Whether the video is made for children, as US law (COPPA) asks. There is no default: it is your declaration, so OmniPosts never makes it for you
tags array of strings No commas, < or > inside a tag. At most 500 characters in total, counted the way YouTube counts them: a tag with a space counts 2 more (YouTube puts it in quotes), and each comma between tags counts 1
categoryId string A YouTube category number. Leave it out to let YouTube decide
format video or short Defaults to video. A short must be vertical or square and at most 3 minutes long. OmniPosts checks this before uploading
notifySubscribers boolean Tell subscribers about the video. Defaults to true
containsSyntheticMedia boolean Declares realistic content that was altered or made with AI. Defaults to false

Whether YouTube is open on your account is on Channels.

TikTok settings

Send these with "type": "tiktok", for a TikTok or a TikTok for Business channel. TikTok has no separate video title: the request's description is the caption, up to 2,200 characters, with emoji counting as two. Any other key is refused with a 400.

Field Type Meaning
type tiktok Required
mode direct Optional. For a draft, see TikTok drafts
privacyLevel PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR or SELF_ONLY Required, with no default: TikTok asks that the person choose who sees each video. Providers shows whether only SELF_ONLY is allowed for now (lockedValue). TikTok for Business channels publish videos to everyone, so they take only PUBLIC_TO_EVERYONE
disableComment boolean Turn off comments. Defaults to false
disableDuet boolean Turn off Duet. Defaults to false
disableStitch boolean Turn off Stitch. Defaults to false
commercialContent boolean The disclosure switch: the video promotes a brand, product or service. When true, set brandedContent, yourBrand or both to true, or the request is refused with a 400. Defaults to false
brandedContent boolean A paid partnership: the video promotes another brand in exchange for something of value. TikTok labels it "Paid partnership". It cannot be SELF_ONLY. Defaults to false
yourBrand boolean The video promotes your own business. TikTok labels it "Promotional content". Defaults to false
aiGenerated boolean Label the video as AI-generated. Defaults to false
coverTimestampMs whole number TikTok channels only: the frame to use as the cover, in milliseconds from the start. Leave it out for the first frame

Right before it posts, OmniPosts reads the account's current settings from TikTok. The video fails, with failure saying why, when privacyLevel is not one this account offers or the video is longer than the account may post. Comments, Duet or Stitch that the creator turned off in TikTok stay off, whatever you send. TikTok downloads the video from OmniPosts and then processes it, so the video stays awaiting_platform for a minute or more before it is published. A video only you can see has no public link, so its externalUrl stays empty.

{
  "channelId": "0192a3b4-0000-7000-8000-000000000003",
  "mediaId": "0192a3b4-0000-7000-8000-000000000002",
  "description": "Glazing day, start to finish #pottery",
  "settings": {
    "type": "tiktok",
    "privacyLevel": "SELF_ONLY",
    "disableDuet": true,
    "aiGenerated": false
  }
}

TikTok drafts

Send "mode": "draft" to put the video in the creator's TikTok inbox instead of posting it. TikTok notifies them, and they add the caption and settings and post it from the TikTok app.

  • A draft carries only the video. Leave out description and every other setting, or the request is refused with a 400, because TikTok would drop them.
  • Drafts work for TikTok channels, not TikTok for Business ones.
  • The video is published once it is in the inbox. It has no externalUrl, because nothing is public yet.
  • TikTok allows 5 pending drafts from apps per account in 24 hours. Past that the video fails with pending_draft_cap.
  • The channel needs permission to upload drafts. A TikTok channel connected before OmniPosts asked for it fails with draft_permission_missing until it is reconnected.
{
  "channelId": "0192a3b4-0000-7000-8000-000000000003",
  "mediaId": "0192a3b4-0000-7000-8000-000000000002",
  "settings": { "type": "tiktok", "mode": "draft" }
}

GET /v1/videos/{id}

Follow a video

GET /v1/videos/{id} returns the video. Its status is the status of the upload itself (post statuses). When it is published, externalUrl links to the video; when it is failed or unknown, failure says what happened and what to do. You can also subscribe to webhooks and skip polling. A post sent to several channels is not a video, and this endpoint answers 404 for it.

Errors

Status Code When
400 invalid_request A missing field, an unknown settings.type, an unknown settings key, or a value of the wrong kind
404 not_found The channel is not one of yours, or it was disconnected
409 idempotency_conflict The same Idempotency-Key was used for a different request
422 settings_type_mismatch The settings are for a different platform than the channel's. details has settingsType and providerId
422 nothing_to_publish The platform's rules refuse the video before it is sent, for example an image instead of a video. details.rejections[0].failure says why

Plan and posting limits answer the same way as for posts. See Errors for the envelope.