Videos API
Upload, manage, and retrieve video content programmatically. Supports file uploads, URL imports, browser uploads, and full video lifecycle management.
Upload Video via URL
/videosImport a video from an external URL. The video will be downloaded and transcoded automatically. Use the upload base URL for this endpoint.
Headers
| Parameter | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Required | Bearer token. Format: Bearer YOUR_API_KEY |
| Content-Type | string | Required | Must be application/json |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| url | string | Required | Public URL of the video file to import |
| title | string | Optional | Title for the videoDefault: Untitled |
| channelKey | string | Optional | Channel key to associate the video with |
| projectId | string | Optional | Project ID to organize the video under |
| description | string | Optional | Video description |
| tags | string[] | Optional | Array of tags for categorization |
| options | object | Optional | Video playback options (autoplay, loop, muted, etc.) |
{
"id": "fFL56RU6PjvJPeE",
"title": "My Imported Video",
"channelKey": "f8RMr2q4h6yNpv9",
"status": 1,
"created": "2024-01-15T10:30:00Z",
"iframeLink": "https://streamvault.one/embed/fFL56RU6PjvJPeE",
"hlsLink": "https://api.streamvault.one/v1/play/fFL56RU6PjvJPeE/master.m3u8",
"privateLink": "https://streamvault.one/v/fFL56RU6PjvJPeE",
"duration": null,
"image": {
"xsUrl": "",
"smUrl": "",
"mdUrl": "",
"lgUrl": ""
}
}{
"error": "url is required",
"code": "INVALID_REQUEST"
}{
"error": "Video upload limit reached for your plan",
"code": "QUOTA_EXCEEDED",
"limit": 50,
"current": 50
}/videoscurl -X POST "https://api.streamvault.one/v1/videos" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/video.mp4",
"title": "Untitled"
}'Browser Upload
/videos/browserGet a tokenized upload URL for direct browser-based uploads using TUS protocol. Returns credentials for chunked resumable upload.
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | Optional | Title for the videoDefault: Untitled |
| projectId | string | Optional | Project ID to organize the video under |
{
"video_id": "a1b2c3d4e5",
"library_id": "12345",
"tus_endpoint": "https://video.bunnycdn.com/tusupload",
"auth_signature": "sha256-signature-hash",
"auth_expiration_time": 1704067200,
"put_upload_url": "https://video.bunnycdn.com/library/12345/videos/a1b2c3d4e5"
}/videos/browsercurl -X POST "https://api.streamvault.one/v1/videos/browser" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Untitled"
}'List Videos
/videosRetrieve a paginated list of the videos in your account, newest first by default. Page with page and size, order with sort, and narrow to one project with projectId (or to a project and everything below it with includeSubprojects).
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| page | integer | Optional | Page number, starting at 1Default: 1 |
| size | integer | Optional | Videos per page, 1 to 100 (a larger value is lowered to 100). limit is accepted as another name for it.Default: 20 |
| sort | string | Optional | created_at, updated_at, name or sort_order; put a minus in front for descending (-name). An unknown field sorts by created_at.Default: -created_at |
| projectId | string | Optional | Only the videos in this project (its id). Videos in its sub-projects are not included unless includeSubprojects is true. |
| includeSubprojects | boolean | Optional | true: also list the videos of every sub-project below projectId (a project plus up to 149 sub-projects). Needs projectId.Default: false |
| channelKey | string | Optional | Accepted, but it does not filter: every video comes back whatever you send. Narrow the list with projectId, and read channelKey on each video. |
There is no server-side title search and no status filter on this endpoint. Parameters it does not know (search, status, orderBy, itemsPerPage) are ignored, not rejected: page through with page and size and filter on your side. The answer carries total, the number of videos that match, so you know when you have them all.
Every video in the list carries projectId, the project it sits in. With includeSubprojects=true the answer also has includeSubprojects: true and projectCount (the projects covered). See Listing sub-projects for the full answer and the limits.
{
"items": [
{
"videoKey": "fFL56RU6PjvJPeE",
"videoId": "fFL56RU6PjvJPeE",
"channelKey": "f8RMr2q4h6yNpv9",
"projectId": "40e78621-c780-4224-94fc-20a831110d91",
"privateLink": null,
"iframeLink": "fFL56RU6PjvJPeE",
"name": "Product Demo",
"description": null,
"duration": 150,
"thumbnailUrl": "https://api.streamvault.one/v1/play/fFL56RU6PjvJPeE/poster.jpg",
"posterUrl": "https://api.streamvault.one/v1/play/fFL56RU6PjvJPeE/poster.jpg",
"availableThumbnails": [
"https://api.streamvault.one/v1/play/fFL56RU6PjvJPeE/thumbs/thumb_01.jpg"
],
"embedWidth": 640,
"embedHeight": 360,
"isPublic": true,
"storageLocation": "b2",
"status": { "state": "ready" },
"created": "2024-01-15T10:30:00+00:00",
"modified": "2024-01-15T10:35:12+00:00"
}
],
"page": 1,
"size": 20,
"total": 42
}duration is in seconds; status.state is processing, ready or failed. A page past the last one is an empty items array that still carries the real total.
/videoscurl -X GET "https://api.streamvault.one/v1/videos" \ -H "Authorization: Bearer YOUR_API_KEY"
Get Video
/videos/{id}Retrieve a single video: its keys, project, links, thumbnails, player size and processing state. The same fields as one entry of List Videos.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The video's id or key (videoId / videoKey) |
{
"videoKey": "fFL56RU6PjvJPeE",
"videoId": "fFL56RU6PjvJPeE",
"channelKey": "f8RMr2q4h6yNpv9",
"projectId": "40e78621-c780-4224-94fc-20a831110d91",
"privateLink": null,
"iframeLink": "fFL56RU6PjvJPeE",
"name": "Product Demo",
"description": "A walkthrough of our product features",
"duration": 150,
"thumbnailUrl": "https://api.streamvault.one/v1/play/fFL56RU6PjvJPeE/poster.jpg",
"posterUrl": "https://api.streamvault.one/v1/play/fFL56RU6PjvJPeE/poster.jpg",
"availableThumbnails": [
"https://api.streamvault.one/v1/play/fFL56RU6PjvJPeE/thumbs/thumb_01.jpg"
],
"embedWidth": 640,
"embedHeight": 360,
"isPublic": true,
"storageLocation": "b2",
"status": { "state": "ready" },
"created": "2024-01-15T10:30:00+00:00",
"modified": "2024-01-15T10:35:12+00:00"
}{
"ok": false,
"error": "not found"
}/videos/{id}curl -X GET "https://api.streamvault.one/v1/videos/{id}" \
-H "Authorization: Bearer YOUR_API_KEY"Get Video Status
/videos/{id}/statusCheck the transcoding/processing status of a specific video. Useful for polling after upload.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The unique video identifier |
{
"id": "fFL56RU6PjvJPeE",
"status": 2,
"statusLabel": "Processing",
"encodeProgress": 65,
"message": "Transcoding in progress"
}| Status | Value | Description |
|---|---|---|
| Na | 0 | Not available |
| Uploaded | 1 | File uploaded, waiting to process |
| Processing | 2 | Transcoding in progress |
| Published | 3 | Ready for playback |
| Error | -1 | Transcoding failed |
| Deleted | 50 | Deleted |
/videos/{id}/statuscurl -X GET "https://api.streamvault.one/v1/videos/{id}/status" \
-H "Authorization: Bearer YOUR_API_KEY"Update Video
/videos/{id}Update video metadata, options, access controls, and configuration.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The unique video identifier |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | Optional | New title for the video |
| description | string | Optional | New description |
| tags | string[] | Optional | Updated tags array |
| projectId | string | Optional | Move to a different project |
| options | object | Optional | Playback options: autoplay, loop, muted, controls, pip, stickyOnScroll |
| allowedDomains | string[] | Optional | Domains allowed to embed this video |
| allowedCountries | string[] | Optional | ISO country codes allowed to view |
| blockedCountries | string[] | Optional | ISO country codes blocked from viewing |
| password | string | Optional | Set a password for protected playback |
| requireAuth | boolean | Optional | Require viewer authentication |
| maxViews | integer | Optional | Maximum allowed view count |
| expiresAt | datetime | Optional | ISO 8601 expiration timestamp |
| skinId | string | Optional | Legacy saved-skin id. It only touches loading color, background, corner radius and a corner logo; to style the player use PATCH /videos/{id}/player-settings |
{
"id": "fFL56RU6PjvJPeE",
"title": "Updated Title",
"description": "Updated description",
"tags": ["updated", "demo"],
"status": 3,
"updated": "2024-01-16T08:00:00Z"
}/videos/{id}curl -X PUT "https://api.streamvault.one/v1/videos/{id}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Title"
}'Delete Video
/videos/{id}Permanently delete a video and all associated data (captions, chapters, CTAs, analytics).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The unique video identifier |
{
"success": true,
"message": "Video deleted successfully"
}{
"error": "Video not found",
"code": "NOT_FOUND"
}/videos/{id}curl -X DELETE "https://api.streamvault.one/v1/videos/{id}" \
-H "Authorization: Bearer YOUR_API_KEY"Copy CTA
/videos/{id}/cta/copyCopy all call-to-action overlays from one video to one or more target videos.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | Source video ID to copy CTAs from |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| targetVideoIds | string[] | Required | Array of video IDs to copy CTAs to |
{
"success": true,
"copied": 3,
"targetVideoIds": ["vid_1", "vid_2", "vid_3"]
}/videos/{id}/cta/copycurl -X POST "https://api.streamvault.one/v1/videos/{id}/cta/copy" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"targetVideoIds": []
}'Move Videos Between Projects
/videos/change-projectMove one or more videos to a different project.
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| videoIds | string[] | Required | Array of video IDs to move |
| projectId | string | Required | Target project ID |
{
"success": true,
"moved": 2,
"projectId": "proj_target123"
}/videos/change-projectcurl -X POST "https://api.streamvault.one/v1/videos/change-project" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"videoIds": [],
"projectId": ""
}'Get Original File
/videos/{id}/original-fileGet a temporary signed URL to download the original uploaded video file.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The unique video identifier |
{
"url": "https://cdn.streamvault.one/original/fFL56RU6PjvJPeE/video.mp4?token=abc&expires=1704067200",
"expiresAt": "2024-01-15T12:00:00Z"
}/videos/{id}/original-filecurl -X GET "https://api.streamvault.one/v1/videos/{id}/original-file" \
-H "Authorization: Bearer YOUR_API_KEY"Get Collected Emails
/videos/collected-emailsRetrieve all emails collected via email gates on your videos from the last 365 days.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| videoId | string | Optional | Filter by specific video ID |
| channelId | string | Optional | Filter by specific channel ID |
{
"emails": [
{
"email": "viewer@example.com",
"videoId": "fFL56RU6PjvJPeE",
"channelId": "ch_abc123",
"subscribedAt": "2024-01-15T10:30:00Z"
}
],
"total": 150
}/videos/collected-emailscurl -X GET "https://api.streamvault.one/v1/videos/collected-emails" \ -H "Authorization: Bearer YOUR_API_KEY"
Create Expirable Link
/videos/{id}/expirable-linkGenerate a time-limited playback link with optional view count limits and geo-restrictions.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The unique video identifier |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| expiresAt | datetime | Required | ISO 8601 expiration timestamp |
| maxViews | integer | Optional | Maximum number of views allowed |
| allowedCountries | string[] | Optional | ISO country codes allowed |
| blockedCountries | string[] | Optional | ISO country codes blocked |
{
"id": "link_abc123",
"token": "f4a8c2e1d3b5a7c9",
"url": "https://streamvault.one/embed/fFL56RU6PjvJPeE?token=f4a8c2e1d3b5a7c9",
"expiresAt": "2024-02-15T00:00:00Z",
"maxViews": 100,
"viewCount": 0
}/videos/{id}/expirable-linkcurl -X POST "https://api.streamvault.one/v1/videos/{id}/expirable-link" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"expiresAt": "2024-12-31T23:59:59Z"
}'Update Thumbnail
/videos/image/{id}Set a video's thumbnail from an image you upload, or from the address of an image. Accepts JPEG, PNG or WebP files up to 5MB.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The video identifier: the id Get Video and List Videos give. The video's asset id and its short key work too. |
Body (multipart/form-data) - send a file or a url
| Parameter | Type | Required | Description |
|---|---|---|---|
| file | file | Optional | Image file (JPEG, PNG or WebP, max 5MB), sent with its image content type. curl -F sets it from the file extension. |
| url | string | Optional | Instead of a file: the public address of a JPEG, PNG or WebP image (max 5MB). The API downloads it. Ignored when a file is sent. |
The request must be a form (multipart/form-data; a plain url= form body works too). An image sent as the raw request body is not accepted. The answer is just { "ok": true }: the address of the new picture is the video's thumbnailUrl (see Get Video), and the same address is its posterUrl. Upload again to replace the picture: the address changes (it ends in ?v=...), so the new picture shows straight away instead of the old one being served from cache. A thumbnail you set here belongs to the file that is playing now: replacing the video's file (Replace Video) brings a generated thumbnail for the new file.
{
"ok": true
}{
"ok": false,
"error": "unsupported format (jpeg/png/webp only)"
}Other 400 answers: file too large (max 5MB), file or url required, failed to fetch url: 404 (the status your url answered), multipart parse failed (the request was not a form). 401 without a valid key; 404 for a video that is not yours.
# Upload a file curl -X PUT "https://api.streamvault.one/v1/videos/image/fFL56RU6PjvJPeE" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "file=@/path/to/thumbnail.jpg" # ...or let the API download an image curl -X PUT "https://api.streamvault.one/v1/videos/image/fFL56RU6PjvJPeE" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "url=https://example.com/thumbnail.jpg" # The new address curl "https://api.streamvault.one/v1/videos/fFL56RU6PjvJPeE" -H "Authorization: Bearer YOUR_API_KEY" # -> thumbnailUrl
Add Captions
/videos/captions/{id}Upload an SRT or VTT subtitle file for a video.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | string | Required | The unique video identifier |
Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| language | string | Required | ISO 639-1 language code (e.g. en, es, fr) |
| label | string | Optional | Display label for the caption trackDefault: English |
| srtContent | string | Required | SRT or VTT content as string |
| isDefault | boolean | Optional | Set as the default caption trackDefault: false |
{
"id": "cap_xyz789",
"videoId": "fFL56RU6PjvJPeE",
"language": "en",
"label": "English",
"isDefault": true
}/videos/captions/{id}curl -X POST "https://api.streamvault.one/v1/videos/captions/{id}" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"language": "en",
"label": "English",
"srtContent": "1\n00:00:00,000 --> 00:00:05,000\nHello World",
"isDefault": true
}'Delete Captions
/videos/captionsRemove a caption track from a video.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| videoId | string | Required | The video identifier |
| captionsId | string | Required | The caption track identifier |
{
"success": true,
"message": "Caption track deleted"
}/videos/captions?videoId={videoId}&captionsId={captionsId}curl -X DELETE "https://api.streamvault.one/v1/videos/captions?videoId={videoId}&captionsId={captionsId}" \
-H "Authorization: Bearer YOUR_API_KEY"