The video object
The video object is a JSON object with the following properties:
{
"id": string,
"status": "COMPLETE" | "PROGRESSING" | "REPLACING" | "NO_FILE" | "ERROR",
"statusProgress": number,
"errorCode": string | null,
"errorMessage": string | null,
"visibility": "public" | "private",
"v": number,
"title": string,
"description": string,
"duration": number,
"fps": number,
"orientation": "landscape" | "portrait",
"language": string,
"aiContent": "none" | "generated" | "modified",
"src": {
"thumbnails": [
{
"name": "2160p" | "1440p" | "1080p" | "720p" | "480p" | "360p" | "240p",
"width": number,
"height": number,
"formats": {
"jpeg": { "url": string, "fileSize": number },
"webp": { "url": string, "fileSize": number }
}
},
[...]
],
"thumbnailUrl": string, // DEPRECATED — use src.thumbnails instead
"filename": string,
"abr": {
"resolution": "auto",
"description": "Adaptive Bitrate Streaming (ABR)",
"url": string, // .m3u8 playlist file
"maxWidth": number,
"maxHeight": number
},
"hls": [
{
"name": "2160p" | "1440p" | "1080p" | "720p" | "540p" | "360p" | "240p",
"url": string, // .m3u8 playlist file
"width": number,
"height": number
},
[...]
],
"mp4": [
{
"name": "2160p" | "1440p" | "1080p" | "720p" | "540p" | "360p" | "240p",
"url": string, // .mp4 file
"width": number,
"height": number
},
[...]
],
"audio": [
{
"name": string, // for example "high-quality" or "low-quality"
"url": string
},
[...]
]
},
"texttracks": [
{
"id": string,
"language": "en-US" | "de-DE" | "...", // region locale
"filename": string,
"type": "subtitles" | "captions",
"url": string,
"autoGenerated": boolean,
"autoTranslated": boolean,
"edited": boolean,
"updatedAt": Date,
"content": string // URL-encoded placeholder. GET the track for the WebVTT.
},
[...]
],
"chapters": [
{
"id": string,
"title": string,
"timestamp": string, // 00:00:00
},
[...]
],
"categories": [
{
"id": string,
"title": string,
"slug": string,
"description": string,
},
[...]
],
"tags": [
{
"id": string,
"title": string,
"slug": string,
"description": string,
},
[...]
],
"transcriptions": [
{
"language": string, // locale in de-DE format
"autoGenerated": boolean,
"text": string, // plain text transcript
"segments": [
{
"startTime": number, // in seconds
"endTime": number, // in seconds
"text": string
},
[...]
],
},
[...]
],
"audiotracks": [ ... ], // present on the object; ignored by PATCH
"autoTranscription": {
"autoStart": boolean,
"lastUpdatedAt": Date,
"data": object // transcription records; population follows depth
},
"contentUpdatedAt": Date, // bumped on content writes; not writable
"customMetadata": object,
"passwordProtection": {
"enabled": boolean,
"password": string // present for callers who can update the video
},
"previewVideoUrl": string,
"previewThumbnailUrl": string,
"previewThumbnailUrlSmall": string,
"player": {
"selectedPreset": object | null, // player preset object
"useCustomDesign": boolean,
"playerDesign": { ... }, // player design properties, see "Player settings"
"shareUrl": string
},
"workspace": string, // workspace id; stays an id at every depth
"createdAt": Date,
"updatedAt": Date
}aiContent
AI content tag for AI-generated or AI-modified content that could appear authentic, as required by regulations such as the EU AI Act (Art. 50). none (default) means the embed player never shows the AI label. generated and modified show the AI label in the player when the player design option aiContentLabel is not off.
v
File version. It starts at 0 and increments when a replacement file finishes encoding.
autoTranscription
autoTranscription is a single object with autoStart, lastUpdatedAt, and data. autoStart is whether transcription starts after encoding. data holds the related transcription records, and its population follows depth. Videos longer than 3 hours produce multiple transcription jobs. Poll transcribe for those job records.
contentUpdatedAt
Timestamp bumped on content writes. You cannot set this field.
customMetadata
A flat object of custom data, with at most 50 keys. Each key matches ^[a-zA-Z0-9_-]+$ and is at most 40 characters. Each value is a string of at most 500 characters, a finite number, or a boolean. Nested objects and arrays are rejected. A later write merges onto the stored object. Sending "" or null for a key deletes that key. You can set it when you create or update a video.
passwordProtection
enabled is whether the video requires a password. password is included for callers who can update the video, when the workspace has password protection enabled. On update, password must be at least 8 characters. The field is writable only while that feature is on.
categories and tags
At the default depth each entry is an object with id, title, slug, and description. With depth=0 each entry is an id. An empty list is null.
Preview URLs
previewVideoUrl, previewThumbnailUrl, and previewThumbnailUrlSmall are signed preview URLs. They are added on read when renditions exist.
Player settings
The player property contains the player design of the video. It is only included in responses to requests with an API key. Webhook payloads do not include it.
| Property | Description |
|---|---|
selectedPreset | The player preset that is assigned to the video, or null. |
useCustomDesign | If true, the video uses its own playerDesign instead of the preset. |
playerDesign | The player design of the video. It has the same properties as a player preset. The embed player setup describes each setting. |
shareUrl | The URL of the embed player for this video on your workspace domain. Use it as the src of an iframe or as a share link. |
selectedPreset and useCustomDesign are only included if your plan includes custom player designs and the workspace has at least one player preset.
To find the design that the player uses:
- If
useCustomDesignistrueorselectedPresetisnull, useplayerDesign. - Otherwise, use the design properties of
selectedPreset.
Encoding status
These fields describe the encoding lifecycle after you upload or replace a video file.
Typical lifecycle
- After you create a video object,
statusisNO_FILEuntil a file is uploaded. - After the file upload finishes, encoding starts and
statusbecomesPROGRESSING.statusProgressmoves from0toward100. - On success,
statusbecomesCOMPLETE,statusProgressis100, and playback sources are available undersrc. - On failure,
statusbecomesERROR. ReaderrorCodeanderrorMessagefor details.
When you replace a video, status briefly becomes REPLACING while the new file is uploaded, then follows the same PROGRESSING → COMPLETE / ERROR path.
status
| Value | Description |
|---|---|
NO_FILE | The video object exists, but no file has been uploaded yet |
PROGRESSING | Encoding is in progress |
REPLACING | A new file is being uploaded to replace the existing video |
COMPLETE | Encoding finished successfully; playback sources are available under src |
ERROR | Encoding failed |
statusProgress
Encoding progress as a percentage from 0 to 100.
While status is PROGRESSING, poll GET /api/videos/[VIDEO_ID] (see get video) and read statusProgress to show progress in your UI. A poll interval of a few seconds is usually enough.
You can also subscribe to video.updated webhooks. Progress updates can fire often during encoding, so debounce UI updates if needed. See Webhooks.
When encoding completes, status becomes COMPLETE and statusProgress is 100.
errorCode and errorMessage
When status is ERROR, these fields explain the failure. Prefer errorCode for programmatic handling. Use errorMessage as a human-readable fallback when you do not map the code yourself.
Both fields are null (or absent) when the video is not in an error state.
Example when encoding fails:
{
"id": "[VIDEO_ID]",
"status": "ERROR",
"statusProgress": 42,
"errorCode": "MEDIACONVERT_1040",
"errorMessage": "Invalid or unsupported file format"
}errorCode | Description |
|---|---|
DURATION_LIMIT_EXCEEDED | Video duration exceeds your account limit |
UNKNOWN_ERROR | An unknown error occurred during processing |
MEDIACONVERT_1040 | Invalid or unsupported file format |
MEDIACONVERT_1041 | Input file is corrupted or incomplete |
MEDIACONVERT_1050 | Video codec not supported |
MEDIACONVERT_1060 | Audio codec not supported |
MEDIACONVERT_1071 | Invalid video resolution or aspect ratio |
MEDIACONVERT_3000 | Service temporarily unavailable; try again later |
Additional errorCode values may appear over time. Always fall back to errorMessage (or a generic failure message) for unknown codes.
Thumbnails
src.thumbnails
Multi-resolution variants of the currently active thumbnail. The array is sorted by width descending (highest resolution first). Only sizes equal to or smaller than the source image are generated. Available resolutions: 2160p, 1440p, 1080p, 720p, 480p, 360p, 240p.
{
"name": "2160p" | "1440p" | "1080p" | "720p" | "480p" | "360p" | "240p",
"width": number,
"height": number,
"formats": {
"jpeg": { "url": string, "fileSize": number },
"webp": { "url": string, "fileSize": number }
}
}Each resolution variant is available in both JPEG and WebP format. Use formats.webp.url for smaller file sizes or formats.jpeg.url for maximum compatibility. To get the highest resolution thumbnail, use src.thumbnails[0].formats.jpeg.url (or .webp.url). To select a specific resolution, filter the array by name, width, or height.
src.thumbnailUrl (deprecated)
Deprecated — Use src.thumbnails instead. This field will be removed in a future version.
Contains the URL of the 1080p variant (or highest available) of the currently active thumbnail. Automatically updated whenever the thumbnail changes.
Thumbnail lifecycle
| Event | src.thumbnails | src.thumbnailUrl |
|---|---|---|
| Video processing completes | Populated with generated variants | Set to 1080p (or highest available) variant |
| Custom thumbnail uploaded | Replaced with new variants | Updated to 1080p (or highest available) variant |
| Thumbnail from timestamp | Replaced with new variants | Updated to 1080p (or highest available) variant |
| Thumbnail reset | Restored to auto-generated variants | Restored to 1080p (or highest available) variant |
Video sources
Video src arrays
The hls and mp4 arrays contain a list of all available video sources for the video. The arrays are ordered by quality, starting with the highest quality. Video variants are generated up to the input videos resolution. So an uploaded 1080p video will not have a 2160p and 1440p variant.
{
"name": "2160p" | "1440p" | "1080p" | "720p" | "540p" | "360p" | "240p",
"url": string,
"width": number,
"height": number
}Adaptive Bitrate Streaming (ABR)
If you want to provide your videos via adaptive bitrate streaming (abbreviated ABR), you can do so by using the src.abr.url as your video source. The playlist file provides all provided video qualities listed in the src.hls array.
src.audio
src.audio lists the audio renditions for the video. Each entry has name and url. name is a label such as high-quality or low-quality.