On this page
For video partners. Returns one playlist for your CMS: Category, group, title, description, artwork, and its clips in order with title, description, duration, muscle groups, equipment, difficulty, calories, poster and production order code. When your organisation is licensed for the playlist, it also says where your copies live in your media space. Call it when List playlists shows a content_version you have not stored.
GET /api/delivery/v1/playlists/{code}Scope: metadata:read
Description
Any playlist in the library can be read, licensed or not. When granted is true, media names your media space and the playlist in it, and each copied clip carries its video ID (vid) and format (hls or mp4). When granted is false, media is null and every clip has ready: false with no video ID. There are no playback links: your app plays the copies straight from your own media space.
A playlist that does not exist and one that is no longer in the library (withdrawn, or its Category withdrawn) return the same 404. A key of an organisation that licenses films gets 403 4032; use Get series metadata instead.
Successful responses are wrapped in the {code, message, data, server_time} envelope; errors use the same envelope without data, except 429 and 400 unsupported_version, which use the flat format. This endpoint shares its rate-limit counter with the catalog.
Request parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Authorization |
header | string | Yes | Bearer <API key> for a key with the metadata:read scope. |
code |
path | string | Yes | Playlist code, for example wall-pilates-01 (the code from the list). |
Wandura-Version |
header | string | No | Optional. A dated API version (YYYY-MM-DD) to use for this request instead of the version pinned to your API key. Unknown or retired values answer 400 with error_code unsupported_version. |
Request example
curl -s https://www.wandura.ai/api/delivery/v1/playlists/wall-pilates-01 \
-H "Authorization: Bearer $WANDURA_API_KEY"Response
200 OK. New fields may be added at any time: ignore the ones you do not recognise.
| Field | Type | Description |
|---|---|---|
code |
integer | 0. |
message |
string | "ok". |
data |
object | |
server_time |
integer | Server time in Unix epoch seconds. |
links |
object | Ready-made absolute URL of this resource (an API link, not a media file). |
Fields of a playlist (data)
| Field | Type | Description |
|---|---|---|
code |
string | Playlist code. |
status |
string | Always active (a playlist not in the library returns 404). |
title |
string | Playlist title. |
description |
string or null | Playlist description, or null. |
category |
object | The Category of the playlist (for example Fitness). |
category.slug |
string | Stable code of the Category, for example fitness. Also the category filter of the list. |
category.name |
string | Display name. |
group |
object or null | Filter label of the playlist inside its Category (for example Pilates or Gym), or null. It is not a unit of licence. |
group.code |
string | Stable code. |
group.title |
string | Display name. |
updated_at |
integer | Last change in Unix epoch seconds. |
content_version |
string | Hash of this whole response. Store it; when the list shows the same value there is nothing to fetch. |
metadata_version |
string or null | Hash of the playlist metadata alone (the same for every organisation). |
granted |
boolean | true when your organisation is licensed for this playlist. |
media |
object or null | Where your copies live, or null when the playlist is not granted. Playback stays between your app and your media space; this API never returns playback links. |
media.space |
string or null | Your media space for this Category, or null while it is not set up. |
media.playlist_id |
string or null | ID of the playlist in space (named after code), or null until it exists. |
media.playlist_name |
string or null | Name of that playlist, or null. |
media.playlists |
array | Every playlist holding the clips in order (at most 100 videos each, so a longer playlist continues in <code>-2…). |
images |
array | Artwork of the playlist. Today one cover (the poster of the first clip); more kinds may be added. Empty when there is none. |
images[].kind |
string | cover. New kinds may be added. |
images[].source |
string | media_space or wandura_cdn. New values may be added. |
images[].url |
string or null | Image URL when source is wandura_cdn, else null. Download it and host your own copy. |
images[].expires_at |
integer or null | When url stops working, in Unix epoch seconds, or null. |
images[].space |
string or null | Your media space holding the image, or null. |
images[].uri |
string or null | The image's URI inside space, or null. |
clips |
array | Clips in playlist order. |
clips[].position |
integer | Position in the playlist. Clips come back in this order. |
clips[].id |
string (UUID) | Clip ID. It never changes; sync on it. The same clip can sit in several playlists. |
clips[].title |
string | Clip title. |
clips[].description |
string or null | Short description, or null. |
clips[].duration_ms |
integer or null | Duration in milliseconds. |
clips[].muscle_groups |
array of strings | Muscle groups worked. Can be empty. |
clips[].equipment |
array of strings | Equipment needed. Can be empty. |
clips[].difficulty |
string or null | beginner, intermediate or advanced, or null. |
clips[].kcal_est |
integer or null | Estimated calories burned. |
clips[].order_code |
string or null | Production order code (for example ABS_01_E01), matching your order file character for character, or null. |
clips[].poster |
object or null | An image, or null when there is none. source says where to get it. media_space: the image is already in your own media space (space) under uri (for a clip it is also the poster set on its vid); load it through your space as you load your videos. wandura_cdn: a link valid until expires_at; download the file and host your own copy, do not store the link. New sources may be added: skip a value you do not know. |
clips[].poster.source |
string | media_space (in your media space) or wandura_cdn (a Wandura link to download). New values may be added. |
clips[].poster.url |
string or null | Image URL when source is wandura_cdn, else null. |
clips[].poster.expires_at |
integer or null | When url stops working, in Unix epoch seconds, or null. |
clips[].poster.space |
string or null | Your media space holding the image when source is media_space, else null. |
clips[].poster.uri |
string or null | The image's URI inside space when source is media_space, else null. |
clips[].ready |
boolean | true when the clip is copied and playable in your media space (media.space). |
clips[].vid |
string or null | Video ID of the clip in your media space, or null while it is not copied (or the playlist is not granted). |
clips[].format |
string or null | How the copy is packaged: hls (clips of 30 seconds or more) or mp4 (shorter clips). null while not copied. |
clips[].playlist_id |
string or null | ID of the playlist in your media space that holds this clip, or null. |
clips[].playlist_name |
string or null | Name of that playlist, or null. |
Images
Each image (the playlist cover in images[], and each clip's poster) says in source where to get it. media_space: the image is already in your media space (space, uri); load it through your space as you load your videos. wandura_cdn: url is a link valid for 1 hour (until expires_at); download the file and host your own copy, never store the link. An image that is not available is null.
Response example
{
"code": 0,
"message": "ok",
"data": {
"code": "wall-pilates-01",
"status": "active",
"title": "Wall Pilates",
"description": "Ten low-impact moves using a wall for support.",
"category": { "slug": "fitness", "name": "Fitness" },
"group": { "code": "pilates", "title": "Pilates" },
"updated_at": 1790390000,
"content_version": "5d41402abc4b2a76b9719d911017c592",
"metadata_version": "0cc175b9c0f1b6a831c399e269772661",
"granted": true,
"media": {
"space": "your-fitness-space",
"playlist_id": "9f8e7d6c5b4a3921",
"playlist_name": "wall-pilates-01",
"playlists": [{ "id": "9f8e7d6c5b4a3921", "name": "wall-pilates-01" }]
},
"images": [{ "kind": "cover", "source": "media_space", "url": null, "expires_at": null, "space": "your-fitness-space", "uri": "your-fitness-space/fit-3f2a1b4c.jpg" }],
"clips": [
{
"position": 1,
"id": "3f2a1b4c-5d6e-4f70-8a9b-0c1d2e3f4a5b",
"title": "Wall Squat",
"description": "Slide down the wall and hold.",
"duration_ms": 45000,
"muscle_groups": ["quads", "glutes"],
"equipment": ["wall"],
"difficulty": "intermediate",
"kcal_est": 9,
"order_code": "ABS_01_E01",
"poster": { "source": "media_space", "url": null, "expires_at": null, "space": "your-fitness-space", "uri": "your-fitness-space/fit-3f2a1b4c.jpg" },
"ready": true,
"vid": "v0a1b2c3d4e5f6",
"format": "hls",
"playlist_id": "9f8e7d6c5b4a3921",
"playlist_name": "wall-pilates-01"
}
]
},
"server_time": 1790400000
}Response headers
| Header | Responses | Description |
|---|---|---|
Wandura-API-Status |
all | API status. beta today, on every response, success or error. |
Wandura-Version |
200 | The dated API version (YYYY-MM-DD) this response was produced in: the version pinned to your API key, or the one you sent in the Wandura-Version request header. Keys created before dated versions existed use 2026-10-02. |
Wandura-Request-Id |
200 | An opaque id for this request (req_ followed by 26 characters). Every response carries it, errors included, and error bodies repeat it as request_id. Log it, and quote it when you contact Wandura about a request: it finds the exact request in our logs. Do not parse it. |
Cache-Control |
200 | Always no-store. Do not cache these responses in shared caches. |
Retry-After |
429 | Seconds to wait before retrying. Sent with 429 and with retryable 503 responses. |
Errors
| Status | code |
When |
|---|---|---|
| 400 | none | The Wandura-Version header, or the version pinned to your key, is unknown or retired. |
| 401 | 4010 | The Authorization: Bearer header is missing. |
| 401 | 4011 | The key is unknown or revoked. |
| 403 | 4030 | The key lacks the metadata:read scope. |
| 403 | 4031 | Your organisation's access is suspended. |
| 403 | 4032 | Playlist metadata is for video partners; your organisation licenses films (use the series endpoints). |
| 404 | 4040 | No such playlist, or it is not in the library (the same answer on purpose). |
| 429 | none | Rate limit reached. |
| 503 | 5030 | The playlist is temporarily unavailable. |
| 503 | 5031 | Wandura could not verify the API key in time. |
What to do for each: Errors.
Updated 5 Oct 2026 · Change history (1)