Media
Upload files, list the media library, and attach media to a post.
Media endpoints use the posts scope, because media only exists to end up on a post.
Upload
POST /v1/media/uploadSend multipart/form-data with the files under the files field:
curl -X POST https://api.fopost.com/v1/media/upload \
-H "X-API-Key: $FOPOST_API_KEY" \
-F "[email protected]" \
-F "workspaceId=7d2b8c11-4e5a-4a8f-b0d9-3c5e6f7a8b90"| Limit | Value |
|---|---|
| Files per request | 5 |
| Size per file | Your account's limit, at most 100 MB on this route |
| Types | jpeg, png, gif, webp, mp4, mov, webm, pdf, txt, csv |
The declared type is verified against the actual file contents, so renaming an executable to .png does not get it through.
This route carries the whole request through the API's edge, which refuses any request body over 100 MB before it reaches FoPost. A file that large on this route gets the edge's own 413 page, not a FoPost error, so keep multipart under 100 MB per file and send anything bigger through direct upload, which has no such cap. Within 100 MB, a file over your account's limit answers 413 with file_too_large and max_file_bytes.
Pass workspaceId to also save the files to that workspace's media library, where they are reusable and count against the account's storage allowance. Leave it out for a one-off attachment.
Limits
GET /v1/media/limits?workspace_id=7d2b8c11-4e5a-4a8f-b0d9-3c5e6f7a8b90The largest file your account can upload grows with the number of connected accounts on the billing account:
| Connected accounts | Largest file |
|---|---|
| Up to 2 | 100 MB |
| Up to 7 | 400 MB |
| Up to 15 | 2 GB |
| 16 and more | 5 GB |
The Large Uploads add-on (Settings → Billing) lifts any account to 5 GB for a flat monthly fee. The endpoint answers the ceiling in force, what set it, the multipart ceiling, and whether direct upload is available:
{
"max_file_bytes": 419430400,
"source": "accounts",
"connected_accounts": 5,
"large_uploads_enabled": false,
"next_tier": { "up_to_accounts": 15, "max_file_bytes": 2147483648 },
"multipart_max_file_bytes": 104857600,
"max_files_per_upload": 5,
"direct_upload_available": true,
"allowed_types": ["image/jpeg", "image/png", "..."]
}Read it before an upload to pick the route and to show the person the real number. source is accounts, add_on, or bypass.
Direct upload
For anything over 100 MB, or a client that should not proxy bytes through your server, upload straight to storage through a signed URL. The bytes never pass through the API, so the only ceiling is your account's limit, up to 5 GB in one PUT. It is three calls.
1. Sign the upload.
POST /v1/media/presign{
"workspaceId": "7d2b8c11-4e5a-4a8f-b0d9-3c5e6f7a8b90",
"filename": "launch.mp4",
"mimeType": "video/mp4",
"size": 18350080
}folderId, brandRole, brandVoiceId, personConsent, and origin are accepted here too, with the same meaning as on upload, so the finished item lands exactly where a multipart upload would.
{
"upload_id": "b1a3…",
"upload_url": "https://…",
"method": "PUT",
"headers": { "Content-Type": "video/mp4" },
"expires_at": "2026-09-19T14:00:00.000Z",
"max_file_bytes": 419430400
}The same types apply as for upload, size is checked against your account's limit (413 file_too_large when over), and the storage allowance is checked here too. size is part of the signature, so the PUT is refused if the byte count differs.
2. PUT the bytes.
curl -X PUT "$UPLOAD_URL" -H "Content-Type: video/mp4" --data-binary @launch.mp4Send exactly the returned headers and no API key. The URL accepts one PUT and stops working after an hour.
3. Complete it.
POST /v1/media/presign/{upload_id}/completeCompletion verifies the object where it sits and promotes it into the library with the same checks as an upload: allowed type, content matching the declared type, size, storage allowance. It answers with the same item shape as upload, including preview_url. A refused object is deleted; 409 means the upload was already completed and 410 that it expired. An upload that is never completed is discarded after 24 hours and never appears in the library.
The SDKs wrap all three calls in one helper (media.uploadDirect or the language equivalent).
List the library
GET /v1/mediaReturns the workspace's library items with their type, name, size, and URL.
Delete
DELETE /v1/media/{id}Removes the item from the library and answers 204 with no body. Posts that already published with it are unaffected, since the network holds its own copy.
Attaching to a post
Two ways. A post can carry its files in the same request: send POST /v1/posts (or PUT /v1/posts/{id}) as multipart/form-data with the JSON body in a post field and the files under files. They are stored in the workspace library and attached to the first content block. The multipart ceiling of 100 MB per file applies; see publishing.
Or upload first and take what upload returns into a content block:
{
"content": [
{
"text": "Doors open Monday.",
"media": [
{
"type": "image",
"name": "launch.png",
"url": "https://...",
"alt": "A storefront with the lights coming on"
}
]
}
]
}type is image, video, or gif. alt is optional and worth sending: it is what screen readers announce, and several networks surface it.
Each network sets its own limits on count, dimensions, aspect ratio, and duration. FoPost resizes and re-encodes for the target where it can, and preflight tells you when it cannot.
Storage
The library counts against your account's free storage allowance; past it, storage is metered per GB per month with a card on file. A stored URL is an identity, not public access: the bucket is private, and the dashboard renders media through a per-request check rather than a link anyone can pass around.
Next
Related documentation
- API Overview
Base URL, envelopes, pagination, and errors for the FoPost REST API.
- Authentication
API keys, scopes, and workspace binding.
- Publishing
Create a post, target accounts, publish it, and read the per-account result.
- Scheduling
Schedule a post, repeat it, and import a batch from a spreadsheet.
- Validation
Check content, text length, and media against platform rules before a post exists.
- Blog
A keyword plan, articles written in the background, a review window, and a target they publish to.
- Blogs and Articles
Read and manage the articles and products that already live on a connected site.
- Accounts
List connected social accounts, check their health, and refresh credentials.