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.
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:
{ "data": { ... } }Errors return an error string:
{ "error": "Error message" }| Code | Meaning |
|---|---|
200 | Success |
201 | Resource created |
400 | Validation error (missing or invalid fields) |
401 | Unauthenticated |
403 | Forbidden (plan limit, disabled feature, etc.) |
404 | Resource not found |
409 | Conflict (e.g. asset already has a source) |
500 | Internal 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
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" | jqResumable 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| State | Description |
|---|---|
created | Asset record exists, no source file yet |
uploaded | Source file confirmed in storage (presigned, TUS, or URL import) |
queued | Transcode job dispatched, waiting to be claimed by a worker |
processing | The Go transcoder is actively transcoding |
ready | All renditions generated, playback available |
error | Transcoding 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
<iframe
src="https://player.strum-vod.dev/embed/p1b2c3d4e5f6g7h8"
width="100%"
height="450"
frameborder="0"
allowfullscreen>
</iframe>| Query parameter | Example | Description |
|---|---|---|
color | ?color=%236366f1 | Accent color override (6-digit hex) |
title | ?title=My+Video | Title overlay override (max 200 chars) |