Guides

Media & images

Upload media once to get an id, then attach it to a post. Each network has its own limits. A media set that isn't valid for one target fails just that target.

Upload

Two ways, whichever suits your client. POST the raw bytes with the correct Content-Type:

curl -X POST https://api.postlake.dev/v1/media \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: image/jpeg" \
  --data-binary @photo.jpg

Or send it as a form file, which is what most HTTP libraries do by default:

curl -X POST https://api.postlake.dev/v1/media \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@photo.jpg"

Either way you get back a MediaAsset. For images it includes the pixel dimensions:

{ "id": "med_abc", "url": "https://…", "contentType": "image/jpeg", "size": 208134, "width": 1080, "height": 1920 }

From a local MCP agent

Call upload_media without url, passing the file's contentType and sizeBytes. It returns a five-minute signed PUT target and a preallocated med_… id. The agent PUTs the local bytes with the returned headers, then uses that id in create_post. For several slides, call upload_media_batch. The file does not need public hosting and its bytes do not pass through MCP JSON or base64. See the MCP local-file workflow.

POST /v1/media/batch takes either JSON { "items": [{ "contentType": "image/jpeg", "sizeBytes": 123 }] } (signed five-minute PUT targets) or multipart with multiple file parts. Max 12 items. Use this for a carousel instead of one request per slide.

Supported: JPEG, PNG, WebP and GIF images; MP4, MOV and WebM video. Video-only networks (YouTube, TikTok) require a video asset.

Pixel limits

Some networks reject an image for its dimensions, and several only do so after accepting the upload. TikTok is the worst case: it takes the post, processes it in the background, and fails a minute later with picture_size_check_failed, which names neither the limit nor the offending image.

So we check before publishing. An image outside a network's range fails validation immediately, with the limit and the actual size in the message:

{ "error": { "type": "invalid_input",
  "message": "TikTok images must be at most 1080x1920. This one is 2160x3840" } }

Current limits are on the platforms page, and in get_platform_capabilities as maxPx. TikTok photos must be between 540x960 and 1080x1920. Where we cannot read an image's header we do not guess, and the check is skipped rather than failing the post.

Attach. Globally or per platform

Put ids in media to attach to every account, or use mediaOverrides to give each platform its own set (a square image for Instagram, a video for TikTok). The url from the upload response works anywhere an id does, so you can pass back whichever field you kept.

{
  "text": "Launch day",
  "media": ["med_abc"],
  "mediaOverrides": { "tiktok": ["med_video"] },
  "accounts": ["acc_ig", "acc_tt"]
}

Per-platform media limits

PlatformMedia
BlueskyUp to 4 images, or 1 video
ThreadsImage carousel, or video
InstagramImage or video (Reels)
TikTokJPEG/WebP photos (max 1080×1920) or video. PNG is converted to JPEG at create/validate, with a warning.
YouTubeVideo only
X, LinkedIn, FacebookImages and video
PinterestImage or video (needs a boardId)

These are the practical rules today; call GET /v1/platforms/{platform} for the live, authoritative limits (max count, size, aspect) so you, or an agent, can validate before posting.

Alt text

Provide accessibility alt text per media item through platformOptions / media alt overrides. If a media set is invalid for a target, that target fails with a clear error and the others still publish, see Errors.