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:
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.