Skip to content

Manage videos

Everything on this page uses the video API ⧉ under /api/v1/project/<project_id>/video. Ids are 64-bit integers serialized as strings in JSON.

The video lifecycle

Status Meaning
waiting_for_upload The video exists but its bytes haven't arrived (direct upload not completed, or the fetch still downloading).
queued The file is in and waiting for (or undergoing) encoding.
ready The essential renditions are playable — viewers can already watch while the higher qualities finish.
completed Every rendition is encoded.
errored Processing failed for good; details are in asset.errors.

Status changes fire the video.status_update webhook.

List videos

GET /api/v1/project/<project_id>/video

Query parameter Default Meaning
limit 20 Page size, 20–1000.
page Opaque page token; use pagination.next_page / prev_page from the previous response.
search Matches against title, description, and tags.
status Filter by one of the statuses above.
public true / false; omit for both.
user_id Filter by the uploading user.
include Embed sub-resources per video (see below).

Results are ordered newest first. The response is { "rows": [ …videos… ], "pagination": { "next_page": …, "prev_page": … } }. The list endpoint is rate-limited — don't poll it to track encoding.

Get a video, with ?include=

GET /api/v1/project/<project_id>/video/<video_id>

Sub-resources are embedded only on request, Stripe-style, via a comma-separated include:

GET …/video/<video_id>?include=presets,posters,text_tracks
include value Fills Contents
presets asset.presets Ready renditions, incl. static_mp4_link on the best one.
posters asset.posters Posters.
audio_tracks asset.audio_tracks Audio tracks.
text_tracks asset.text_tracks Text tracks.
storyboards asset.storyboards Storyboards.

A field is null when not requested and [] when requested but empty.

Useful top-level fields: link (the embed URL, signed when the video is private), hls_link (the HLS master playlist), permalink (your own canonical URL for the video — set by you, used for share links), and asset (duration, width/height, encoding tier, errors, original_link, and fast-clip provenance via source_asset_id / clip_ranges). The signed links expire after 24 hours by default — re-fetch the video for fresh ones.

Encoding progress

While a video is processing, the single-video response carries asset.encoding_progress — a map of preset id to a 0–1 fraction, so you can render a live per-rendition progress bar. It is null once encoding has finished and is never included in list responses.

Edit a video

POST /api/v1/project/<project_id>/video/<video_id> — send at least one field:

Field Constraints
title 1–64 characters.
description Up to 256 characters.
public true / false — see secure playback.
password Up to 32 characters. Several comma-separated passwords may be set; each unlocks the password-gated embed. Changing it also rotates the public MP4 URL.
permalink Your canonical URL for the video (up to 2048 characters).
tags List of tags, each up to 32 characters.
meta Arbitrary JSON object, up to 1 KB.
default_poster_id One of the video's poster ids — see posters.
swap_id See below.

Swap two videos' content

Editing with swap_id exchanges the content (the asset) of two videos while each keeps its id, title, embed link, and stats — useful for replacing a published video without breaking its links. Both videos must have completed status.

Delete a video

DELETE /api/v1/project/<project_id>/video/<video_id> — returns 204. The video and its stored files are removed.

A video that fast clips were made from can't be deleted while those clips exist (422 cant_delete_source_with_clips) — delete the fast clips first.