Media Requirements
Each social platform enforces its own limits on file sizes, dimensions, video duration, and formats. This page covers every constraint so you can validate media before uploading.
Upload Limits
The PostEverywhere API accepts files up to these sizes:
| Type | Maximum Size |
|---|---|
| Images | 20 MB |
| Videos | 500 MB |
| PDFs | 20 MB |
Accepted MIME Types
image/jpeg
image/png
image/gif
image/webp
image/heic
image/heif
video/mp4
application/pdf
Only video/mp4 is accepted for video uploads. If your source video is in another format, transcode it to H.264 MP4 before uploading.
File Size Limits by Platform
The API enforces the PostEverywhere upload limits above, but individual platforms may reject media that exceeds their own limits. Ensure your files stay within these bounds:
| Platform | Image Max | Video Max | Other |
|---|---|---|---|
| 8 MB | 100 MB | -- | |
| X / Twitter | 5 MB | 512 MB | -- |
| 20 MB | 5 GB | 100 MB (PDF) | |
| 4 MB | 1 GB | -- | |
| TikTok | 2 MB | 500 MB | -- |
| YouTube | -- | 256 GB | -- |
| Threads | 8 MB | 100 MB | -- |
| 20 MB | 2 GB | -- |
PostEverywhere's own 500 MB video upload limit is more restrictive than some platforms (YouTube, LinkedIn). We process and re-upload your media to each platform.
Image Dimensions
| Platform | Minimum | Maximum / Recommended |
|---|---|---|
| 320 x 320 | 1080 x 1350 (4:5 portrait recommended) | |
| X / Twitter | 200 x 200 | 4096 x 4096 |
| 552 x 368 | 4000 x 4000 | |
| 200 x 200 | 2048 x 2048 | |
| TikTok | 720 x 1280 | 1080 x 1920 |
| Threads | 320 x 320 | 1080 x 1350 |
| 200 x 200 | 1000 x 1500 (2:3 recommended) |
You do not need to pre-resize images to fit the table above. Media is served to each platform through Cloudflare Images, and where a platform enforces a hard ceiling we request a scaled-down variant automatically — TikTok's Photo API rejects anything over 1080 px, so a 4032 x 3024 phone photo is delivered to TikTok at 1080 x 810 with the aspect ratio preserved. Images already within a platform's limits are passed through untouched at full resolution.
Video Duration Limits
| Platform | Minimum | Maximum |
|---|---|---|
| Instagram Reels | 3 seconds | 15 minutes |
| X / Twitter | 0.5 seconds | 2 min 20 sec |
| 3 seconds | 10 minutes | |
| 1 second | 4 hours | |
| TikTok | 1 second | 10 minutes |
| YouTube | 1 second | 12 hours |
| Threads | 1 second | 5 minutes |
| 4 seconds | 15 minutes |
Aspect Ratios
Aspect ratio requirements vary significantly by platform. Getting these wrong is one of the most common causes of publishing failures.
| Platform | Accepted Ratios | Notes |
|---|---|---|
| TikTok | 9:16 only | Vertical video is mandatory. Other ratios are rejected. |
| 4:5 to 1.91:1 | 4:5 portrait performs best. Square (1:1) is safe. | |
| X / Twitter | 1:3 to 3:1 | Wide range accepted. 16:9 is standard. |
| 1:2.4 to 2.4:1 | 1:1 or 16:9 recommended for feed. | |
| 9:16 to 16:9 | 4:5 recommended for feed. | |
| YouTube | 16:9 | Other ratios are letterboxed or pillarboxed. |
| Threads | 4:5 to 1.91:1 | Same as Instagram. |
| 2:3 to 1:1 | 2:3 vertical pins perform best. |
TikTok strictly rejects any video that is not in 9:16 portrait orientation. Always verify the aspect ratio before publishing to TikTok.
Media Count Limits
Maximum number of media attachments per post:
| Platform | Images | Videos | |
|---|---|---|---|
| 10 (carousel) | 1 (Reels) | -- | |
| X / Twitter | 4 | 1 | -- |
| 20 | 1 | 1 | |
| 10 | 1 | -- | |
| TikTok | 1 | 1 | -- |
| YouTube | -- | 1 | -- |
| Threads | 10 | 1 | -- |
| 1 | 1 | -- |
You cannot mix images and videos in the same post on most platforms. Instagram carousels are image-only.
Video Codec Requirements
All platforms require H.264-encoded MP4 files. Details vary:
| Platform | Codec | Frame Rate | Max Bitrate |
|---|---|---|---|
| H.264 | 30 fps | 25 Mbps | |
| X / Twitter | H.264 | 60 fps | 25 Mbps |
| H.264 | 30 fps | 30 Mbps | |
| H.264 | 30 fps | 16 Mbps | |
| TikTok | H.264 | 30 fps | 20 Mbps |
| YouTube | H.264 / H.265 | 60 fps | 128 Mbps |
| Threads | H.264 | 30 fps | 25 Mbps |
| H.264 | 25 fps | 20 Mbps |
Audio should be AAC, 128 kbps or higher. PostEverywhere transcodes uploaded videos automatically, but starting with a compliant file avoids quality loss.
Upload Flow
Two options depending on whether the file is already on the public web:
Option A: Already on a public URL (one call)
If your image is already hosted somewhere publicly fetchable, use POST /v1/media/upload-from-url:
curl -X POST https://app.posteverywhere.ai/api/v1/media/upload-from-url \
-H "Authorization: Bearer pe_live_abc123..." \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com/hero.webp" }'
Response is ready-to-use immediately (media_status: "ready"):
{
"data": {
"media_id": "a1b2c3d4-...",
"media_ids": ["a1b2c3d4-..."],
"media_status": "ready",
"type": "image",
"url": "https://imagedelivery.net/.../img_.../public",
"content_type": "image/webp",
"size": 14914
}
}
Images (25 MB cap) import instantly; MP4 videos (500 MB cap) import asynchronously — poll GET /media/{id} until media_status is ready. For local files, use Option B.
Option B: Local file (3-step flow)
For local files, the upload is a 3-step process: request a presigned URL, upload bytes to it, then finalise.
Step 1: Request a presigned upload URL
POST /v1/media/upload takes JSON describing the file you're about to upload — not the file itself. Field names are filename, content_type, size (not file_name, mime_type, file_size).
curl -X POST https://app.posteverywhere.ai/api/v1/media/upload \
-H "Authorization: Bearer pe_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"filename": "photo.jpg",
"content_type": "image/jpeg",
"size": 2048000
}'
The response includes a media_id, an upload_url, and an upload_method describing how to upload:
{
"data": {
"media_id": "a1b2c3d4-...",
"upload_url": "https://upload.imagedelivery.net/...",
"upload_method": {
"method": "POST",
"content_type": "multipart/form-data",
"field_name": "file"
},
"media_status": "uploading"
}
}
Step 2: Upload the bytes to upload_url
Sending PUT with raw bytes to an image upload_url returns 400 {"code":100,"message":"method is not supported"}. Image URLs are Cloudflare direct-upload endpoints: use POST with multipart/form-data and the file in the field named by upload_method.field_name (usually file). Only video and PDF URLs accept PUT with raw bytes.
For images, send a multipart POST with the field name from upload_method.field_name (usually file):
curl -X POST "<upload_url>" \
-F "[email protected]"
For videos, use the PUT method with the correct Content-Type header (upload_method.method will be PUT and upload_method.headers tells you the header to send).
Step 3: Finalise
This step is required — without it the media stays in media_status: "uploading" and POST /v1/posts will reject attempts to attach it.
curl -X POST https://app.posteverywhere.ai/api/v1/media/{media_id}/complete \
-H "Authorization: Bearer pe_live_abc123..."
After Step 3 the media is ready and you can attach it via media_ids in a post.
Polling for video processing (Option B videos only)
Videos go through additional processing for thumbnail extraction. After Step 3 returns ready, the file is uploadable but the thumbnail may still be generating. Poll GET /v1/media/{id} if you need the thumbnail_url field populated.
Step 3: Attach to a post
curl -X POST https://app.posteverywhere.ai/api/v1/posts \
-H "Authorization: Bearer pe_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"content": "Check out this photo!",
"account_ids": [123],
"media_ids": ["550e8400-e29b-41d4-a716-446655440000"],
"scheduled_for": "2026-04-15T10:00:00Z"
}'
Always confirm the media status is ready before attaching it to a post. See Upload Media for the full endpoint reference.
Related
- Upload Media -- upload endpoint reference
- Schedule a Post -- attach media to posts
- Error Handling -- media-related error codes (
unsupported_media_type,file_too_large,file_type_mismatch)