Media API
Media (images, video, documents) is uploaded via a presigned URL flow: the client requests a signed upload URL, PUTs the file directly to object storage, and then references the resulting media ID when creating a post.
Requires authentication.
Upload flow
1. Request a presigned upload URL ──► media record created (status: pending)
2. PUT the file to the presigned URL ──► file lands in storage (R2)
3. Reference mediaId in POST /v1/posts ──► media attached to the post
Files are stored in R2 and served back with full HTTP byte-range support, so videos stream and seek correctly.
Upload ceilings
Regardless of platform, the largest file accepted is:
| Type | Max size |
|---|---|
| Video | 5 GB |
| Images | 25 MB |
| Documents (PDF) | 100 MB |
Your plan may impose a lower ceiling (the per-plan
maxFileSize), and per-platform limits are often lower still. When media is
attached to a post, the destination platform's limits are enforced — see
Limits.
In posts
Reference uploaded media by ID in the mediaIds array when
creating a post. Order is preserved (sortOrder), which
matters for carousels and galleries.
{
"caption": "Behind the scenes",
"accountIds": ["acc_instagram"],
"mediaIds": ["med_01", "med_02", "med_03"]
}
Validation
When a post is created, each attached media asset is validated against the
destination platform's constraints for that post type — aspect ratio,
resolution, duration, bitrate, and file count. Mismatches return 400 with a
descriptive message before anything is published.
Local development
In local development (where the R2 binding is absent), a filesystem fallback
handles uploads at POST /api/upload and serves them from /api/uploads/*.
In production, always use the presigned URL flow. See the
media library guide for the user-facing details.
Related
- Posts API — attach
mediaIdshere. - Limits — per-platform media constraints.
- Media library — the user-facing counterpart.