Upload media
Media is attached to posts by url. There are three ways to get a media url, in
increasing order of effort — pick the first one that fits your client.
Option A — Upload a file directly (one call)
Send the raw bytes as multipart/form-data to POST /v0/media/upload. The server stores
the file and returns the media record; use its url in your post.
curl -X POST https://api.schedulin.app/v0/media/upload \ -H "x-api-key: sk_live_..." \ -F "file=@launch.jpg" \ -F "alt=Launch day"
{ "id": "med_123", "url": "https://r2.schedulin.app/<your-org>/<id>-launch.jpg", "...": "..." }
Accepts image, video, and audio up to 250 MB. SVG and other active content is rejected.
Option B — Import from a public URL
If the file is already hosted somewhere public, let the server fetch it with
POST /v0/media/from-url — no bytes leave your machine:
curl -X POST https://api.schedulin.app/v0/media/from-url \ -H "x-api-key: sk_live_..." \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/launch.jpg" }'
You can also skip this step entirely and pass a public url straight into the post's
media array — POST /v0/posts imports any external URL for you automatically.
Option C — Presigned upload (large files / direct-to-storage)
For direct-to-storage uploads, request a presigned PUT from POST /v0/media/presign
(contentType and key required), upload the bytes yourself, then reference the file URL:
# 1. presign curl -X POST https://api.schedulin.app/v0/media/presign \ -H "x-api-key: sk_live_..." \ -H "Content-Type: application/json" \ -d '{ "contentType": "image/jpeg", "key": "launch.jpg", "size": 248173 }' # → { "url": "https://<bucket>.r2.cloudflarestorage.com/...", "key": "<your-org>/launch.jpg", "method": "PUT" } # 2. upload the raw bytes to the returned url curl -X PUT "<url>" -H "Content-Type: image/jpeg" --data-binary @launch.jpg
The public file URL is https://r2.schedulin.app/<key>. The key does not exist until the
PUT completes — POST /v0/posts rejects a key whose bytes were never uploaded.
Attach it to a post
Whichever option you used, put the resulting url in the media array:
curl -X POST https://api.schedulin.app/v0/posts \ -H "x-api-key: sk_live_..." \ -H "Content-Type: application/json" \ -d '{ "socialAccountId": "acc_123", "caption": "Behind the scenes 📸", "media": [{ "url": "https://r2.schedulin.app/<your-org>/<id>-launch.jpg" }], "action": "now" }'