Create a playlist
Creates a new playlist. status: published sets active: true; status: draft sets active: false. Send slug + custom_slug: true to pin a
permanent slug; without custom_slug: true the slug regenerates on title
change. After creation, Lighthouse and compliance scans are queued
automatically. With lang, the translatable fields (title,
description) are written for that locale; omitting lang writes the
default locale.
curl --request POST \
--url https://api.fluid.app/api/v202604/company/playlists \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"library": {
"title": "Primex Wellness Playlist",
"description": "A curated collection for Primex members.",
"status": "published",
"kind": "manual",
"country_isos": [
"GB",
"US"
]
}
}
'import requests
url = "https://api.fluid.app/api/v202604/company/playlists"
payload = { "library": {
"title": "Primex Wellness Playlist",
"description": "A curated collection for Primex members.",
"status": "published",
"kind": "manual",
"country_isos": ["GB", "US"]
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
library: {
title: 'Primex Wellness Playlist',
description: 'A curated collection for Primex members.',
status: 'published',
kind: 'manual',
country_isos: ['GB', 'US']
}
})
};
fetch('https://api.fluid.app/api/v202604/company/playlists', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fluid.app/api/v202604/company/playlists",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'library' => [
'title' => 'Primex Wellness Playlist',
'description' => 'A curated collection for Primex members.',
'status' => 'published',
'kind' => 'manual',
'country_isos' => [
'GB',
'US'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fluid.app/api/v202604/company/playlists"
payload := strings.NewReader("{\n \"library\": {\n \"title\": \"Primex Wellness Playlist\",\n \"description\": \"A curated collection for Primex members.\",\n \"status\": \"published\",\n \"kind\": \"manual\",\n \"country_isos\": [\n \"GB\",\n \"US\"\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fluid.app/api/v202604/company/playlists")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"library\": {\n \"title\": \"Primex Wellness Playlist\",\n \"description\": \"A curated collection for Primex members.\",\n \"status\": \"published\",\n \"kind\": \"manual\",\n \"country_isos\": [\n \"GB\",\n \"US\"\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fluid.app/api/v202604/company/playlists")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"library\": {\n \"title\": \"Primex Wellness Playlist\",\n \"description\": \"A curated collection for Primex members.\",\n \"status\": \"published\",\n \"kind\": \"manual\",\n \"country_isos\": [\n \"GB\",\n \"US\"\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"status": 200,
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"pagination": {
"cursor": "<string>",
"limit": 25,
"prev_cursor": "<string>",
"next_cursor": "<string>"
}
},
"playlist": {
"id": 3812,
"slug": "primex-wellness-playlist",
"title": "Primex Wellness Playlist",
"description": "A curated collection of wellness resources for Primex members.",
"image_url": "https://cdn.fluid.app/libraries/3812.png",
"canonical_url": "https://acme.fluid.app/home/libraries/primex-wellness-playlist",
"images": {
"thumb": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/categories/4821.png",
"width": 600
},
"medium": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/categories/4821.png",
"width": 600
},
"large": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/categories/4821.png",
"width": 600
}
},
"active": true,
"status": "published",
"publish_at": null,
"seo": {
"title": "Summer Sale — Up to 40% Off",
"description": "Shop the July clearance event before it ends.",
"image_url": "https://ik.imagekit.io/fluidapp/tr:w-1200,h-630,c-maintain_ratio,fo-auto,f-auto,q-80/seo/9215.png",
"block_crawler": false,
"id": 9215
},
"metafields": [
{
"namespace": "custom",
"key": "material",
"value": "<unknown>",
"value_type": "single_line_text_field",
"description": "The primary material used in this product",
"created_at": "2026-05-01T12:00:00Z",
"updated_at": "2026-05-01T12:00:00Z",
"locked": false
}
],
"languages": [
"en",
"fr"
],
"kind": "manual",
"countries": [
"GB",
"US"
],
"total_items_count": 5,
"library_items": [
{
"id": 123,
"relateable_type": "<string>",
"relateable_id": 123,
"order": 123
}
],
"custom_slug": false
}
}{
"message": "Invalid credentials."
}{
"error": "Not authorized."
}{
"error": {
"message": "<string>",
"details": {}
},
"status": 123,
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"pagination": {
"cursor": "<string>",
"limit": 25,
"prev_cursor": "<string>",
"next_cursor": "<string>"
}
}
}Authorizations
Bearer token authentication. Accepts company-admin tokens with
storefront.view for read operations and storefront.update
for writes and scan triggers (legacy per-resource grants like
categories.update / products.view / etc. are still accepted
during the migration), required on every company operation.
Storefront public operations under /api/v202604/{resource} and
/api/v202604/{resource}/{slug} are unauthenticated
(security: []).
Query Parameters
Response locale. ISO code (e.g. fr, de). When omitted,
responds in the company's default locale. On the public
surface, falls back to en for any translated field missing
in the requested locale.
"fr"
Body
The wrapper key is library (the underlying ActiveRecord model
name), while the URL resource is playlists — this mismatch is
intentional, not a typo. The write payload nests under library;
with additionalProperties: false a { playlist: ... } body is
rejected.
Show child attributes
Show child attributes
Response
Playlist created.
Shared success envelope for list / show / create / update
responses: the resource payload is returned alongside a top-level
integer status and meta. Composed onto each resource response
via allOf.
200
Response metadata included on every successful response body.
request_id and timestamp are always present; list endpoints
also add pagination.
Show child attributes
Show child attributes
Authenticated (company-surface) Playlist read shape: the public
PlaylistBase plus custom_slug, admin metadata never rendered on the
public surface.
Show child attributes
Show child attributes
curl --request POST \
--url https://api.fluid.app/api/v202604/company/playlists \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"library": {
"title": "Primex Wellness Playlist",
"description": "A curated collection for Primex members.",
"status": "published",
"kind": "manual",
"country_isos": [
"GB",
"US"
]
}
}
'import requests
url = "https://api.fluid.app/api/v202604/company/playlists"
payload = { "library": {
"title": "Primex Wellness Playlist",
"description": "A curated collection for Primex members.",
"status": "published",
"kind": "manual",
"country_isos": ["GB", "US"]
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
library: {
title: 'Primex Wellness Playlist',
description: 'A curated collection for Primex members.',
status: 'published',
kind: 'manual',
country_isos: ['GB', 'US']
}
})
};
fetch('https://api.fluid.app/api/v202604/company/playlists', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fluid.app/api/v202604/company/playlists",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'library' => [
'title' => 'Primex Wellness Playlist',
'description' => 'A curated collection for Primex members.',
'status' => 'published',
'kind' => 'manual',
'country_isos' => [
'GB',
'US'
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fluid.app/api/v202604/company/playlists"
payload := strings.NewReader("{\n \"library\": {\n \"title\": \"Primex Wellness Playlist\",\n \"description\": \"A curated collection for Primex members.\",\n \"status\": \"published\",\n \"kind\": \"manual\",\n \"country_isos\": [\n \"GB\",\n \"US\"\n ]\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fluid.app/api/v202604/company/playlists")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"library\": {\n \"title\": \"Primex Wellness Playlist\",\n \"description\": \"A curated collection for Primex members.\",\n \"status\": \"published\",\n \"kind\": \"manual\",\n \"country_isos\": [\n \"GB\",\n \"US\"\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fluid.app/api/v202604/company/playlists")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"library\": {\n \"title\": \"Primex Wellness Playlist\",\n \"description\": \"A curated collection for Primex members.\",\n \"status\": \"published\",\n \"kind\": \"manual\",\n \"country_isos\": [\n \"GB\",\n \"US\"\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"status": 200,
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"pagination": {
"cursor": "<string>",
"limit": 25,
"prev_cursor": "<string>",
"next_cursor": "<string>"
}
},
"playlist": {
"id": 3812,
"slug": "primex-wellness-playlist",
"title": "Primex Wellness Playlist",
"description": "A curated collection of wellness resources for Primex members.",
"image_url": "https://cdn.fluid.app/libraries/3812.png",
"canonical_url": "https://acme.fluid.app/home/libraries/primex-wellness-playlist",
"images": {
"thumb": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/categories/4821.png",
"width": 600
},
"medium": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/categories/4821.png",
"width": 600
},
"large": {
"url": "https://ik.imagekit.io/fluidapp/tr:w-600,c-at_max,f-auto,q-75/categories/4821.png",
"width": 600
}
},
"active": true,
"status": "published",
"publish_at": null,
"seo": {
"title": "Summer Sale — Up to 40% Off",
"description": "Shop the July clearance event before it ends.",
"image_url": "https://ik.imagekit.io/fluidapp/tr:w-1200,h-630,c-maintain_ratio,fo-auto,f-auto,q-80/seo/9215.png",
"block_crawler": false,
"id": 9215
},
"metafields": [
{
"namespace": "custom",
"key": "material",
"value": "<unknown>",
"value_type": "single_line_text_field",
"description": "The primary material used in this product",
"created_at": "2026-05-01T12:00:00Z",
"updated_at": "2026-05-01T12:00:00Z",
"locked": false
}
],
"languages": [
"en",
"fr"
],
"kind": "manual",
"countries": [
"GB",
"US"
],
"total_items_count": 5,
"library_items": [
{
"id": 123,
"relateable_type": "<string>",
"relateable_id": 123,
"order": 123
}
],
"custom_slug": false
}
}{
"message": "Invalid credentials."
}{
"error": "Not authorized."
}{
"error": {
"message": "<string>",
"details": {}
},
"status": 123,
"meta": {
"request_id": "<string>",
"timestamp": "2023-11-07T05:31:56Z",
"pagination": {
"cursor": "<string>",
"limit": 25,
"prev_cursor": "<string>",
"next_cursor": "<string>"
}
}
}