logo
Schedulin Developers

Manage media

Everything you upload or import lives in your workspace's media library. To add files, see Upload media; this page covers the rest.

Register a presigned upload

Files uploaded straight to storage with a presigned PUT (POST /v0/media/presign) aren't in the library until you register them. POST /v0/media/register records the uploaded object in place — no copy — and returns its media record; calling it again for the same key returns the same record.

curl -X POST https://api.schedulin.app/v0/media/register \
  -H "x-api-key: $SCHEDULIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "key": "<your-org>/launch.mp4", "name": "launch.mp4" }'
const media = await client.media.register({ key: "<your-org>/launch.mp4" });
media = client.media.register(key="<your-org>/launch.mp4")

From the CLI: schedulin media register <key>. See Upload media for the full presign → PUT → register flow.

Collect files from someone's device

When the file is on a user's phone or laptop (or pasted into a chat with your AI agent), create an upload link and hand it to them. The link opens a Schedulin page where they can drop files straight into your media library — no API key needed on their side.

curl -X POST https://api.schedulin.app/v0/media/upload-link \
  -H "x-api-key: $SCHEDULIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "expiresInHours": 24 }'
{
  "url": "https://…/upload/…",
  "expiresAt": "2026-06-02T15:00:00.000Z"
}
const link = await client.media.createUploadLink({ expiresInHours: 24 });
console.log(link.url);
link = client.media.create_upload_link(expires_in_hours=24)
print(link.url)

expiresInHours defaults to 24 (max 168, one week). Once the user says they're done, list media to find the new files and use their url in a post.

List and search media

GET /v0/media is paginated (page, limit up to 100) and returns the most recently updated items first. Filter with q (file name), type (image, video, or all), and tagIds. See Pagination.

curl "https://api.schedulin.app/v0/media?q=launch&type=image&limit=20" \
  -H "x-api-key: $SCHEDULIN_API_KEY"
const { items, totalPages } = await client.media.list({ q: "launch", type: "image", limit: 20 });
page = client.media.list(q="launch", type="image", limit=20)
for item in page.items:
    print(item.id, item.url)

Fetch a single item with GET /v0/media/{id} (client.media.retrieve).

Delete media

curl -X DELETE https://api.schedulin.app/v0/media/6f0c… \
  -H "x-api-key: $SCHEDULIN_API_KEY"

Deleting removes the media record and the file from storage. Copies already cached by the CDN may still be served from the old URL for a short while after the delete. Don't rely on the URL going dead immediately.

Media that is still attached to a post can't be deleted — the API returns 409 Conflict; remove it from those posts (or delete them) first.

Update media

PUT /v0/media/{id} updates a record's metadata (url, mimeType, width, height, size, duration) and returns the updated media record.