Skip to main content
A playlist is not a separate resource. It is playlist_options, a JSON column, on a video row: the video you enable it on becomes the playlist’s container, and its {playlist} id in every URL below is that video’s own numeric id, the same id you would use on GET /v1/videos/{video}. Items in the playlist reference other videos, but by their video_code string, not their numeric id.
{playlist} and {video} in the item routes below are two different kinds of identifier. {playlist} is always a numeric video id. {video} in /playlists/ {playlist}/videos/{video} is always a video_code string. Passing a numeric id where a video_code is expected does not resolve to anything and returns a 404.
Reading needs videos:read. Everything that writes needs videos:write.

List and read

curl
200 OK
GET /v1/playlists/{playlist} returns the same shape for one playlist, wrapped in {"playlist": {...}}. GET /v1/playlists/{playlist}/videos returns its items: {"items": [...], "total": 6}.
playlist_chrome is a real, writable field (see below), but it does not appear in any of the three read responses above. If you set it, expect it to be silently absent when you read the playlist back: not null, absent entirely.

Enable a playlist

Turns an existing video into a playlist container.
integer
required
The video to enable a playlist on.
string
default:"linear"
linear or course.
string
Max 128 characters. Your own identifier for the playlist.
object[]
Starting items. Each is {"video_code": "...", "title": "..."}. You can only seed items here, at creation. After this call, manage items with the add/update/remove endpoints below, PATCH /v1/playlists/{playlist} does not accept items.
boolean
default:"true"
Whether the player moves to the next item automatically.
boolean
default:"false"
string
rail or button.
curl
201 Created
Calling this again on a video that already has a playlist does not fail. It re-enables it (setting enabled back to true if it was disabled) and applies whatever fields you send, leaving the rest as they were. This is also how you turn a disabled playlist back on.

Update a playlist

integer
required
The video’s numeric id.
string
string
boolean
integer
0 to 30000. Only settable here, not at creation.
boolean
string
sidebar, next-button, both, or none. Only settable here, not at creation.
string
rail or button.
curl
200 OK
Only the fields you send change. There is no items field here: manage items with the endpoints below.

Disable a playlist

curl
200 OK
This is a soft disable. It sets enabled to false; every item stays in place. The playlist stops appearing in GET /v1/playlists and its chrome stops showing in the player, but nothing is deleted. Enable it again with POST /v1/playlists.

Manage items

Items are keyed by video_code, the code of the video being added as an item, not by any id of the item itself.

Add an item

integer
required
The playlist’s video id.
string
required
Max 64 characters. Not validated against real videos: any string is accepted and stored as-is.
string
string
integer
string
A valid URL, max 2048 characters.
curl
201 Created
Adding a video_code that is already in the playlist does not merge or reject it. It appends a second entry with the same code. Check the existing list first if you need to guarantee one entry per video.

Update an item

PATCH /v1/playlists/{playlist}/videos/{video}, where {video} is the item’s video_code.
integer
required
The playlist’s video id.
string
required
The item’s video_code, not a numeric id.
string
string
integer
string
curl
200 OK
If video_code does not match any current item, this returns 404 {"error": {"code": "NOT_FOUND", "message": "Item not found."}}, unlike remove, below.

Remove an item

curl
200 OK
Removing a video_code that is not in the playlist is not an error. It returns 200 with the item list unchanged. Update 404s on an unknown code; remove does not.

Enum reference

Errors

The token is wrong, expired, or revoked.
Reads need videos:read. Everything else needs videos:write.
No video with that {playlist} id in your workspace. Laravel’s default body: {"message": "No query results for model [App\\Models\\WorkspaceVideo] 512"}.
Only from PATCH .../videos/{video}: {"error": {"code": "NOT_FOUND", "message": "Item not found."}}.
Validation failed. Laravel’s default shape, e.g. an invalid playback_mode or a thumb_url that is not a URL.
Rate limited. Reads: 600 per minute per token. Writes: 60 per minute per token.