Content

File uploads

Pre-signed S3 uploads

File uploads in OpenPost go directly to S3via pre-signed URLs. Files never pass through our servers, which means fast uploads and tight security. This page covers the upload flow and the edge cases you’ll hit.

Upload caps are 1 GB per video and 30 MB per image. These are product-wide ceilings and apply even when the target platform allows larger files — for anything bigger, upload natively on the platform.

Upload flow (3 steps)

1

Request a pre-signed URL

POST /v1/media/upload with filename, content type, and size. OpenPost responds with an S3 URL valid for 10 minutes.

curl
curl -X POST https://api.openpost.so/v1/media/upload \
  -H "Authorization: Bearer $OP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "launch-hero.mp4",
    "content_type": "video/mp4",
    "size": 48571204
  }'
json
{
  "id": "med_abc",
  "upload_url": "https://...s3.amazonaws.com/...",
  "upload_headers": { "Content-Type": "video/mp4" },
  "expires_at": "2026-04-20T14:10:00Z"
}
2

PUT the file to S3

Send the file directly. Include the headers from the response — S3 rejects uploads whose Content-Typedoesn’t match the pre-signed spec.

bash
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: video/mp4" \
  --data-binary @launch-hero.mp4
3

Reference the media ID in a post

The ID from step 1 is now usable in any post payload.

json
{
  "content": "Ship day video",
  "integrations": ["int_x_abc"],
  "media": ["med_abc"]
}
You don’t need a separate “finalize” call — OpenPost checks the S3 ETag when the media is first attached to a post. If the upload never completed, the post create returns a 400.

Multipart uploads for large files

For files over 500 MB, OpenPost returns a multipart upload URL set instead of a single PUT URL. Each part is uploaded independently. Resume on network failure.

Our Node SDK handles multipart transparently; if you’re rolling your own client, see AWS’s multipart guide.

Video transcoding

After upload, OpenPost runs the file through an internal transcoder if it’s not already in the right codec for each target channel. This happens asynchronously and usually takes 10-60 seconds for a 1-minute video. The post stays in scheduled status during transcoding.

Image processing

Images are not re-encoded unless they exceed a platform’s size or dimension caps. When they do, we downscale using sharp/libvips, preserving aspect and color profile.

Security

  • Pre-signed URLs are scoped to your workspace and to the single file you requested.
  • URLs expire in 10 minutes. Expired URLs return 403.
  • Files are stored in an S3 bucket with aws:kms encryption at rest.
  • Access to media assets in our CDN is authenticated via short-lived JWTs signed per workspace.
Last updated April 2026 Edit this page