Skip to content

API Reference ​

Strum VOD's customer API — the video-resource surface (assets, collections, playback, comments, webhooks) your own integration calls. All endpoints are prefixed with /v1/ and return JSON.

Open the interactive API reference →

That page is generated straight from the same route definitions and Zod schemas the API itself validates against (apps/api-edge/src/routes/customer/) — not hand-maintained prose, so it can't drift the way this page used to. Two other artifacts, same source:

  • Raw spec — /openapi/customer.json (OpenAPI 3.1). Import into Postman/Insomnia, or feed it to your own codegen (openapi-generator, etc.) for a client in any language.
  • TypeScript request types — /openapi/customer.d.ts. Request bodies/params/query are typed, and most endpoints also carry a typed response shape; a handful of simple/legacy endpoints still fall back to a generic { data: unknown } response — see the spec generator's own comment for which ones.

This page covers the customer surface only — the routes an integration or the dashboard's own asset UI can call with an org API key. Account/platform management (billing, org members, admin) and internal-only routes (the worker fleet, provider webhooks) aren't part of this public contract — see CLAUDE.md if you're contributing to the platform itself.

Auth ​

Every customer endpoint accepts either:

  • X-Api-Key: mk_... — an org API key, minted from the dashboard's Settings → API Keys page.
  • Authorization: Bearer <token> — a dashboard session JWT (what the dashboard's own UI uses against these same routes).

Public playback endpoints (GET /v1/playback/:playbackId and friends) need no auth — the playback ID itself is the credential, the same model Mux uses.

Response Format ​

Successful responses wrap the payload in a data key:

json
{ "data": { ... } }

Errors return an error string:

json
{ "error": "Error message" }
CodeMeaning
200Success
201Resource created
400Validation error (missing or invalid fields)
401Unauthenticated
403Forbidden (plan limit, disabled feature, etc.)
404Resource not found
409Conflict (e.g. asset already has a source)
500Internal server error

MCP (Model Context Protocol) ​

Strum VOD also exposes an MCP server at POST <API_BASE_URL>/mcp, authenticated with the same mk_ API keys — see the dedicated MCP Server page for the tool list and client setup.

Quick start: upload → transcode → playback ​

bash
API_BASE_URL="https://vapi.usestrum.app"   # your instance's api-edge URL
API_KEY="mk_..."                            # from the dashboard's Settings -> API Keys

# 1. Create an asset
ASSET=$(curl -s -X POST "$API_BASE_URL/v1/assets" \
  -H "X-Api-Key: $API_KEY" -H "Content-Type: application/json" \
  -d '{"title": "Demo Video"}')
ASSET_ID=$(echo "$ASSET" | jq -r '.data.id')

# 2. Get a presigned upload URL and upload the file
UPLOAD=$(curl -s -X POST "$API_BASE_URL/v1/assets/$ASSET_ID/upload-url" -H "X-Api-Key: $API_KEY")
curl -X PUT "$(echo "$UPLOAD" | jq -r '.data.uploadUrl')" \
  -H "Content-Type: video/mp4" --data-binary @my-video.mp4

# 3. Confirm the upload, then start transcoding
curl -s -X POST "$API_BASE_URL/v1/assets/$ASSET_ID/upload-complete" -H "X-Api-Key: $API_KEY"
curl -s -X POST "$API_BASE_URL/v1/assets/$ASSET_ID/process" -H "X-Api-Key: $API_KEY"

# 4. Poll until ready
while true; do
  STATUS=$(curl -s "$API_BASE_URL/v1/assets/$ASSET_ID" -H "X-Api-Key: $API_KEY" | jq -r '.data.status')
  echo "Status: $STATUS"
  [ "$STATUS" = "ready" ] && break
  sleep 5
done

# 5. Get the public playback payload (HLS manifest, thumbnails, subtitles, ...)
curl -s "$API_BASE_URL/v1/assets/$ASSET_ID/playback" -H "X-Api-Key: $API_KEY" | jq

Resumable uploads (large files) go through TUS instead of a single presigned PUT — see POST /v1/assets/:id/upload-token in the interactive reference for the token, and apps/tus-edge for the server it talks to.

Asset Lifecycle ​

created ──► uploaded ──► queued ──► processing ──► ready
                                                    │
                                                    └──► error
StateDescription
createdAsset record exists, no source file yet
uploadedSource file confirmed in storage (presigned, TUS, or URL import)
queuedTranscode job dispatched, waiting to be claimed by a worker
processingThe Go transcoder is actively transcoding
readyAll renditions generated, playback available
errorTranscoding failed (see the asset's errorMessage field)

DELETE /v1/assets/:id is a hard delete — removes the DB row and the underlying storage objects. Not recoverable.

Embeddable Player ​

html
<iframe
  src="https://player.strum-vod.dev/embed/p1b2c3d4e5f6g7h8"
  width="100%"
  height="450"
  frameborder="0"
  allowfullscreen>
</iframe>
Query parameterExampleDescription
color?color=%236366f1Accent color override (6-digit hex)
title?title=My+VideoTitle overlay override (max 200 chars)

STRUM Proprietary License — © 2026 Strum. All rights reserved.