# Private media uploads

Source: https://adsuperpowers.ai/docs/media-upload

Upload private images up to 20 MB and videos up to 500 MB through AdSuperpowers to Meta, TikTok, LinkedIn and Google Ads, with clear limits and recovery guidance.

Upload images up to 20 MB and videos up to 500 MB through AdSuperpowers to Meta, TikTok, LinkedIn and Google Ads. Use a connected destination account that your workspace is currently allowed to modify. Tool discovery alone does not mean your workspace has upload access. Media generation happens in the tool or client you choose.

These image and video upload routes are available in production. Creating a LinkedIn image or video draft from uploaded media is a separate step, currently available only to explicitly enabled pilot accounts.

## Choose your source

Reuse an existing media ID in the destination account when possible. For a local file, your client must be able to read the file and make an HTTP request. The remote MCP server cannot open a local path or an attachment stored in another application. Test your client's actual capabilities.

Use private staging when your workspace has access. An already approved direct HTTPS media URL remains an option on tools that support it; a sharing page is not a direct media URL. Do not publish a private file just to obtain a URL. Without file or HTTP access, use an authorized manual upload to the selected platform library and reuse its media ID.

## File limits

- Images: JPEG or PNG, up to 20 MB (20,000,000 bytes) and 16 million pixels.

- Video: MP4 with H.264 and optional AAC audio, up to 500 MB (500,000,000 bytes), with each dimension between 120 and 1920 pixels.

- Meta and Google video duration: 1–1800 seconds. TikTok: 3–600 seconds. LinkedIn: 3–1800 seconds. TikTok and LinkedIn require at least 75 KiB.

These are staging ceilings, not a guarantee of provider acceptance or placement eligibility. The stage response and current workspace availability govern your upload. Existing stages keep their recorded limits. Legacy Meta inline base64 images retain their 4 MiB raw-byte limit; base64 can consume substantial AI context and is not the preferred local-file route.

## Reserve, send, then finalize

1. Choose the workspace, platform and exact destination account. Calculate the file's byte length and SHA-256 locally. Preserve your original.

2. Call `assets_stage` with `platform`, `account_id`, `asset_type`, `filename`, `content_type`, `size_bytes` and `sha256_expected`. Send metadata only through MCP.

3. LinkedIn also requires the organization owner. Google video requires an existing channel, title, description and PUBLIC or UNLISTED privacy. UNLISTED is viewable by anyone with the link; it is not private YouTube storage. This flow creates no channel.

4. Use the returned method, URL and headers to send the original bytes once with HTTP PUT. Keep the upload capability out of chat, logs and progress files. Do not follow redirects.

5. After HTTP 201, finalize the same stage with the destination tool below. Keep the stage, account, immutable name, SHA-256, byte count and returned provider ID together.

### Meta

Image: `meta_upload_image`. Video: `meta_upload_video`. Keep the same account and image name or video title. Check private video processing with action=status.

### TikTok

Image: `tiktok_upload`. Video: `tiktok_upload`. Set asset_type to image or video. Keep advertiser_id and file_name exactly as staged.

### LinkedIn

Image: `linkedin_upload`. Video: `linkedin_upload`. Supply the organization owner when staging. Keep ad_account_id and asset_name. Use action=status to verify AVAILABLE.

### Google Ads

Image: `google_ads_upload`. Video: `google_ads_upload`. Set asset_type to video for MP4. Keep customer_id and asset_name. Video status reads the recorded YouTubeVideoUpload resource.

Upload success means accepted media, not ad approval or campaign activation. Observe processing readiness where required before using the media. Google video upload first returns a YouTubeVideoUpload resource; processing and a Google Ads asset are separate steps. Status checks create no asset or advertisement. Uploading media never authorizes spending.

## From media to a LinkedIn draft

For an enabled pilot account, `linkedin_manage` with `object_type="creative"` and `action="create_inline"` creates one image or video creative together with its dark post. The dark post supplies the ad content without organic feed distribution. Upload access alone does not enable this action; current account write access and organization posting rights are also required.

1. Select existing media in the destination account and verify `AVAILABLE`. Its owner must be the organization that will author the post. Check the intended ad placement's file requirements, which can be stricter than the upload limits above.

2. Select a campaign in the same account with a matching format: `SPONSORED_UPDATES` with `STANDARD_UPDATE` for an image or `SINGLE_VIDEO` for video. For a draft-only trial, confirm that the campaign and its group cannot deliver.

3. Review the exact campaign, media, text, title, destination link and call to action before authorizing creation. The server sets the creative to `DRAFT` and the post's `feedDistribution` to `NONE`.

4. Keep both the creative ID and the underlying post ID. Verify the account, campaign, author, media and copy, plus the creative's `isServing` and `servingHoldReasons` and the post's distribution. For immediate verification, use an uncached read; an older cached creative response is insufficient.

The post can be `PUBLIC` and `PUBLISHED` while the creative remains a non-serving draft. It may be reachable by a member with permission through its direct link. `NONE` does not make the post private. Draft creation is not ad approval or activation, and deleting a creative does not automatically delete its post.

If creation has an uncertain outcome, retain the response and any returned IDs and stop. Do not automatically create another creative because the response or an ID is missing.

You can also use `linkedin_query` to find targeting options (`entity_type="targeting_entities"`) and estimate audience size (`entity_type="audience_count"`) under your existing read access. These reads do not require inline-creative pilot enrollment. Counts are rounded provider estimates, not a forecast of campaign reach. See the [LinkedIn tool reference](https://adsuperpowers.ai/docs/tools/linkedin-ads) for examples.

## Cost and safe recovery

A new stage and successful finalization normally use two successful MCP calls. Each successful status check or receipt replay adds a call. HTTP PUT uses none. Fifty new uploads need at least 100 calls before checks or ad creation; a 50-call trial cannot cover that batch. Ordinary limits apply. Process one or two files at a time, with at most five open stages per workspace.

If a PUT response is lost, try finalizing the same known stage instead of sending the bytes again. Follow explicit same-stage capacity or retry hints; they do not authorize a new stage. Meta's safe image retry path does not apply automatically to another provider or to video.

On an unknown provider outcome, stop and inspect the exact destination. Never automatically restage, resend or resume byte offsets. Missing search results, a filename or a local hash alone do not establish that no upload occurred. Keep recorded IDs after reconnection; do not switch a stage to another account or credential to work around an access denial.

## Where your media goes

Original bytes, including embedded metadata, pass through Ad Superpowers on Railway and temporary private Supabase Storage to your selected platform account. We do not automatically strip metadata. Only the HTTP byte transfer stays outside MCP payloads; metadata, legacy base64 and files already shared with your AI client may still be in its context.

Staging is not a library or backup. The PUT capability permits one admitted attempt within 10 minutes. A ready stage can begin finalization within 24 hours of reservation. Sources become eligible for deletion after completion, failure or expiry. Cleanup is scheduled every 15 minutes with a daily bounded orphan inventory; outages can delay physical deletion. Result evidence has a separate 30-day window and is pruned after confirmed source deletion. Provider copies, audit records, backups and local originals have separate lifecycles. Closing admission also closes PUT; retained receipts remain subject to their deadlines and current authorization.

Merchant Center product media belongs in its webshop or feed workflow. GA4, Search Console and Tag Manager are not media-upload destinations. Documents, HTML5 bundles and audio uploads are outside this media upload flow.

[Read the data privacy details](https://adsuperpowers.ai/docs/data-privacy#uploaded-media)
