Media API
Upload images, videos, and documents to PostEverywhere via presigned URLs. Media is automatically processed and optimized for each platform, then attached to posts via the Posts API.
Endpoints
/media/upload/media/{id}/complete/media/media/{id}/media/{id}Upload flow
Media uploads use a four-step presigned URL flow. Your files go directly to cloud storage without passing through PostEverywhere servers, making uploads fast and secure.
Request a presigned URL
Call POST /media/upload with your file metadata. The API returns a presigned URL and a media_id to track the upload.
curl -X POST https://app.posteverywhere.ai/api/v1/media/upload \ -H "Authorization: Bearer pe_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{ "filename": "product-launch.jpg", "content_type": "image/jpeg", "size": 2048576, "platforms": ["instagram", "facebook", "linkedin"], "width": 1080, "height": 1080 }'{ "data": { "media_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "upload_url": "https://storage.posteverywhere.ai/uploads/a1b2c3d4...?X-Amz-Signature=...", "upload_method": { "method": "PUT", "content_type": "image/jpeg", "field_name": null }, "provider": "s3", "protocol": "https", "expires_in": 900, "max_size": 20971520 }, "meta": { "request_id": "req_abc123", "timestamp": "2026-03-02T10:30:00Z" } }Upload the file directly
PUT your file directly to the upload_url. This goes straight to cloud storage — no PostEverywhere server in the middle.
curl -X PUT "https://storage.posteverywhere.ai/uploads/a1b2c3d4...?X-Amz-Signature=..." \ -H "Content-Type: image/jpeg" \ --data-binary @product-launch.jpgConfirm completion
After the PUT upload succeeds, call POST /media/{id}/complete to tell PostEverywhere the upload is done. This triggers processing (thumbnail generation, dimension extraction, platform-specific optimization). The response includes the final media object with processed URLs.
curl -X POST https://app.posteverywhere.ai/api/v1/media/a1b2c3d4-e5f6-7890-abcd-ef1234567890/complete \ -H "Authorization: Bearer pe_live_your_key_here"Attach media to a post
Once processing is complete, use the media_id when creating a post via the Posts API.
curl -X POST https://app.posteverywhere.ai/api/v1/posts \ -H "Authorization: Bearer pe_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{ "content": "Check out our new product!", "account_ids": [1, 2, 3], "media_ids": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"], "scheduled_at": "2026-03-15T14:00:00Z" }'AI-generated images skip this flow. Images created via POST /ai/generate-image go directly into your media library with a ready status — no presigned URL upload or completion step required.
/media/uploadRequest a presigned URL for uploading a media file. The file is not uploaded in this request — you receive a URL to PUT the file directly to cloud storage.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | Original filename including extension |
content_type | string | Yes | MIME type (e.g. image/jpeg, video/mp4) |
size | integer | Yes | File size in bytes |
platforms | string[] | No | Target platforms for optimization (e.g. ["instagram", "facebook"]) |
width | integer | No | Image/video width in pixels |
height | integer | No | Image/video height in pixels |
duration | number | No | Video duration in seconds |
Response fields
| Field | Type | Description |
|---|---|---|
media_id | uuid | Unique identifier to reference this media in other API calls |
upload_url | string | Presigned URL to PUT your file to |
upload_method | object | Upload instructions: method (HTTP method), content_type (Content-Type header), field_name (for multipart uploads, otherwise null). Images use Cloudflare Images with platform-optimized variants for Instagram, Facebook, LinkedIn, X. Videos and PDFs use R2 presigned PUT URLs. |
provider | string | Storage provider (e.g. s3) |
protocol | string | Upload protocol (e.g. https) |
expires_in | integer | Seconds until the presigned URL expires |
max_size | integer | Maximum file size in bytes for this upload |
/media/{id}/completeConfirm that a file has been uploaded to the presigned URL. This triggers server-side processing (thumbnail generation, dimension extraction, and platform-specific optimization). Call this endpoint after your PUT upload succeeds.
curl -X POST https://app.posteverywhere.ai/api/v1/media/a1b2c3d4-e5f6-7890-abcd-ef1234567890/complete \ -H "Authorization: Bearer pe_live_your_key_here"{ "data": { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "type": "image", "mime_type": "image/jpeg", "file_size": 2048576, "status": "processing", "original_name": "product-launch.jpg", "url": null, "thumbnail_url": null, "dimensions": { "width": 1080, "height": 1080 }, "aspect_ratio": "1:1", "orientation": "square", "created_at": "2026-03-02T10:30:00Z" }, "meta": { "request_id": "req_cmp456", "timestamp": "2026-03-02T10:30:05Z" } }/mediaList your uploaded media files with optional filtering by type. Results are paginated and sorted by creation date (newest first).
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
type | string | all | Filter by type: image, video, or document |
limit | integer | 25 | Number of items per page (1-100) |
offset | integer | 0 | Number of items to skip for pagination |
curl -X GET "https://app.posteverywhere.ai/api/v1/media?type=image&limit=2" \ -H "Authorization: Bearer pe_live_your_key_here"{ "data": { "media": [ { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "type": "image", "mime_type": "image/jpeg", "file_size": 2048576, "status": "ready", "original_name": "product-launch.jpg", "url": "https://cdn.posteverywhere.ai/media/a1b2c3d4.jpg", "thumbnail_url": "https://cdn.posteverywhere.ai/media/a1b2c3d4-thumb.jpg", "dimensions": { "width": 1080, "height": 1080 }, "aspect_ratio": "1:1", "orientation": "square", "created_at": "2026-03-02T10:30:00Z" }, { "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "type": "image", "mime_type": "image/png", "file_size": 3145728, "status": "ready", "original_name": "team-photo.png", "url": "https://cdn.posteverywhere.ai/media/b2c3d4e5.png", "thumbnail_url": "https://cdn.posteverywhere.ai/media/b2c3d4e5-thumb.png", "dimensions": { "width": 1920, "height": 1080 }, "aspect_ratio": "16:9", "orientation": "landscape", "created_at": "2026-03-01T15:45:00Z" } ], "pagination": { "limit": 2, "offset": 0 } }, "meta": { "request_id": "req_def456", "timestamp": "2026-03-02T12:00:00Z" } }/media/{id}Retrieve full details for a single media file by its UUID. Returns dimensions, status, file size, and processing information.
curl -X GET https://app.posteverywhere.ai/api/v1/media/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \ -H "Authorization: Bearer pe_live_your_key_here"{ "data": { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "type": "image", "mime_type": "image/jpeg", "file_size": 2048576, "status": "ready", "dimensions": { "width": 1080, "height": 1080 }, "aspect_ratio": "1:1", "orientation": "square", "created_at": "2026-03-02T10:30:00Z" }, "meta": { "request_id": "req_ghi789", "timestamp": "2026-03-02T12:05:00Z" } }/media/{id}Permanently delete a media file. This removes the file from storage and cannot be undone. Media currently attached to scheduled posts will still be published.
curl -X DELETE https://app.posteverywhere.ai/api/v1/media/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \ -H "Authorization: Bearer pe_live_your_key_here"{ "data": { "deleted": true, "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }, "meta": { "request_id": "req_jkl012", "timestamp": "2026-03-02T12:10:00Z" } }MediaItem schema
Every media object returned by the API follows this schema. Fields marked as nullable may be null while media is still processing.
| Field | Type | Nullable | Description |
|---|---|---|---|
id | uuid | No | Unique media identifier |
type | string | No | image, video, or document |
mime_type | string | No | MIME type of the file (e.g. image/jpeg) |
file_size | integer | No | File size in bytes |
status | string | No | processing, ready, or failed |
original_name | string | Yes | Original filename from upload request |
url | string | Yes | CDN URL of the processed media file |
thumbnail_url | string | Yes | CDN URL of the thumbnail (images and videos only) |
dimensions | object | Yes | { width: int, height: int } |
aspect_ratio | string | Yes | Computed aspect ratio (e.g. 16:9, 1:1) |
orientation | string | Yes | landscape, portrait, or square |
created_at | string | No | ISO 8601 timestamp of when the media was created |
Supported file types
PostEverywhere accepts the following file types. Each platform may have additional constraints — the API automatically validates and optimizes media for your target platforms.
| Type | Extensions | MIME types | Max size |
|---|---|---|---|
| Images | .jpg, .png, .gif, .webp | image/jpeg, image/png, image/gif, image/webp | 20 MB |
| Videos | .mp4, .mov | video/mp4, video/quicktime | 500 MB |
| Documents | application/pdf | 10 MB |
Frequently asked questions
What is the maximum file size for media uploads?
How long do presigned URLs last before they expire?
Can I upload multiple files in a single request?
What happens to media after it is uploaded?
Related documentation
Start uploading media
Get your API key and upload your first image in under 2 minutes.