YouTube API for uploading Shorts
YouTube is the one network here that will not take a URL. It wants the video bytes over a resumable session — PostMCP fetches, uploads and publishes them for you.
- Endpoint
- POST /api/tools/create_post
- Platform value
- "youtube"
- Auth
- x-api-key or Bearer token
- Upstream
- YouTube Data API v3

What the YouTube Shorts API gives you
Publishing a Short through the YouTube Data API means opening a resumable upload session with the video metadata, reading the Location header it returns, and PUTting the file to that URL. Nothing about it resembles a normal JSON post, and nothing else on this list works that way.
"Shorts" is also not a separate endpoint. A video becomes a Short because of what it is — vertical or square, three minutes or less — not because of a flag you set. PostMCP checks the file before it spends the quota, splits your copy into a title and a description, turns hashtags into video tags and appends #Shorts so YouTube classifies it correctly.
Video upload from a URL
You pass a mediaUrl. The engine fetches the file, opens the resumable session and streams the bytes — the part of the API you would otherwise write yourself.
Title from the first line
The first non-empty line of your copy becomes the video title, trimmed to YouTube’s 100 characters. Angle brackets are stripped, because a stray <3 in a title fails the whole upload.
Description and #Shorts tagging
The full body becomes the description, capped at 5,000 characters, with #Shorts appended when you have not already tagged it.
Hashtags become video tags
Hashtags in the copy are lifted into the tags array, where YouTube actually reads them, and trimmed to fit the 500-character tag ceiling.
Pre-flight format check
A still image or a missing attachment is rejected before the upload starts, so a bad post costs one request rather than 1,600 units of daily quota.
Scheduled publication
Queue a Short by date and time alongside every other connected network.
Common uses
- Turn a product clip into a Short and cross-post the announcement to X and LinkedIn in the same call.
- Let an agent publish a weekly Short with the title and hashtags written from a plain-English brief.
- Schedule a run of Shorts across a launch week without keeping a Google token alive yourself.
- Repurpose an existing vertical video from your CDN by passing its URL, with no local upload step.
Post to YouTube Shorts in three steps
Connect the account once, grab an API key, then send a single request. The same body works from a shell, a server, or an AI agent.
- 1
Connect your YouTube Shorts account
Open the dashboard, choose YouTube Shorts and complete the hosted connect flow. Credentials are encrypted into the user vault and never returned to your client.
- 2
Create an API key
Generate a key from the dashboard. Send it as
x-api-key, as anAuthorization: Bearerheader, or as anapikeyquery parameter on the MCP transport. - 3
Send your first post
POST to
/api/tools/create_postwithplatforms: ["youtube"]. SetpublishImmediatelyto broadcast now, or supplyscheduleDateandscheduleTimeto queue it.
curl -X POST "https://api.postmcpai.com/api/tools/create_post" \
-H "Content-Type: application/json" \
-H "x-api-key: $POSTMCPAI_API_KEY" \
-d '{"content":"Shipping something new today. Built with PostMCP AI.","platforms":["youtube"],"publishImmediately":true}'{
"success": true,
"message": "Post created and queued successfully",
"post": {
"id": "66a50c89e4b019a2b72f",
"content": "Shipping something new today. Built with PostMCP AI.",
"platforms": [
"youtube"
],
"status": "published"
}
}YouTube Shorts API endpoints
Every endpoint is a POST against the base URL https://api.postmcpai.com. The same seven operations cover all connected networks — set the platform value to "youtube" to target YouTube Shorts.
| Operation | Endpoint | What it does |
|---|---|---|
| preflight_post | POST/api/tools/preflight_post | Dry-run copy against limits, targets and credits before publishing. |
| create_post | POST/api/tools/create_post | Schedule a post or broadcast it immediately. |
| publish_post_now | POST/api/tools/publish_post_now | Force a queued post out ahead of its slot, or retry the profiles that failed. |
| list_posts | POST/api/tools/list_posts | Read the queue — scheduled, published, draft and failed — with counts. |
| get_post | POST/api/tools/get_post | Read one post, with per-profile delivery state and live URLs. |
| update_post | POST/api/tools/update_post | Edit copy, targets, schedule or status before publication. |
| reschedule_post | POST/api/tools/reschedule_post | Move a post to another slot, keeping its copy and targets. |
| reset_stuck_post | POST/api/tools/reset_stuck_post | Release a post left stuck mid-publish so it can be retried. |
| delete_post | POST/api/tools/delete_post | Remove a scheduled or draft post from the queue. |
| get_connected_accounts | POST/api/tools/get_connected_accounts | List connected profiles, handles and page IDs per platform. |
| get_account_health | POST/api/tools/get_account_health | Find connections whose token expired or is about to. |
| list_brandings | POST/api/tools/list_brandings | Read the workspace brand kits used to keep copy and visuals on-brand. |
| generate_image | POST/api/tools/generate_image | Generate a post image and get back a hosted URL for mediaUrl. |
| list_workspaces | POST/api/tools/list_workspaces | List the workspaces on this key, with the id to scope other calls to. |
| get_user_info | POST/api/tools/get_user_info | Read plan tier, publishing credits and AI token balance. |
create_post parameters
| Field | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | Text body of the post. Truncation rules are enforced by the destination network, not by PostMCP. |
| targetAccounts | array[object] | Yes | The profiles that receive the post. Each entry takes platform and profileId (from get_connected_accounts). Only the profiles listed here are posted to. |
| platforms | array[string] | Optional | Shorthand for whole networks — linkedin, twitter, facebook, instagram, threads, bluesky, youtube. Each one expands to every connected profile on it, so prefer targetAccounts unless you mean that fan-out. Optional when targetAccounts is given. |
| publishImmediately | boolean | Optional | When true the post is broadcast on receipt. Defaults to false, which queues it. |
| scheduleDate | string | Optional | Publication date as YYYY-MM-DD. Required when publishImmediately is false. |
| scheduleTime | string | Optional | Publication time as HH:MM on a 24-hour clock. Required when publishImmediately is false. |
| timezone | string | Optional | IANA zone the schedule above is written in, e.g. Asia/Kolkata. Omit it and the wall-clock slot resolves as UTC, which is rarely what "10am" meant. |
| mediaUrl | string | Optional | Publicly reachable image or video URL. PostMCP fetches it and re-uploads it in the format the network expects. Required, and must be a video, when the post targets YouTube. |
| workspaceId | string | Optional | Workspace to post from, taken from list_workspaces. Omitted, the call resolves to the default workspace on the key. |
YouTube Shorts OAuth and API keys
Two layers of auth sit under every request: the YouTube Shorts credential you grant once during connect, and the PostMCP API key your code sends on each call.
Consent on Google
The channel owner signs in with Google and grants the upload and read-only scopes. Offline access is requested so a refresh token comes back.
Scopes verified at the callback
The granted scope list is checked for youtube.upload. A consent screen where that box was unticked is rejected there and then.
Channel resolved
channels?mine=true returns the channel. Its id is stored as the profile id, because that survives a handle change; a Google account with no channel is refused with that reason.
Tokens encrypted and refreshed
The refresh token is encrypted into the user vault and exchanged for a fresh access token before every upload.
Scopes requested from YouTube Shorts
| Scope | Why it is needed |
|---|---|
| https://www.googleapis.com/auth/youtube.upload | The only scope that can insert a video. Without it the connection is refused at the callback rather than failing later on a publish. |
| https://www.googleapis.com/auth/youtube.readonly | Reads the channel title, handle and avatar so the connected profile is named properly instead of showing a bare channel id. |
Sending your API key
x-api-key: pmcp_sec_…Authorization: Bearer pmcp_sec_…/mcp?apikey=pmcp_sec_…How PostMCP publishes to YouTube Shorts
One request from you becomes this sequence server-side. Knowing the shape helps when you are debugging a failed broadcast.
- 1
Check the media first
The
mediaUrlmust be present and must look like a video (mp4, mov, webm, …). Anything else fails here, before a byte is transferred. - 2
Fetch the video
The file is downloaded with a video-length read window and a 256MB ceiling, and its MIME type derived from the URL and the response.
- 3
Build the metadata
Title from the first line, description from the body with
#Shorts, tags from the hashtags, category "People & Blogs" and an explicit made-for-kids declaration — which YouTube requires. - 4
Open the resumable session
The metadata is POSTed with
X-Upload-Content-LengthandX-Upload-Content-Type; YouTube answers with the upload URL. - 5
Send the bytes
The whole file goes in one PUT. Chunking only pays off when a transfer can resume across restarts, which a single publish run cannot do.
- 6
Record the link
The returned video id is stored and the delivery link is built as
youtube.com/shorts/{id}.
Upstream YouTube Shorts calls
| Method | Endpoint | Purpose |
|---|---|---|
| GET | https://www.googleapis.com/youtube/v3/channels?part=snippet,contentDetails&mine=true | Identifies the channel behind the token and supplies its name, handle and avatar. |
| POST | https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status | Opens the resumable session with the snippet and status metadata, returning the upload URL in the Location header. |
| PUT | {resumable upload URL} | Sends the video bytes and returns the published video id. |
Direct YouTube Shorts API vs PostMCP
| Aspect | Calling YouTube Shorts directly | With PostMCP |
|---|---|---|
| Upload protocol | Open a resumable session, read the Location header, PUT the bytes | One `mediaUrl` field |
| Getting the video | You host and stream the file yourself | Fetched from your URL, size and type checked |
| Title and description | Two separate fields you have to split and truncate | First line becomes the title, the body becomes the description |
| Shorts classification | No flag exists — you have to get the file right | Format checked up front, `#Shorts` appended for you |
| Tokens | Refresh the Google access token before each call | Encrypted, refreshed per broadcast |
| Scheduling | Not part of the Data API | Same queue as every other network |
YouTube Shorts limits and supported media
These ceilings are set by YouTube Shorts, not by PostMCP. Your content field is forwarded unchanged, so the network enforces them rather than silently truncating.
Common YouTube Shorts API errors
Failures are recorded per platform on the post record, so a multi-network broadcast that partially succeeds tells you exactly which leg failed and why.
| Code | Message | Likely cause | Fix |
|---|---|---|---|
| quotaExceeded | The request cannot be completed because you have exceeded your quota | Each upload costs 1,600 of the application’s 10,000 daily units, so roughly six uploads a day exhausts a default project. | This is an application-wide limit, not a limit on your channel. It resets at midnight Pacific — reschedule the post for tomorrow and retry it then. |
| mediaRequired | YouTube Shorts needs a video | The post carried no attachment, or the attachment was a still image. | Attach a vertical clip of three minutes or less. The check runs before the upload, so nothing is spent. |
| invalidTitle | Video title rejected | YouTube refuses titles containing angle brackets. | Handled for you — the brackets are stripped from the first line before it is sent. |
| forbidden | The request is not properly authorized | The youtube.upload scope was not granted, or the refresh token was revoked in the Google account. | Reconnect the channel and leave every requested permission ticked. |
| uploadLimitExceeded | The user has exceeded the number of videos they may upload | YouTube applies its own per-channel daily upload ceiling, separate from the API quota. | Space the Shorts out across days using the scheduler. |
Post to YouTube Shorts from an AI agent
The same seven operations are exposed as MCP tools. Point Claude Desktop, Cursor, or any MCP client at the server and your agent can publish to YouTube Shorts directly.
{
"mcpServers": {
"postmcpai": {
"command": "npx",
"args": ["-y", "@postmcpai/server"],
"env": {
"POSTMCPAI_API_KEY": "pmcp_sec_YOUR_SECRET_KEY",
"POSTMCPAI_API_URL": "https://api.postmcpai.com"
}
}
}
}Prompt the agent directly
With the server connected, natural language is enough — the agent picks the tool and fills the arguments:
“Draft a YouTube Shorts post about today’s release and schedule it for 9:30am tomorrow.”
YouTube Shorts API questions
How do I upload a YouTube Short with the API?
POST to https://api.postmcpai.com/api/tools/create_post with platforms: ["youtube"], your content and a mediaUrl pointing at a vertical video. PostMCP fetches the file, opens the resumable upload session and publishes it to the connected channel.
Is there a separate Shorts API?
No. A video is treated as a Short because of what it is — vertical or square and three minutes or under — not because of any flag. PostMCP checks the file before uploading and appends #Shorts so YouTube classifies it.
Where do the title and description come from?
The first non-empty line of your copy becomes the title, trimmed to 100 characters, and the full body becomes the description, capped at 5,000. Hashtags in the copy also become video tags.
Can I post an image to YouTube?
No, and the request is rejected before anything is uploaded. YouTube only takes video, so a post without a video attachment fails its pre-flight check rather than burning upload quota.
What does "quota exceeded" mean on a YouTube post?
Every upload costs 1,600 units of a Google project’s 10,000 daily units, so about six uploads exhaust a default quota. It is a limit on the application rather than on your channel, and it resets at midnight Pacific time.
Which permissions does connecting a channel need?
youtube.upload to publish and youtube.readonly to read the channel name and avatar. If the upload permission is unticked on the Google consent screen, the connection is refused right there instead of failing on a later publish.
Other social media APIs
One authenticated POST publishes to a LinkedIn profile or company page. PostMCP owns the OAuth dance, the image upload handshake and the versioned LinkedIn REST calls underneath.
Read the referenceSend one request and PostMCP handles Twitter API v2 for you — PKCE OAuth, the three-step chunked media upload, refresh tokens and the final tweet call.
Read the referencePublish text and photo posts to every Facebook Page you manage from one endpoint. PostMCP resolves page access tokens and calls Graph API v26.0 for you.
Read the referenceInstagram publishing is a two-phase asynchronous flow. PostMCP creates the media container, polls it to FINISHED and publishes it — you send a caption and a media URL.
Read the referenceThreads processes every post asynchronously, even plain text. PostMCP creates the container, polls it to FINISHED and publishes — one call from your side.
Read the referenceBluesky is not OAuth — it is a session against an AT Protocol server. PostMCP refreshes that session, uploads image blobs and writes the feed record for you.
Read the referenceStart posting to YouTube Shorts today
Connect the account, take an API key and send your first request in under five minutes — from a shell, your backend, or an AI agent.