Add comprehensive OpenAPI 3.1 documentation covering all REST endpoints: - Connection/auth endpoints (ping, cert) - Playback control (play, pause, seek, volume, next, previous) - Queue management (add, shuffle, repeat, play index) - Search (tracks, albums, artists) - Favorites management - Library (album/artist details) - Real-time updates (SSE and WebSocket) Also add /api/docs endpoint to serve the spec when Remote Control is active. This enables developers to build custom clients (web, CLI, mobile).
1190 lines
32 KiB
YAML
1190 lines
32 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: QBZ Remote Control API
|
|
description: |
|
|
REST API for controlling QBZ music player remotely. This API allows you to build
|
|
custom clients (web, CLI, mobile) to control playback, manage queue, search music,
|
|
and receive real-time updates.
|
|
|
|
## Authentication
|
|
|
|
All endpoints (except `/api/cert`) require authentication via one of:
|
|
- Header: `X-API-Key: <token>`
|
|
- Header: `Authorization: Bearer <token>`
|
|
- Query parameter: `?token=<token>`
|
|
|
|
The token is generated by QBZ and can be found in Settings > Remote Control.
|
|
|
|
## Network Requirements
|
|
|
|
- API only accepts connections from LAN (private IP addresses)
|
|
- Default port: 8182 (configurable)
|
|
- Supports HTTP and HTTPS (self-signed certificate)
|
|
|
|
## Real-time Updates
|
|
|
|
Use the `/api/events` SSE endpoint for real-time playback state updates instead of polling.
|
|
|
|
version: 1.0.0
|
|
contact:
|
|
name: QBZ Project
|
|
url: https://github.com/vicrodh/qbz-nix
|
|
license:
|
|
name: GPL-3.0
|
|
url: https://www.gnu.org/licenses/gpl-3.0.html
|
|
|
|
servers:
|
|
- url: http://{host}:{port}
|
|
description: QBZ Remote Control Server (HTTP)
|
|
variables:
|
|
host:
|
|
default: 192.168.1.100
|
|
description: Local IP address of the machine running QBZ
|
|
port:
|
|
default: "8182"
|
|
description: Remote control port (configurable in QBZ settings)
|
|
- url: https://{host}:{port}
|
|
description: QBZ Remote Control Server (HTTPS)
|
|
variables:
|
|
host:
|
|
default: 192.168.1.100
|
|
port:
|
|
default: "8182"
|
|
|
|
tags:
|
|
- name: Connection
|
|
description: Connection and authentication endpoints
|
|
- name: Playback
|
|
description: Playback control (play, pause, seek, volume)
|
|
- name: Queue
|
|
description: Queue management (add, remove, shuffle, repeat)
|
|
- name: Search
|
|
description: Search for tracks, albums, and artists
|
|
- name: Favorites
|
|
description: Manage user favorites
|
|
- name: Library
|
|
description: Album and artist information
|
|
- name: Real-time
|
|
description: Real-time updates via SSE/WebSocket
|
|
|
|
security:
|
|
- ApiKeyHeader: []
|
|
- BearerAuth: []
|
|
- ApiKeyQuery: []
|
|
|
|
paths:
|
|
/api/ping:
|
|
get:
|
|
tags: [Connection]
|
|
summary: Test connection
|
|
description: Check if the server is running and get device info. Use this to verify your connection is working.
|
|
responses:
|
|
"200":
|
|
description: Server is running
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/PingResponse"
|
|
example:
|
|
ok: true
|
|
version: "1.1.8"
|
|
name: "blitzkrieg-pc"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/cert:
|
|
get:
|
|
tags: [Connection]
|
|
summary: Download TLS certificate
|
|
description: |
|
|
Download the self-signed TLS certificate for HTTPS connections.
|
|
Only available when secure mode is enabled. This endpoint does NOT require authentication.
|
|
security: []
|
|
responses:
|
|
"200":
|
|
description: PEM certificate file
|
|
content:
|
|
application/x-pem-file:
|
|
schema:
|
|
type: string
|
|
format: binary
|
|
"500":
|
|
description: Certificate not available
|
|
|
|
/api/now-playing:
|
|
get:
|
|
tags: [Playback]
|
|
summary: Get current playback state
|
|
description: Returns the current playback state and track information.
|
|
responses:
|
|
"200":
|
|
description: Current playback state
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/NowPlayingResponse"
|
|
example:
|
|
playback:
|
|
isPlaying: true
|
|
position: 125
|
|
duration: 320
|
|
trackId: 12345678
|
|
volume: 0.75
|
|
track:
|
|
id: 12345678
|
|
title: "Bohemian Rhapsody"
|
|
artist: "Queen"
|
|
album: "A Night at the Opera"
|
|
durationSecs: 320
|
|
artworkUrl: "https://static.qobuz.com/images/..."
|
|
hires: true
|
|
bitDepth: 24
|
|
sampleRate: 96.0
|
|
isLocal: false
|
|
albumId: "abc123"
|
|
artistId: 456
|
|
streamable: true
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/status:
|
|
get:
|
|
tags: [Playback]
|
|
summary: Get current playback state (alias)
|
|
description: Alias for `/api/now-playing`.
|
|
responses:
|
|
"200":
|
|
description: Current playback state
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/NowPlayingResponse"
|
|
|
|
/api/playback/play:
|
|
post:
|
|
tags: [Playback]
|
|
summary: Resume playback
|
|
description: Resume playback if paused.
|
|
responses:
|
|
"204":
|
|
description: Playback resumed
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"500":
|
|
description: Playback error
|
|
|
|
/api/playback/pause:
|
|
post:
|
|
tags: [Playback]
|
|
summary: Pause playback
|
|
description: Pause current playback.
|
|
responses:
|
|
"204":
|
|
description: Playback paused
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"500":
|
|
description: Playback error
|
|
|
|
/api/playback/next:
|
|
post:
|
|
tags: [Playback]
|
|
summary: Skip to next track
|
|
description: Skip to the next track in the queue.
|
|
responses:
|
|
"200":
|
|
description: Next track info (or null if queue ended)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/QueueTrack"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/playback/previous:
|
|
post:
|
|
tags: [Playback]
|
|
summary: Go to previous track
|
|
description: Go back to the previous track in history.
|
|
responses:
|
|
"200":
|
|
description: Previous track info (or null if no history)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/QueueTrack"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/playback/seek:
|
|
post:
|
|
tags: [Playback]
|
|
summary: Seek to position
|
|
description: Seek to a specific position in the current track.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SeekRequest"
|
|
example:
|
|
position: 60
|
|
responses:
|
|
"204":
|
|
description: Seek successful
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"500":
|
|
description: Seek error
|
|
|
|
/api/playback/volume:
|
|
post:
|
|
tags: [Playback]
|
|
summary: Set volume
|
|
description: Set the playback volume (0.0 to 1.0).
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/VolumeRequest"
|
|
example:
|
|
volume: 0.75
|
|
responses:
|
|
"204":
|
|
description: Volume set
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"500":
|
|
description: Volume error
|
|
|
|
/api/playback/preferences:
|
|
get:
|
|
tags: [Playback]
|
|
summary: Get playback preferences
|
|
description: Get current playback preferences including autoplay mode.
|
|
responses:
|
|
"200":
|
|
description: Playback preferences
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/PlaybackPreferences"
|
|
example:
|
|
autoplayMode: "continue"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/playback/autoplay:
|
|
post:
|
|
tags: [Playback]
|
|
summary: Set autoplay mode
|
|
description: |
|
|
Set what happens when the current track/queue ends.
|
|
- `continue`: Continue playing within the current album/playlist
|
|
- `track_only`: Stop after current track
|
|
- `infinite`: Start infinite radio based on current track
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AutoplayRequest"
|
|
example:
|
|
mode: "continue"
|
|
responses:
|
|
"204":
|
|
description: Autoplay mode set
|
|
"400":
|
|
description: Invalid mode
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/queue:
|
|
get:
|
|
tags: [Queue]
|
|
summary: Get queue state
|
|
description: Get the current queue including upcoming tracks, history, and settings.
|
|
responses:
|
|
"200":
|
|
description: Queue state
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/QueueState"
|
|
example:
|
|
currentTrack:
|
|
id: 12345678
|
|
title: "Bohemian Rhapsody"
|
|
artist: "Queen"
|
|
album: "A Night at the Opera"
|
|
durationSecs: 320
|
|
currentIndex: 2
|
|
upcoming:
|
|
- id: 12345679
|
|
title: "Another Track"
|
|
artist: "Artist"
|
|
album: "Album"
|
|
durationSecs: 240
|
|
history:
|
|
- id: 12345677
|
|
title: "Previous Track"
|
|
artist: "Artist"
|
|
album: "Album"
|
|
durationSecs: 180
|
|
shuffle: false
|
|
repeat: "Off"
|
|
totalTracks: 10
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/queue/add:
|
|
post:
|
|
tags: [Queue]
|
|
summary: Add track to queue
|
|
description: Add a track to the end of the queue.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AddToQueueRequest"
|
|
responses:
|
|
"204":
|
|
description: Track added
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/queue/add-next:
|
|
post:
|
|
tags: [Queue]
|
|
summary: Add track to play next
|
|
description: Add a track to play immediately after the current track.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AddToQueueRequest"
|
|
responses:
|
|
"204":
|
|
description: Track added to play next
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/queue/play:
|
|
post:
|
|
tags: [Queue]
|
|
summary: Play track at index
|
|
description: Start playing a specific track in the queue by its index.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/PlayIndexRequest"
|
|
example:
|
|
index: 3
|
|
responses:
|
|
"200":
|
|
description: Track info (or null if index invalid)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/QueueTrack"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"502":
|
|
description: Playback failed
|
|
|
|
/api/queue/shuffle:
|
|
post:
|
|
tags: [Queue]
|
|
summary: Set shuffle mode
|
|
description: Enable or disable shuffle mode.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ShuffleRequest"
|
|
example:
|
|
enabled: true
|
|
responses:
|
|
"200":
|
|
description: Updated shuffle/repeat state
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ShuffleRepeatResponse"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/queue/repeat:
|
|
post:
|
|
tags: [Queue]
|
|
summary: Set repeat mode
|
|
description: |
|
|
Set the repeat mode:
|
|
- `off`: No repeat
|
|
- `all`: Repeat entire queue
|
|
- `one`: Repeat current track
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/RepeatRequest"
|
|
example:
|
|
mode: "all"
|
|
responses:
|
|
"200":
|
|
description: Updated shuffle/repeat state
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ShuffleRepeatResponse"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/search:
|
|
get:
|
|
tags: [Search]
|
|
summary: Search tracks
|
|
description: Search for tracks by query string.
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
required: true
|
|
description: Search query
|
|
schema:
|
|
type: string
|
|
example: "bohemian rhapsody"
|
|
- name: limit
|
|
in: query
|
|
description: Maximum results (default 20)
|
|
schema:
|
|
type: integer
|
|
default: 20
|
|
- name: offset
|
|
in: query
|
|
description: Results offset for pagination
|
|
schema:
|
|
type: integer
|
|
default: 0
|
|
responses:
|
|
"200":
|
|
description: Search results
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SearchResultsPage"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"502":
|
|
description: Search service unavailable
|
|
|
|
/api/search/all:
|
|
get:
|
|
tags: [Search]
|
|
summary: Search all types
|
|
description: Search for tracks, albums, and artists simultaneously.
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
required: true
|
|
description: Search query
|
|
schema:
|
|
type: string
|
|
- name: limit
|
|
in: query
|
|
description: Maximum results per type (default 10)
|
|
schema:
|
|
type: integer
|
|
default: 10
|
|
- name: offset
|
|
in: query
|
|
description: Results offset
|
|
schema:
|
|
type: integer
|
|
default: 0
|
|
responses:
|
|
"200":
|
|
description: Search results for all types
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SearchAllResults"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"502":
|
|
description: Search service unavailable
|
|
|
|
/api/favorites:
|
|
get:
|
|
tags: [Favorites]
|
|
summary: Get favorites
|
|
description: Get user's favorite items by type.
|
|
parameters:
|
|
- name: fav_type
|
|
in: query
|
|
required: true
|
|
description: Type of favorites to retrieve
|
|
schema:
|
|
type: string
|
|
enum: [tracks, albums, artists]
|
|
- name: limit
|
|
in: query
|
|
description: Maximum results (default 50)
|
|
schema:
|
|
type: integer
|
|
default: 50
|
|
- name: offset
|
|
in: query
|
|
description: Results offset
|
|
schema:
|
|
type: integer
|
|
default: 0
|
|
responses:
|
|
"200":
|
|
description: Favorites list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
description: Paginated favorites (structure varies by type)
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"502":
|
|
description: Service unavailable
|
|
|
|
/api/favorites/add:
|
|
post:
|
|
tags: [Favorites]
|
|
summary: Add to favorites
|
|
description: Add an item to user's favorites.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/FavoriteRequest"
|
|
example:
|
|
favType: "tracks"
|
|
itemId: "12345678"
|
|
responses:
|
|
"204":
|
|
description: Added to favorites
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"502":
|
|
description: Service unavailable
|
|
|
|
/api/favorites/remove:
|
|
post:
|
|
tags: [Favorites]
|
|
summary: Remove from favorites
|
|
description: Remove an item from user's favorites.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/FavoriteRequest"
|
|
example:
|
|
favType: "tracks"
|
|
itemId: "12345678"
|
|
responses:
|
|
"204":
|
|
description: Removed from favorites
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"502":
|
|
description: Service unavailable
|
|
|
|
/api/album/{id}:
|
|
get:
|
|
tags: [Library]
|
|
summary: Get album details
|
|
description: Get full album information including track list.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Album ID
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Album details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Album"
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"502":
|
|
description: Service unavailable
|
|
|
|
/api/album/play:
|
|
post:
|
|
tags: [Library]
|
|
summary: Play album
|
|
description: Clear queue and play all tracks from an album.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/PlayAlbumRequest"
|
|
example:
|
|
albumId: "abc123xyz"
|
|
responses:
|
|
"204":
|
|
description: Album playback started
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"404":
|
|
description: Album not found or has no tracks
|
|
"502":
|
|
description: Playback failed
|
|
|
|
/api/artist/{id}:
|
|
get:
|
|
tags: [Library]
|
|
summary: Get artist details
|
|
description: Get artist information including discography.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
description: Artist ID
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Artist details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Artist"
|
|
"400":
|
|
description: Invalid artist ID
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
"502":
|
|
description: Service unavailable
|
|
|
|
/api/events:
|
|
get:
|
|
tags: [Real-time]
|
|
summary: SSE event stream
|
|
description: |
|
|
Server-Sent Events stream for real-time playback updates. This is the recommended
|
|
way to receive updates instead of polling `/api/now-playing`.
|
|
|
|
**Connection:**
|
|
```javascript
|
|
const es = new EventSource('http://host:port/api/events?token=YOUR_TOKEN');
|
|
es.onmessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
console.log('Playback update:', data);
|
|
};
|
|
```
|
|
|
|
**Events:**
|
|
- Playback state changes (play/pause, position, volume)
|
|
- Track changes
|
|
- Shuffle/repeat mode changes
|
|
|
|
**Keep-alive:** Server sends ping every 15 seconds.
|
|
|
|
**Reconnection:** EventSource automatically reconnects on connection loss.
|
|
responses:
|
|
"200":
|
|
description: SSE event stream
|
|
content:
|
|
text/event-stream:
|
|
schema:
|
|
type: string
|
|
description: |
|
|
Stream of SSE events. Each event contains JSON data:
|
|
```
|
|
data: {"isPlaying":true,"position":125,"duration":320,"trackId":12345678,"volume":0.75,"sampleRate":96000,"bitDepth":24,"shuffle":false,"repeat":"off"}
|
|
```
|
|
example: |
|
|
data: {"isPlaying":true,"position":125,"duration":320,"trackId":12345678,"volume":0.75}
|
|
|
|
data: {"isPlaying":true,"position":126,"duration":320,"trackId":12345678,"volume":0.75}
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
/api/ws:
|
|
get:
|
|
tags: [Real-time]
|
|
summary: WebSocket connection (deprecated)
|
|
description: |
|
|
WebSocket endpoint for real-time updates. **Deprecated:** Use `/api/events` (SSE) instead
|
|
for simpler integration and automatic reconnection.
|
|
|
|
**Connection:**
|
|
```javascript
|
|
const ws = new WebSocket('ws://host:port/api/ws?token=YOUR_TOKEN');
|
|
ws.onmessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
console.log('Playback update:', data);
|
|
};
|
|
```
|
|
deprecated: true
|
|
responses:
|
|
"101":
|
|
description: WebSocket upgrade
|
|
"401":
|
|
$ref: "#/components/responses/Unauthorized"
|
|
|
|
components:
|
|
securitySchemes:
|
|
ApiKeyHeader:
|
|
type: apiKey
|
|
in: header
|
|
name: X-API-Key
|
|
description: API token from QBZ Settings > Remote Control
|
|
BearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
description: API token as Bearer token
|
|
ApiKeyQuery:
|
|
type: apiKey
|
|
in: query
|
|
name: token
|
|
description: API token as query parameter (useful for SSE/WebSocket)
|
|
|
|
responses:
|
|
Unauthorized:
|
|
description: Missing or invalid authentication token
|
|
content:
|
|
text/plain:
|
|
schema:
|
|
type: string
|
|
example: "Unauthorized"
|
|
|
|
schemas:
|
|
PingResponse:
|
|
type: object
|
|
required: [ok, version, name]
|
|
properties:
|
|
ok:
|
|
type: boolean
|
|
description: Always true if server is running
|
|
version:
|
|
type: string
|
|
description: QBZ version
|
|
example: "1.1.8"
|
|
name:
|
|
type: string
|
|
description: Device hostname
|
|
example: "my-pc"
|
|
|
|
NowPlayingResponse:
|
|
type: object
|
|
required: [playback]
|
|
properties:
|
|
playback:
|
|
$ref: "#/components/schemas/PlaybackState"
|
|
track:
|
|
$ref: "#/components/schemas/QueueTrack"
|
|
nullable: true
|
|
description: Current track info (null if nothing playing)
|
|
|
|
PlaybackState:
|
|
type: object
|
|
required: [isPlaying, position, duration, trackId, volume]
|
|
properties:
|
|
isPlaying:
|
|
type: boolean
|
|
description: Whether playback is active
|
|
position:
|
|
type: integer
|
|
format: int64
|
|
description: Current position in seconds
|
|
duration:
|
|
type: integer
|
|
format: int64
|
|
description: Track duration in seconds
|
|
trackId:
|
|
type: integer
|
|
format: int64
|
|
description: Current track ID (0 if nothing playing)
|
|
volume:
|
|
type: number
|
|
format: float
|
|
minimum: 0
|
|
maximum: 1
|
|
description: Volume level (0.0 to 1.0)
|
|
|
|
PlaybackEvent:
|
|
type: object
|
|
description: Real-time playback event (sent via SSE/WebSocket)
|
|
required: [isPlaying, position, duration, trackId, volume]
|
|
properties:
|
|
isPlaying:
|
|
type: boolean
|
|
position:
|
|
type: integer
|
|
format: int64
|
|
duration:
|
|
type: integer
|
|
format: int64
|
|
trackId:
|
|
type: integer
|
|
format: int64
|
|
volume:
|
|
type: number
|
|
format: float
|
|
sampleRate:
|
|
type: integer
|
|
nullable: true
|
|
description: Current stream sample rate in Hz
|
|
example: 96000
|
|
bitDepth:
|
|
type: integer
|
|
nullable: true
|
|
description: Current stream bit depth
|
|
example: 24
|
|
shuffle:
|
|
type: boolean
|
|
nullable: true
|
|
description: Queue shuffle state
|
|
repeat:
|
|
type: string
|
|
nullable: true
|
|
enum: [off, all, one]
|
|
description: Queue repeat mode
|
|
|
|
QueueTrack:
|
|
type: object
|
|
required: [id, title, artist, album, durationSecs]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
description: Track ID
|
|
title:
|
|
type: string
|
|
description: Track title
|
|
artist:
|
|
type: string
|
|
description: Artist name
|
|
album:
|
|
type: string
|
|
description: Album title
|
|
durationSecs:
|
|
type: integer
|
|
format: int64
|
|
description: Duration in seconds
|
|
artworkUrl:
|
|
type: string
|
|
format: uri
|
|
nullable: true
|
|
description: Album artwork URL
|
|
hires:
|
|
type: boolean
|
|
default: false
|
|
description: Whether track is Hi-Res
|
|
bitDepth:
|
|
type: integer
|
|
nullable: true
|
|
description: Maximum bit depth available
|
|
example: 24
|
|
sampleRate:
|
|
type: number
|
|
nullable: true
|
|
description: Maximum sample rate in kHz
|
|
example: 96.0
|
|
isLocal:
|
|
type: boolean
|
|
default: false
|
|
description: Whether track is from local library
|
|
albumId:
|
|
type: string
|
|
nullable: true
|
|
description: Album ID for navigation
|
|
artistId:
|
|
type: integer
|
|
format: int64
|
|
nullable: true
|
|
description: Artist ID for navigation
|
|
streamable:
|
|
type: boolean
|
|
default: true
|
|
description: Whether track is available for streaming
|
|
|
|
QueueState:
|
|
type: object
|
|
required: [shuffle, repeat, totalTracks]
|
|
properties:
|
|
currentTrack:
|
|
$ref: "#/components/schemas/QueueTrack"
|
|
nullable: true
|
|
currentIndex:
|
|
type: integer
|
|
nullable: true
|
|
description: Index of current track in queue
|
|
upcoming:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/QueueTrack"
|
|
description: Upcoming tracks
|
|
history:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/QueueTrack"
|
|
description: Previously played tracks
|
|
shuffle:
|
|
type: boolean
|
|
description: Shuffle mode enabled
|
|
repeat:
|
|
type: string
|
|
enum: [Off, All, One]
|
|
description: Repeat mode
|
|
totalTracks:
|
|
type: integer
|
|
description: Total tracks in queue
|
|
|
|
SeekRequest:
|
|
type: object
|
|
required: [position]
|
|
properties:
|
|
position:
|
|
type: integer
|
|
format: int64
|
|
minimum: 0
|
|
description: Target position in seconds
|
|
|
|
VolumeRequest:
|
|
type: object
|
|
required: [volume]
|
|
properties:
|
|
volume:
|
|
type: number
|
|
format: float
|
|
minimum: 0
|
|
maximum: 1
|
|
description: Volume level (0.0 to 1.0)
|
|
|
|
PlayIndexRequest:
|
|
type: object
|
|
required: [index]
|
|
properties:
|
|
index:
|
|
type: integer
|
|
minimum: 0
|
|
description: Queue index to play
|
|
|
|
AddToQueueRequest:
|
|
type: object
|
|
required: [track]
|
|
properties:
|
|
track:
|
|
$ref: "#/components/schemas/QueueTrack"
|
|
|
|
ShuffleRequest:
|
|
type: object
|
|
required: [enabled]
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
description: Enable shuffle mode
|
|
|
|
RepeatRequest:
|
|
type: object
|
|
required: [mode]
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: [off, all, one]
|
|
description: Repeat mode
|
|
|
|
ShuffleRepeatResponse:
|
|
type: object
|
|
required: [shuffle, repeat]
|
|
properties:
|
|
shuffle:
|
|
type: boolean
|
|
repeat:
|
|
type: string
|
|
enum: [off, all, one]
|
|
|
|
PlaybackPreferences:
|
|
type: object
|
|
properties:
|
|
autoplayMode:
|
|
type: string
|
|
enum: [continue, track_only, infinite]
|
|
description: What happens when queue ends
|
|
|
|
AutoplayRequest:
|
|
type: object
|
|
required: [mode]
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: [continue, track_only, infinite]
|
|
description: |
|
|
- `continue`: Continue within current source
|
|
- `track_only`: Stop after current track
|
|
- `infinite`: Start infinite radio
|
|
|
|
FavoriteRequest:
|
|
type: object
|
|
required: [favType, itemId]
|
|
properties:
|
|
favType:
|
|
type: string
|
|
enum: [tracks, albums, artists]
|
|
itemId:
|
|
type: string
|
|
description: Item ID to add/remove
|
|
|
|
PlayAlbumRequest:
|
|
type: object
|
|
required: [albumId]
|
|
properties:
|
|
albumId:
|
|
type: string
|
|
description: Album ID to play
|
|
|
|
SearchResultsPage:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Track"
|
|
total:
|
|
type: integer
|
|
description: Total matching results
|
|
offset:
|
|
type: integer
|
|
limit:
|
|
type: integer
|
|
|
|
SearchAllResults:
|
|
type: object
|
|
properties:
|
|
albums:
|
|
$ref: "#/components/schemas/SearchResultsPage"
|
|
tracks:
|
|
$ref: "#/components/schemas/SearchResultsPage"
|
|
artists:
|
|
$ref: "#/components/schemas/SearchResultsPage"
|
|
playlists:
|
|
$ref: "#/components/schemas/SearchResultsPage"
|
|
|
|
Track:
|
|
type: object
|
|
description: Track from search results
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
title:
|
|
type: string
|
|
duration:
|
|
type: integer
|
|
description: Duration in seconds
|
|
hires:
|
|
type: boolean
|
|
maximumBitDepth:
|
|
type: integer
|
|
maximumSamplingRate:
|
|
type: number
|
|
streamable:
|
|
type: boolean
|
|
performer:
|
|
$ref: "#/components/schemas/ArtistSummary"
|
|
album:
|
|
$ref: "#/components/schemas/AlbumSummary"
|
|
|
|
Album:
|
|
type: object
|
|
description: Full album details
|
|
properties:
|
|
id:
|
|
type: string
|
|
title:
|
|
type: string
|
|
artist:
|
|
$ref: "#/components/schemas/ArtistSummary"
|
|
image:
|
|
type: object
|
|
properties:
|
|
small:
|
|
type: string
|
|
format: uri
|
|
large:
|
|
type: string
|
|
format: uri
|
|
tracks:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Track"
|
|
total:
|
|
type: integer
|
|
|
|
AlbumSummary:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
title:
|
|
type: string
|
|
image:
|
|
type: object
|
|
properties:
|
|
small:
|
|
type: string
|
|
format: uri
|
|
large:
|
|
type: string
|
|
format: uri
|
|
|
|
Artist:
|
|
type: object
|
|
description: Full artist details
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
name:
|
|
type: string
|
|
image:
|
|
type: object
|
|
nullable: true
|
|
properties:
|
|
small:
|
|
type: string
|
|
format: uri
|
|
large:
|
|
type: string
|
|
format: uri
|
|
albums:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/AlbumSummary"
|
|
|
|
ArtistSummary:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
name:
|
|
type: string
|