Skip to main content
POST
Upload Content
This is the primary way to get content into ShortKit. Send metadata and get back signed upload URLs — your client uploads files directly to cloud storage, no proxying through your server. This endpoint accepts both publishable keys and secret keys, making it safe to call directly from mobile apps and browsers.
Building client-side uploads? A guide for integrating direct uploads into your app is coming soon.
Automatic captions and language detection. ShortKit generates captions for every video automatically — no configuration needed. Once processing completes, the detected language is stored as customMetadata.language (BCP 47 code, e.g. "en", "es"). You can use this field to filter the feed by language.

Request body

string
required
"video", "carousel", or "video_carousel".
string
required
Display title. Max 200 characters.
string
Optional description. Max 2000 characters.
string[]
Tags for categorization and filtering.
string
Editorial section (e.g., "Sports", "News"). Max 200 characters.
string
Content author name. Max 200 characters.
object
Arbitrary key-value pairs passed through to the feed.
boolean
When true, playback is gated behind a short-lived signed streaming URL and the item’s streamingUrl is withheld until one is issued. When omitted, defaults to your organization’s default. See Protected Content.
string
default:"other"
"ios_upload" or "other". Set to "ios_upload" for videos recorded on iOS devices to enable color-accurate thumbnail extraction. iOS HEVC recordings frequently omit color metadata, which can cause default first-frame thumbnails to render with incorrect colors. Marking the origin enables an alternate extraction path that infers the correct color space.Only applies to contentType: "video". No effect for image or video carousels. If you also render this content in a custom feed via the SDK, pair with the origin field on FeedInput.video.
string
ISO 8601 timestamp. Content won’t appear in the feed before this time.
string
ISO 8601 timestamp. Content is removed from the feed after this time.
object[]
Carousel only. Defines the image slots for the carousel. Each object can include:
  • position (integer) — Display order (0-indexed). Defaults to array index.
  • altText (string) — Accessibility text for the image.
The number of objects in this array determines how many signed upload URLs you receive.
number
Carousel only. Seconds between automatic image transitions.
string
A webhook URL that ShortKit will POST to as the content moves through the processing pipeline. Applies to "video" and "carousel" content types. See Callback events for payload shape and delivery behavior.

Uploading a video

Send a POST with contentType: "video" and your metadata. The response includes a signed uploadUrl — your client PUTs the video file directly to that URL.

For carousels, specify the image slots you need in the images array. The response returns a signed upload URL for each slot.

Video carousels are containers that reference existing video content items. Create the carousel first, then add videos to it.
Video carousels reference existing video content — the videos must already be uploaded and in ready status. Empty carousels are excluded from the feed.

Uploading in bulk

There is no batch upload endpoint — each content item requires its own POST /v1/content/upload call. To upload many items, make requests in parallel:
For bulk server-side ingestion from URLs (cloud storage, CMS, etc.), use Import instead — it accepts up to 100 items in a single request.

Callback events

When you provide a callbackUrl, ShortKit sends a POST request to that URL at each stage of processing. Your endpoint must respond with a 2xx status code to acknowledge receipt.

Video uploads

ShortKit delivers up to three callbacks per video upload: 1. content.imported with status: "processing" Sent when your file has been received and processing has begun. If a playbackId is present, store it alongside your content record — the video is already streamable at this point, though transcoding is not yet complete. Viewers of longer videos may experience buffering near the end until encoding finishes.
playbackId may be null in this callback if processing is still in its earliest stage. The ready callback always includes a non-null playbackId.
2. content.imported with status: "ready" Sent when transcoding completes and the video is fully available at all quality levels. The payload shape is identical to the processing callback, with status set to "ready". playbackId is always present. 3. content.import_failed with status: "error" Sent if processing fails. The payload includes an error field with a human-readable description of the failure. No playbackId is included.
A single callback fires once all images have been validated. The status is "ready" if at least one image processed successfully, or "errored" if all images failed. Only successfully processed images are included in the images array.
externalId reflects the value you provided on upload, or null if not set.

Retry behavior

Each callback is attempted up to 3 times. If your endpoint returns a non-2xx status or is unreachable, ShortKit retries after 1 second, then again after 5 seconds. If all three attempts fail, the callback is abandoned. Callbacks are fire-and-forget — a failed callback does not affect processing. If your endpoint was down and you missed a callback, you can always retrieve the current status by polling GET /v1/content/{id}.