PlayVideo

Videos API

Upload, manage, and stream videos.

Base URL

https://api.playvideo.dev/v1

Authentication

All endpoints require a Bearer token:

Authorization: Bearer play_live_xxx

Upload Video

Upload a new video to a collection.

POST /videos

Request

Content-Type: multipart/form-data

FieldTypeRequiredDescription
fileFileYesVideo file (mp4, mov, avi, mkv, webm)
collectionStringYesCollection slug to upload to

Example

curl -X POST https://api.playvideo.dev/v1/videos \
  -H "Authorization: Bearer play_live_xxx" \
  -F "[email protected]" \
  -F "collection=my-app"
const result = await bb.videos.upload({
  file: './video.mp4',
  collection: 'my-app'
});

Response

{
  "message": "Video uploaded and queued for processing",
  "video": {
    "id": "clx1234567890",
    "filename": "video.mp4",
    "status": "PENDING",
    "collection": "my-app"
  }
}

Status Codes

CodeDescription
202Video accepted for processing
400Invalid request (missing file or collection)
404Collection not found
413File too large for your plan

List Videos

Get all videos, optionally filtered.

GET /videos

Query Parameters

ParameterTypeDescription
collectionStringFilter by collection slug
statusStringFilter by status (PENDING, PROCESSING, COMPLETED, FAILED)
limitNumberResults per page (max 100, default 50)
offsetNumberPagination offset

Example

curl "https://api.playvideo.dev/v1/videos?collection=my-app&status=COMPLETED" \
  -H "Authorization: Bearer play_live_xxx"
const { videos } = await bb.videos.list({
  collection: 'my-app',
  status: 'COMPLETED',
  limit: 10
});

Response

{
  "videos": [
    {
      "id": "clx1234567890",
      "filename": "video.mp4",
      "status": "COMPLETED",
      "duration": 120.5,
      "originalSize": 52428800,
      "processedSize": 31457280,
      "playlistUrl": "https://cdn.playvideo.dev/.../playlist.m3u8",
      "thumbnailUrl": "https://cdn.playvideo.dev/.../thumb.jpg",
      "previewUrl": "https://cdn.playvideo.dev/.../preview.mp4",
      "resolutions": ["360p", "480p", "720p", "1080p"],
      "errorMessage": null,
      "collection": {
        "slug": "my-app",
        "name": "My App"
      },
      "createdAt": "2026-01-07T12:00:00.000Z",
      "updatedAt": "2026-01-07T12:05:00.000Z"
    }
  ]
}

Get Video

Get details for a specific video.

GET /videos/:id

Example

curl https://api.playvideo.dev/v1/videos/clx1234567890 \
  -H "Authorization: Bearer play_live_xxx"
const video = await bb.videos.get('clx1234567890');

Response

{
  "id": "clx1234567890",
  "filename": "video.mp4",
  "status": "COMPLETED",
  "duration": 120.5,
  "originalSize": 52428800,
  "processedSize": 31457280,
  "playlistUrl": "https://cdn.playvideo.dev/.../playlist.m3u8",
  "thumbnailUrl": "https://cdn.playvideo.dev/.../thumb.jpg",
  "previewUrl": "https://cdn.playvideo.dev/.../preview.mp4",
  "resolutions": ["360p", "480p", "720p", "1080p"],
  "errorMessage": null,
  "collection": {
    "slug": "my-app",
    "name": "My App"
  },
  "createdAt": "2026-01-07T12:00:00.000Z",
  "updatedAt": "2026-01-07T12:05:00.000Z"
}

Video Status

StatusDescription
PENDINGUpload complete, waiting for processing
PROCESSINGVideo is being transcoded
COMPLETEDReady to stream
FAILEDProcessing failed (see errorMessage)

Delete Video

Delete a video and its files.

DELETE /videos/:id

Example

curl -X DELETE https://api.playvideo.dev/v1/videos/clx1234567890 \
  -H "Authorization: Bearer play_live_xxx"
await bb.videos.delete('clx1234567890');

Response

{
  "message": "Video deleted"
}

Video Object

FieldTypeDescription
idStringUnique identifier
filenameStringOriginal filename
statusStringProcessing status
durationNumberDuration in seconds (null if not processed)
originalSizeNumberOriginal file size in bytes
processedSizeNumberProcessed size in bytes (null if not complete)
playlistUrlStringHLS playlist URL (null if not ready)
thumbnailUrlStringThumbnail image URL (null if not ready)
previewUrlStringShort preview clip URL (null if not ready)
resolutionsArrayAvailable resolutions
errorMessageStringError description (null if no error)
collectionObjectParent collection info
createdAtStringISO 8601 timestamp
updatedAtStringISO 8601 timestamp

Polling for Completion

Videos are processed asynchronously. Poll the video endpoint to check status:

// Manual polling
let video = await bb.videos.get(videoId);
while (video.status === 'PROCESSING' || video.status === 'PENDING') {
  await new Promise(r => setTimeout(r, 2000));
  video = await bb.videos.get(videoId);
}

// Or use the SDK helper
const video = await bb.videos.waitForReady(videoId);

For real-time notifications, use webhooks.


Supported Formats

Input

  • MP4 (.mp4)
  • QuickTime (.mov)
  • AVI (.avi)
  • Matroska (.mkv)
  • WebM (.webm)
  • OGG (.ogv)
  • FLV (.flv)
  • WMV (.wmv)
  • MPEG (.mpeg, .mpg)
  • 3GPP (.3gp, .3g2)

Output

  • HLS (HTTP Live Streaming) - Universal playback
  • Auto-generated thumbnail (JPEG)
  • Preview clip (MP4)