Developer API

    Integrate video hosting and streaming capabilities into your applications with our RESTful API. Upload videos, manage content, and deliver media at scale.

    https://api.streamvault.one/v1
    Authorization: Bearer YOUR_API_KEY
    Recently shipped — May 2026

    Projects API with subprojects, Auto-Delete Plans, Branding (per-project logo with auto-extracted color palette), and the full Player Skin API with 4-level inheritance (account / project / channel / video). See the corresponding sections below for the full reference.

    Quick Start

    Get your API key and make your first request in 5 minutes.

    Get your API keys

    Your API requests are authenticated using API keys. Any request that doesn't include an API key will return an error. You can generate an API key from your Dashboard under Videos → Global Settings → API Keys.

    Note: The API key does not expire. The key should be used on the server-end and not on the client-end. If the API key gets compromised, you can delete it from the dashboard and generate a new one.

    API Authentication

    Use Bearer authentication. Send an Authorization header in all requests:

    http
    Authorization: Bearer YOUR_API_KEY

    Base URL

    StreamVault has a single canonical base URL. All endpoints — including video uploads — live under it:

    PurposeURL
    API base (everything: videos, uploads, channels, streams, projects, branding)https://api.streamvault.one/v1
    Health check (returns Worker version + uptime)https://api.streamvault.one/v1/health

    Make your first request

    Send an authenticated request to the videos endpoint to list your videos:

    javascript
    // List your videos
    const response = await fetch('https://api.streamvault.one/v1/videos', {
      headers: {
        'Authorization': 'Bearer YOUR_API_KEY'
      }
    });
    
    const data = await response.json();
    console.log(data.videos);

    Example Response

    json
    {
      "pager": {
        "page": 1,
        "totalPages": 1,
        "totalResults": 10,
        "sort": ""
      },
      "videos": [
        {
          "id": "fFL56RU6PjvJPeE",
          "title": "My Video",
          "channelKey": "f8RMr2q4h6yNpv9",
          "status": 3,
          "created": "2024-01-15T10:30:00Z"
        }
      ]
    }

    Rate Limits

    API requests are limited to 120 requests per minute per API key. When you exceed the limit, requests return 429 Too Many Requests until the window resets. Batch endpoints let you act on many videos in a single request — prefer them over per-video loops.

    json
    {
      "error": "Rate limit exceeded. Please slow down and try again shortly."
    }

    Errors

    Errors return a JSON body with an error message and a conventional HTTP status code:

    StatusMeaning
    400Invalid request — missing or malformed parameters
    401Missing, invalid, or revoked API key
    404Resource not found, or not owned by your account
    429Rate limit exceeded — retry after a short delay
    500Something went wrong on our side — safe to retry
    json
    {
      "error": "Invalid or revoked API key"
    }

    Videos API

    The Videos API allows you to upload, manage, and retrieve video content programmatically.

    https://api.streamvault.one/v1

    Upload Videos

    MethodEndpointDescription
    POST/videosUpload video via URL
    POST/videos/browserGet TUS upload credentials for browser-based upload

    Manage Videos

    MethodEndpointDescription
    GET/videosGet list of videos
    GET/videos/{id}Get a single video
    GET/videos/{id}/statusGet video transcoding status
    PUT/videos/{id}Update video details
    DELETE/videos/{id}Delete a video
    POST/videos/{id}/cta/copyCopy CTA from one video to others
    POST/videos/change-projectMove videos between projects

    Additional Operations

    MethodEndpointDescription
    GET/videos/{id}/original-fileGet original video URL
    GET/videos/collected-emailsGet collected emails (last 365 days)
    POST/videos/{id}/expirable-linkCreate expirable playback link
    PUT/videos/image/{id}Update video thumbnail
    POST/videos/captions/{id}Add captions/subtitles
    DELETE/videos/captions?videoId=&captionsId=Delete captions/subtitles

    Video Status Codes

    StatusValueDescription
    Na0Not available
    Uploaded1Uploaded
    Processing2Transcoding in progress
    Published3Ready for playback
    Error-1Transcoding failed
    Deleted50Deleted

    Quick Example

    javascript
    // Upload a video via URL
    const response = await fetch('https://api.streamvault.one/v1/videos', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        channelKey: 'abc123',
        url: 'https://example.com/video.mp4'
      })
    });
    
    const video = await response.json();
    console.log(video.iframeLink);
    View full Videos API reference

    Projects API

    Projects are folders that group your videos. They support arbitrary nesting via parent_id so you can model brands → shows → seasons (or any hierarchy that fits your workflow).

    Endpoints

    MethodEndpointDescription
    GET/projectsList all your projects
    POST/projectsCreate a project (or subproject via parent_id)
    GET/projects/{id}Get one project
    PATCH/projects/{id}Update name / description / parent_id
    DELETE/projects/{id}Delete (cascade-deletes videos in the project)

    Create a project

    bash
    curl -X POST https://api.streamvault.one/v1/projects \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Kinana VOD AR",
        "description": "Arabic news bulletins for the Kinana brand",
        "parent_id": null
      }'

    Response

    json
    {
      "id": "448ba8b6-eaa6-4ff8-80be-9a075e47c642",
      "user_id": "...",
      "name": "Kinana VOD AR",
      "description": "...",
      "parent_id": null,
      "created_at": "2026-05-07T...",
      "updated_at": "2026-05-07T..."
    }

    Subprojects (parent_id)

    Pass parent_id (a UUID) to create a subproject under an existing parent. Set parent_id to null for a top-level project.

    Update / move a project

    PATCH /v1/projects/{id} accepts a partial body. Setting parent_id to another project's UUID re-parents it; setting it to null makes it top-level.

    json
    { "name": "Renamed", "description": "New description", "parent_id": "uuid-of-new-parent-or-null" }

    Auto-Delete Plans

    Schedule automatic deletion of old videos based on retention rules. Mirrors DynTube's /auto-delete-plans URL shape so existing DynTube integrations work with just a host swap.

    Endpoints

    MethodEndpointDescription
    POST/auto-delete-plans/searchList with body-based pagination (DynTube-compatible)
    GET/auto-delete-plansList with query params (?page=1&size=50)
    GET/auto-delete-plans/{id}Get one plan
    POST/auto-delete-plansCreate a plan
    PUT/auto-delete-plans/{id}Update a plan
    DELETE/auto-delete-plans/{id}Delete a plan

    Plan shape

    json
    {
      "id": "uuid",
      "name": "Daily News Cleanup",
      "project_ids": ["uuid1", "uuid2"],
      "retention_days": 15,
      "title_filter": { "enabled": false, "value": "" },
      "is_active": true,
      "last_run_at": "2026-05-09T12:00:00Z",
      "last_run_deleted_count": 7,
      "created_at": "2026-05-01T00:00:00Z",
      "updated_at": "2026-05-09T12:00:00Z"
    }
    • project_ids — list of project UUIDs the rule applies to. Empty array = applies to every project you own.
    • retention_days — videos older than this many days are deleted.
    • title_filter.enabled + value — substring match (case-insensitive). Videos must match the filter to be deleted.
    • is_active: false — pauses the rule without deleting it.

    Plans run automatically once per hour. The dashboard shows last_run_at and last_run_deleted_count after each run.

    Create a plan

    bash
    curl -X POST https://api.streamvault.one/v1/auto-delete-plans \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Daily News 15-day cleanup",
        "project_ids": ["uuid-of-project-1"],
        "retention_days": 15,
        "title_filter": { "enabled": true, "value": "daily news" },
        "is_active": true
      }'
    bash
    curl -X POST https://api.streamvault.one/v1/auto-delete-plans/search \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "page": 1, "pageSize": 50 }'

    Response

    json
    {
      "plans": [ /* ... */ ],
      "pager": { "page": 1, "pageSize": 50, "totalResults": 3, "totalPages": 1 }
    }

    Branding (Project Logo)

    Upload a brand logo per project, automatically extract its color palette, and apply it to that project's player skin (controls color, big play disc, frame, watermark). The same logo also doubles as a corner overlay on the player.

    Endpoints

    MethodEndpointDescription
    PUT/projects/{id}/logoUpload a logo (multipart) and auto-extract its palette
    GET/projects/{id}/logoGet the logo URL + extracted palette
    DELETE/projects/{id}/logoRemove the logo (does not clear applied colors)
    POST/projects/{id}/logo/applyRe-apply the saved palette to player_settings

    Upload a file

    bash
    curl -X PUT https://api.streamvault.one/v1/projects/PROJECT_ID/logo \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -F "file=@./logo.png" \
      -F "auto_apply=true" \
      -F 'palette={"vibrant":"#FFC800","dark_muted":"#121218","muted":"#FFFFFF","text_on_vibrant":"#000000"}'

    Or pass a remote URL

    bash
    curl -X PUT https://api.streamvault.one/v1/projects/PROJECT_ID/logo \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -F "url=https://example.com/logo.png" \
      -F "auto_apply=true"
    • Max 2 MB
    • Accepted: PNG, JPEG, WebP, SVG (SVG is rasterized at 256×256 server-side before extraction)
    • auto_apply (default true) — write the extracted palette to project_player_settings (controls_color, big_play_color, big_play_icon_color, player_color, watermark_color)
    • palette (optional, JSON) — pre-extracted palette to use directly. When provided, the server skips its own extraction and uses your values verbatim. Recommended from a browser context where @vibrant/core is already running client-side; server-side extraction is best-effort and may return only a partial palette. Shape: { vibrant?, dark_vibrant?, light_vibrant?, muted?, dark_muted?, light_muted?, text_on_vibrant? } — all fields hex strings, all optional/nullable.

    Response (palette extraction)

    json
    {
      "logo_url": "https://api.streamvault.one/b2/project-logos/PROJECT_ID/logo.png",
      "logo_palette": {
        "vibrant": "#FF6B35",
        "dark_vibrant": "#7A2E0E",
        "light_vibrant": "#FFB89A",
        "muted": "#806257",
        "dark_muted": "#3B2A20",
        "light_muted": "#D4C4BA",
        "text_on_vibrant": "#FFFFFF",
        "extracted_at": "2026-05-09T22:00:00Z"
      },
      "applied": true,
      "applied_fields": [
        "controls_color", "big_play_color", "big_play_icon_color",
        "player_color", "watermark_color"
      ]
    }

    Re-apply palette

    If you previously declined auto_apply, or you've manually overridden colors and want to revert to the logo-derived palette:

    bash
    curl -X POST https://api.streamvault.one/v1/projects/PROJECT_ID/logo/apply \
      -H "Authorization: Bearer YOUR_API_KEY"

    Logo overlay & deletion

    When the project's logo_overlay_enabled player setting is true, the uploaded logo renders as a corner watermark on every player in the project. Position, size, and opacity are configured under Player Skin.

    Delete logo

    bash
    curl -X DELETE https://api.streamvault.one/v1/projects/PROJECT_ID/logo \
      -H "Authorization: Bearer YOUR_API_KEY"

    Note: deleting the logo does not clear the applied colors from project_player_settings. Use the Player Skin API or the dashboard's "Reset to inherit" links to clear those.

    Player Skin API

    Configure how the video player looks and behaves. Settings can be set at four levels with override precedence.

    When controls_color is set (either directly or via the Branding palette auto-apply), the entire control chrome paints with that color: progress fill, seek handle, volume slider, time display, playback speed pill, and every icon (play/pause, next, volume, settings, picture-in-picture, fullscreen). The big-play disc uses big_play_color, which falls back to controls_color when unset. Net effect: one brand color drives every accent on the player.

    Inheritance hierarchy

    text
    Per-video override     (highest priority, video.player_settings JSONB)
       ↓
    Channel default        (channel_player_settings)
       ↓
    Project default        (project_player_settings — also where logo palette writes)
       ↓
    Account default        (account_player_settings — set in Global Settings → Player Skins)

    A field set to null means "inherit from parent". The runtime resolution merges left-to-right; per-video wins, then channel, project, account, then a hardcoded system default.

    Account / project / channel / video endpoints

    MethodEndpointDescription
    GET/player-defaultsGet your account-level skin defaults
    PATCH/player-defaultsUpdate account-level defaults
    GET/projects/{id}/player-settingsGet effective project defaults
    PATCH/projects/{id}/player-settingsOverride fields at project level
    GET/channels/{id}/player-settingsGet effective channel defaults
    PATCH/channels/{id}/player-settingsOverride fields at channel level
    GET/videos/{id}/player-settingsGet the merged effective settings for this video
    PATCH/videos/{id}/player-settingsOverride at the video level

    Settings shape

    json
    {
      "skin": "modern",
      "player_color": "#0E1014",
      "controls_color": "#4CC2E0",
      "watermark_color": "#FFFFFF",
      "controls_opacity": 90,
      "watermark_opacity": 70,
    
      "big_play_button": true,
      "big_play_color": null,
      "big_play_icon_color": null,
      "big_play_opacity": 100,
      "big_play_size": "md",
      "big_play_shape": "circle",
      "big_play_show_on_hover": false,
    
      "autoplay": false,
      "start_muted": false,
      "loop": false,
      "captions_on_by_default": false,
      "seek_buttons": true,
      "fullscreen_control": true,
    
      "ip_watermark": false,
    
      "playback_speed_control": true,
      "allow_fast_forward": true,
      "click_for_sound": false,
      "click_to_resume": false,
      "auto_resume_playback": false,
      "default_quality": "auto",
      "default_volume": 100,
    
      "show_player_controls": true,
      "persistent_control_bar": false,
      "volume_control": true,
      "quality_selector": true,
      "sticky_player": false,
      "pause_on_scroll": false
    }

    Skin options

    skin accepts one of: modern (default), pill, sharp, halo, minimal, bold, heritage, floating.

    Big play button options

    • big_play_color (hex, null = inherit controls_color)
    • big_play_icon_color (hex, null = inherit player_color)
    • big_play_opacity (int 0–100)
    • big_play_size (sm / md / lg)
    • big_play_shape (circle / rounded / square)
    • big_play_show_on_hover (boolean — keeps the disc visible during playback while the user hovers; not in DynTube)

    Inheritance behavior

    Setting any color/opacity/skin field to null clears that override. The next-highest-priority layer takes effect. Example: a project sets controls_color: '#FF6B35', a video sets controls_color: null — that video plays with the project's orange. If the project later clears its override too, the video falls back to the account default cyan.

    The dashboard shows an "Inherited from {project|channel|account}" badge next to fields that are inheriting, with a "Reset to inherit" link on overridden fields.

    Update example

    bash
    curl -X PATCH https://api.streamvault.one/v1/projects/PROJECT_ID/player-settings \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "skin": "pill",
        "controls_color": "#FF6B35",
        "big_play_size": "lg",
        "big_play_show_on_hover": true,
        "ip_watermark": true
      }'

    CTAs

    Overlay call-to-action buttons and email-capture prompts on the player — per video, or per project with inheritance.

    Per-video CTAs

    MethodEndpointDescription
    GET/videos/{id}/ctasList a video's CTAs
    POST/videos/{id}/ctasCreate a CTA on a video
    PATCH/videos/{id}/ctas/{ctaId}Update a CTA
    DELETE/videos/{id}/ctas/{ctaId}Delete a CTA
    POST/videos/{id}/cta/copyCopy this video's CTAs to other videos
    POST/videos/batch/ctaBulk-assign a CTA to many videos

    Per-project CTAs

    MethodEndpointDescription
    GET/projects/{id}/ctasList a project's CTAs
    POST/projects/{id}/ctasCreate a project-level CTA
    PATCH/projects/{id}/ctas/{ctaId}Update a project CTA
    DELETE/projects/{id}/ctas/{ctaId}Delete a project CTA

    Inheritance & override

    Videos inherit their project's CTAs by default. Toggle per level withPATCH /videos/{id}or PATCH /projects/{id}with { "cta_inherit": false }. A video's own CTAs render on top of inherited ones.

    CTA shape

    json
    {
      "title": "Subscribe",
      "url": "https://example.com",
      "type": "link",            // "link" or "email"
      "show_at": 0,               // seconds; when to appear
      "hide_at": null,            // seconds; null = until end
      "position": "bottom-right", // top/bottom x left/center/right
      "background": "#2764EB",    // null = brand palette fallback
      "text_color": "#ffffff"
    }

    Full parameter reference (palette keys, email-capture fields) is in theAPI Referenceunder CTAs.

    Webhooks

    StreamVault allows you to set up webhooks to receive notifications for specific events such asvideoPublished.

    Setting Up Webhooks

    1. Log in to your StreamVault account.
    2. Navigate to Dashboard → Settings → Webhooks.
    3. Set the event type (e.g. videoPublished).
    4. Provide the webhook URL where you want to receive notifications.
    5. Webhook configuration will be automatically saved.

    Video Published Event

    json
    {
      "event": "videoPublished",
      "video": {
        "Id": "YOUR_VIDEO_ID",
        "Duration": "00:00:02.2200000",
        "ProjectId": "YOUR_PROJECT_ID",
        "AccountKey": "YOUR_ACCOUNT_KEY",
        "Region": "use",
        "Image": {
          "xsUrl": "",
          "smUrl": "",
          "mdUrl": "",
          "lgUrl": ""
        },
        "Captions": [],
        "Key": "YOUR_VIDEO_KEY",
        "ChannelKey": "YOUR_CHANNEL_KEY",
        "PrivateLink": "YOUR_PRIVATE_LINK",
        "IframeLink": "YOUR_IFRAME_LINK",
        "HLSLink": "YOUR_HLS_LINK",
        "PlanType": 1,
        "Mp4Url": "",
        "Mp4Urls": [],
        "Formats": {
          "Hls": true,
          "Mp4": false,
          "Options": { "SecureMp4": true }
        },
        "HLSUrl": "YOUR_HLS_URL",
        "HLSUrlWeb": "YOUR_HLS_URL_WEB",
        "Title": "YOUR_VIDEO_TITLE",
        "Description": "YOUR_VIDEO_DESCRIPTION",
        "Options": {},
        "Tags": [],
        "Version": 1,
        "Status": 3,
        "Created": "2024-01-15T10:30:00Z"
      }
    }
    View full Webhooks reference

    SDKs & Libraries

    Official client libraries to get you started quickly.

    JavaScript

    Node.js & browser SDK

    Coming soon

    React

    React component library

    Coming soon

    Python

    Python SDK

    Coming soon

    JavaScript Quick Example

    javascript
    import StreamVault from '@streamvault/sdk';
    
    const sv = new StreamVault({ apiKey: 'YOUR_API_KEY' });
    
    // List videos
    const { videos } = await sv.videos.list();
    
    // Upload via URL
    const video = await sv.videos.upload({
      url: 'https://example.com/video.mp4',
      title: 'My Video'
    });
    
    console.log(video.iframeLink);

    React Embed Component

    jsx
    import { StreamVaultPlayer } from '@streamvault/react';
    
    function App() {
      return (
        <StreamVaultPlayer
          videoId="YOUR_VIDEO_ID"
          autoplay={false}
          controls
          style={{ width: '100%', maxWidth: 800 }}
        />
      );
    }

    Embed via iframe

    html
    <!-- Embed StreamVault Player -->
    <iframe 
      src="https://player.streamvault.one/embed/VIDEO_ID"
      width="640" 
      height="360" 
      frameborder="0" 
      allow="encrypted-media"
      allowfullscreen>
    </iframe>
    View full SDKs & Embeds reference

    Need Help?

    Can't find what you're looking for? Reach out to our support team or check the user documentation.