Host images and videos with a presigned upload URL, then attach them to posts.
Posts reference media by URL. You can use any public http(s) URL, or host files on BetterPost in two steps: ask
for a presigned upload URL, then PUT the raw file to it.
curl -s -X POST https://api.betterpost.dev/v1/media/upload \
-H "x-access-key: $BETTERPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "filename": "launch.mp4", "mimeType": "video/mp4", "size": 18874368 }'{
"success": true,
"data": {
"uploadUrl": "https://example-account.r2.cloudflarestorage.com/betterpost/proj_123/2026/10/med_4k8d2n6q0s3v7x1z5b9c2f4h-launch.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900&X-Amz-Signature=...",
"publicUrl": "https://assets.betterpost.dev/proj_123/2026/10/med_4k8d2n6q0s3v7x1z5b9c2f4h-launch.mp4"
}
}filename (required): used in the stored path. Characters other than letters, digits, ., _ and - become
_; it is cut to 100 characters.mimeType (required): must be image/* or video/*, otherwise 400 unsupported_mime_type.size (required, bytes; sizeBytes is accepted as an alias): checked against your storage limit up front and
signed into the URL, so the upload must be exactly that many bytes. Leaving it out returns 400
size_required. Unlike PostPeer, where the size is optional, BetterPost requires it so every upload is capped.curl -s -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--data-binary @launch.mp4Content-Type as mimeType.size in bytes (curl --data-binary sets Content-Length for you).{ "mediaItems": [{ "type": "video", "url": "https://assets.betterpost.dev/proj_123/2026/10/med_4k8d2n6q0s3v7x1z5b9c2f4h-launch.mp4" }] }| Plan | Storage |
|---|---|
| Free | 100 MB |
| Starter, Standard, Pro | 5 GB |
The limit covers all projects of your account, counting the declared size of every upload URL you have requested
(including files not uploaded yet). An upload that would go over the limit is refused up front with 413
storage_limit_exceeded.
Free up space with DELETE /v1/media:
curl -s -X DELETE https://api.betterpost.dev/v1/media \
-H "x-access-key: $BETTERPOST_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://assets.betterpost.dev/proj_123/2026/10/med_4k8d2n6q0s3v7x1z5b9c2f4h-launch.mp4" }'{ "success": true, "freedBytes": 18874368 }Media uploads and deletes are free. AI agents using the MCP server cannot PUT files, so they
use the upload_media_from_url tool instead, which copies a public https file (up to 25 MB) into storage.
Reference: POST /v1/media/upload, DELETE /v1/media.