Skip to main content
Beta Early access — Lock in $55/month for 24 months. Export your data with one command, any time.
API docs

API you can connect directly to business systems

Review the default flow for upload initiation, job completion, playback, and billing state updates.

OpenAPI spec /docs/openapi.yaml

Quickstart

First video in three requests

# 1. Create the asset and get a presigned upload URL
curl -X POST http://127.0.0.1:3000/api/v1/uploads/initiate \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "tenant_id": 1,
    "filename": "demo.mp4",
    "bytes_expected": 1024,
    "source_height": 720,
    "content_type": "video/mp4"
  }'

# 2. PUT the file to the returned upload_url, then mark it complete
curl -X PUT "$UPLOAD_URL" --upload-file demo.mp4
curl -X POST http://127.0.0.1:3000/api/v1/uploads/$UPLOAD_ID/complete \
  -H 'X-API-Key: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"bytes_received": 1024}'

# 3. Once playback_status is ready, fetch the playback URLs
curl http://127.0.0.1:3000/api/v1/playback/$ASSET_ID \
  -H 'X-API-Key: YOUR_API_KEY'

One-line embed

Drop it into any page

Once playback_status is ready, embed the asset with a plain iframe or the nulx-player web component. Both point at /embed/:id and inherit the same autoplay and token rules as the hosted watch page.

Option A: iframe
<iframe
  src="https://nulx.dev/embed/YOUR_ASSET_ID"
  style="width: 100%; aspect-ratio: 16 / 9; border: 0;"
  allow="autoplay; fullscreen; picture-in-picture"
  allowfullscreen
></iframe>
Option B: web component
<script src="https://nulx.dev/nulx-player.js" async></script>
<nulx-player playback-id="YOUR_ASSET_ID"></nulx-player>

Add ?autoplay=1 (or the autoplay attribute on <nulx-player>) for muted autoplay, and a token attribute/query param when the asset requires a playback token.

Primary endpoints

GET  /api/v1/tenants
POST /api/v1/uploads/initiate
POST /api/v1/uploads/:id/complete
POST /api/v1/transcoding_jobs/next (Idempotency-Key required; 1–255 bytes)
POST /api/v1/transcoding_jobs/:id/heartbeat
POST /api/v1/transcoding_jobs/:id/complete
GET  /api/v1/playback/:id
POST /api/v1/billing/checkout
POST /api/v1/billing/webhook

Use a long random SSTREAM_ADMIN_TOKEN value in production instead of a fixed development token.

Authentication

  • X-API-Key — tenant-scoped API calls
  • X-SSTREAM-ADMIN-TOKEN — worker and bootstrap administration
  • PayPal webhook — verify signatures in production; simulated headers are for local or non-production flows only

Launch flow

First video path

DB id or external_id accepted for playback
01

Create or select a tenant and API key with assets:write.

02

Initiate upload, PUT the file to R2, then complete the upload.

03

Worker leases the job, publishes HLS/DASH/thumbnail/captions, and sends heartbeats.

04

Read /api/v1/playback/:id with either numeric id or external_id and embed the returned HLS URL.

Endpoint contracts

Endpoint Purpose Must include
POST /api/v1/uploads/initiate Create a tenant-scoped direct upload session. tenant_id, filename, bytes_expected, content_type, source_width, source_height
POST /api/v1/uploads/:id/complete Mark upload complete and enqueue transcode. bytes_received no larger than bytes_expected
POST /api/v1/transcoding_jobs/next Lease one job for a trusted worker. X-SSTREAM-ADMIN-TOKEN; Idempotency-Key (required, 1–255 bytes)
POST /api/v1/transcoding_jobs/:id/heartbeat Renew lease and publish progress. X-SSTREAM-JOB-LEASE-TOKEN, progress, worker_id, stage
POST /api/v1/transcoding_jobs/:id/complete Publish finished playback artifacts. manifest_path; dash_manifest_path when DASH requested; thumbnail_path when thumbnail enabled; subtitle_paths for requested captions
GET /api/v1/playback/:id Issue playback URLs and token. Use numeric id or asset external_id; asset must be ready

Upload example

curl -X POST http://127.0.0.1:3000/api/v1/uploads/initiate \
  -H 'X-SSTREAM-ADMIN-TOKEN: YOUR_LONG_RANDOM_ADMIN_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "tenant_id": 1,
    "filename": "demo.mp4",
    "bytes_expected": 1024,
    "source_height": 720,
    "content_type": "video/mp4"
  }'

Common errors

  • 401 unauthorized — missing or invalid X-API-Key / admin token.
  • 403 insufficient_scope — API key lacks a required scope such as assets:write or billing:write.
  • 409 stale or invalid lease token — worker callback is no longer the active lease owner.
  • 422 invalid_transcoding_result — completion omitted required HLS/DASH/thumbnail/caption artifact paths.
  • 429 rate_limited — retry after the upload or billing window resets.