You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 0942a3a
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: docs/api-reference.md
+50Lines changed: 50 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3540,6 +3540,56 @@ The playlists [`GET /playlists`](#get-playlists) lists, with track ids in playli
3540
3540
3541
3541
Keep the other people's playlists apart from the caller's own (a "Shared with me" and a "Public playlists" section, each entry labelled with its `owner`).
3542
3542
3543
+
### Mobile playlist writes
3544
+
3545
+
`GET /api/server/info` advertises `capabilities.playlist_editing: true` when these routes are available. These routes use stable mobile **track IDs**, and write only **manual** (Library-created) playlists. An inaccessible playlist or track returns `404`; imported playlists and callers without the required write permission return `403`; malformed bodies or fields return `400`; a stale reorder returns `409` without changing the playlist. The library sync index must be ready; otherwise a write returns `503` (`Starting up`). There is no whole-playlist delete route in this mobile API.
3546
+
3547
+
Create and rename require the playlist owner or an admin. Add, remove, and reorder require the owner, an admin, or an editor of a shared playlist. Successful changes notify connected WebSocket clients with `playlists_changed` according to playlist visibility.
3548
+
3549
+
All successful writes return the canonical shape `{ "name", "manual", "count", "track_ids" }`, where `track_ids` is in playlist order and includes every repeated occurrence. Rename also returns `previous`; track edits may also return `added`, `removed`, and `already`.
`add` and `remove` are arrays of track IDs. `remove` removes every copy of each ID; `remove_entries` removes only the specified zero-based occurrence of an ID in playlist order. A missing occurrence removes nothing. By default, adding an ID already in the playlist skips it and lists it in `already`; set `allow_duplicates` to `true` to add another copy. The response may include `added` and `removed` counts and `already` track IDs, alongside the canonical result shape.
3582
+
3583
+
The combined number of IDs in `add`, `remove`, and `remove_entries` may not exceed 10,000. The reorder endpoint also accepts at most 10,000 IDs. Larger requests return `400` before any IDs are resolved or the playlist is changed. Unknown and caller-hidden IDs both return `404`.
3584
+
3585
+
#### `PUT /api/v1/playlists/order`
3586
+
3587
+
Replace the order of a manual playlist's tracks. `track_ids` must describe the caller-visible playlist contents, including each repeated occurrence.
If the playlist changed since the client loaded it, the request returns `409`; reload and retry with the current IDs. Success returns the canonical result shape.
@@ -152,9 +152,23 @@ Other reads, all by track id:
152
152
|`POST /api/v1/playlists/seen`| Body `{ "name" }` — clear the `new` marker of a playlist shared with the user |
153
153
|`GET /api/v1/playlists/hidden?name=`|`{ "name", "songs": [{ "key", "label", "track_id", "hidden_at" }] }` — the songs the user hid from an imported playlist of theirs (`track_id` is `""` once the file is gone) |
154
154
|`POST /api/v1/playlists/hidden`| Body `{ "name", "hide": [track_ids], "show": [keys] }` — hide tracks from an imported playlist of the user's (they stay out when its watch or link brings them back; the tracks stay in the library), or show hidden ones again. Answers `{ "name", "hidden", "keys", "shown", "restored", "count", "track_ids" }`; send `keys` as `show` to undo. Offer it on `mine` playlists that aren't `manual` or `liked` (`409` otherwise). See [Hidden playlist songs](features/hidden-playlist-songs.md)|
155
+
|`POST /api/v1/playlists`| Body `{ "name" }` — create an empty manual playlist |
156
+
|`POST /api/v1/playlists/rename`| Body `{ "name", "new_name" }` — rename a manual playlist |
157
+
|`POST /api/v1/playlists/tracks`| Body `{ "name", "add"?: [track_id], "remove"?: [track_id], "remove_entries"?: [{ "track_id", "occurrence" }], "allow_duplicates"?: bool }` — edit a manual playlist by track ID; at most 10,000 total references across all three arrays (`400` above the limit) |
158
+
|`PUT /api/v1/playlists/order`| Body `{ "name", "track_ids": [...] }` — reorder a manual playlist, including repeated occurrences; at most 10,000 IDs (`400` above the limit) |
155
159
|`GET /api/v1/likes`|`{ "track_ids": [...] }`, newest first |
156
160
|`PUT /api/v1/likes`| Body `{ "track_id", "liked" }` — idempotent |
157
161
162
+
### Editing playlists
163
+
164
+
The `capabilities.playlist_editing` flag in `/api/server/info` is `true` when the server supports these writes. Use the stable track IDs from library sync, never file paths. All four routes operate on manual playlists; this API has no whole-playlist delete route. Create and rename require the owner or an admin. Adding, removing, or reordering requires the owner, an admin, or an editor of a shared playlist.
165
+
166
+
Successful writes return `{ "name", "manual", "count", "track_ids" }`, with `track_ids` in playlist order and repeated once per occurrence. Rename also returns `previous`; track edits may return `added`, `removed`, and `already`.
167
+
168
+
For `POST /api/v1/playlists/tracks`, `add` appends IDs; existing IDs are skipped and listed in `already` unless `allow_duplicates` is `true`. `remove` removes every copy of each ID. `remove_entries` removes only a specified zero-based `occurrence` of that ID in playlist order; a nonexistent occurrence removes nothing. For `PUT /api/v1/playlists/order`, send the current caller-visible IDs in the desired order, retaining repeated IDs. A stale list returns `409`; reload the playlist and retry.
169
+
170
+
Inaccessible playlists or tracks return `404`. Imported playlists and callers without the required write permission return `403`. Invalid bodies or fields return `400`; if the library sync index is not ready, the write returns `503`. Successful playlist changes send `playlists_changed` to connected WebSocket clients according to playlist visibility.
171
+
158
172
## 5. Stream and download
159
173
160
174
```http
@@ -200,7 +214,7 @@ Messages the app can rely on:
200
214
| Message | When |
201
215
|---------|------|
202
216
|`{ "type": "library_changed" }`| Tracks were added, removed or moved (debounced ~2 s) — sync |
203
-
|`{ "type": "playlists_changed" }`| A playlist was shared, unshared, followed, copied, detached, renamed or deleted, or songs were hidden from it or shown again — refetch `GET /api/v1/playlists`|
217
+
|`{ "type": "playlists_changed" }`| A playlist was shared, unshared, followed, copied, detached, renamed or deleted, its tracks changed, or songs were hidden from it or shown again — refetch `GET /api/v1/playlists`; playlist write notifications follow playlist visibility|
|`{ "type": "queue_reload" }`| Many downloads were queued at once — refetch `GET /api/queue`|
206
220
|`{ "song": {…}, "progress": 42.5, "status": "downloading"\|"done"\|"error", "message", "filename", "provider" }`| A server download's progress (no `type`) — one’s own jobs only (every job on an admin’s device) |
0 commit comments