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.