REST API

Media

Three calls to attach an image.

Files go straight from you to storage. They never pass through our API, so a large upload does not sit in a request.

POST/v1/media/presign

Ask for an upload URL and a media id.

NameTypeDescription
fileNameRequiredstringOriginal file name.
contentTypeRequiredstringimage/jpeg, image/png, image/webp, image/gif
bytesRequirednumberFile size in bytes.
widthnumberPixel width, if you know it.
heightnumberPixel height, if you know it.
altTextstringWhat the image shows, for screen readers. Applied to carousel items.
aiGeneratedbooleantrue when the file was generated or substantially changed with AI. Naver Blog photos get the AI usage label, and Instagram, YouTube and TikTok get their AI declaration unless the post sets it to false.

What comes back

NameTypeDescription
idstringPass this to publish as a mediaId.
uploadUrlstringOne-time PUT target.
contentTypestringSend exactly this on the PUT.
expiresInnumberSeconds the uploadUrl stays valid.
mediaExpiresAtstringISO 8601. After this the media id is reclaimed if it was never published.
# 1. ask for a slot
curl -X POST https://api.uplika.com/v1/media/presign \
  -H "authorization: Bearer $UPLIKA_KEY" \
  -H "content-type: application/json" \
  -d '{"fileName":"cover.jpg","contentType":"image/jpeg","bytes":184320,"altText":"A cat on a windowsill"}'
# -> { "id": "med_01H...", "uploadUrl": "https://...", "mediaExpiresAt": "2026-08-12T..." }

# 2. send the bytes straight to storage (no auth header)
curl -X PUT "$UPLOAD_URL" -H "content-type: image/jpeg" --data-binary @cover.jpg

# 3. confirm
curl -X POST https://api.uplika.com/v1/media/med_01H.../complete \
  -H "authorization: Bearer $UPLIKA_KEY"

Upload the bytes

PUT the file to the uploadUrl with the same Content-Type you declared. No auth header. The URL is already signed and it expires.

POST/v1/media/{id}/complete

Confirm the upload. We check the object really exists.

DELETE/v1/media/{id}

Remove a media item you uploaded by mistake. Anything a post still uses, or an original a copy in another workspace still shares, answers 409.

PATCH/v1/media/{id}

Mark or clear the AI-made flag. Every copy of the same file in your workspaces follows. Posts already out do not change.

NameTypeDescription
aiGeneratedRequiredbooleantrue when the file was generated or substantially changed with AI. Naver Blog photos get the AI usage label, and Instagram, YouTube and TikTok get their AI declaration unless the post sets it to false.

What if the file is already on the web?

Agents without a shell cannot PUT bytes, so the three step upload is out of reach for them. Give us the URL instead and we download the file, copy it into our storage and hand back a media id. We never pass someone else’s URL on to the channel. https only, and Google Drive or Dropbox share links do not work because they return an HTML preview instead of the file.

POST/v1/media/from-url

Copy a public file into your workspace in one call.

NameTypeDescription
urlRequiredstringPublic https URL of the file itself.
altTextstringWhat the image shows, for screen readers.
aiGeneratedbooleantrue when the file was generated or substantially changed with AI. Naver Blog photos get the AI usage label, and Instagram, YouTube and TikTok get their AI declaration unless the post sets it to false.

What we accept

NameTypeDescription
typesimageimage/jpeg, image/png, image/webp, image/gif
sizeimageup to 20MB
aspect ratioimageup to 20:1 (any pixel width)
countimageup to 20 per post on Threads
typesvideovideo/mp4, video/quicktime, video/webm
sizevideoup to 8192MB
lengthvideoup to 43200 seconds
widthvideoup to 4096px
carouselmixed2-20 items on Threads, images and video can be mixed

Common questions

How many calls does one image take?

Three. Presign for an id and an upload URL, PUT the bytes to that URL, then complete to confirm. Only after the third can publish use the id.

Does the file go through your API?

No. It goes straight from you to storage on a signed URL, so a large upload never sits inside one of our requests.

Can I put an image and a video in the same post?

On Threads, yes, in a carousel of two to twenty items. A channel that cannot mix them keeps the video and drops the images, and the target's warning says so. The limits endpoint tells you which channels mix.