Summary
BluOS B400S Volume Control exposes a subset of the BluOS Custom Integration HTTP API focused on volume and mute control. All commands are HTTP GET requests to the player on TCP port 11000 returning UTF-8 XML responses. This spec captures the volume, mute, playback, queue, grouping, preset, browse, doorbell, input and reboot endpoints documented in the source.
Transport
protocols:
- http
addressing:
port: 11000
base_url: http://<player_ip>:11000
auth:
type: none # inferred: no auth procedure in source
Traits
- powerable # inferred: /reboot and doorbell/standby controls present
- routable # inferred: input selection commands (Play?url=, /Play?inputIndex=, /Play?inputTypeIndex=) present
- queryable # inferred: /Status, /SyncStatus, /Playlist, /Presets query endpoints present
- levelable # inferred: /Volume level/db/abs_db/mute controls present
Actions
- id: set_volume_level
label: Set Volume Level (0-100)
kind: action
command: "GET /Volume?level={level}&tell_slaves={tell_slaves}"
params:
- name: level
type: integer
description: Absolute volume level 0..100
- name: tell_slaves
type: integer
description: 0 = only this player, 1 = apply to all grouped players
- id: set_volume_abs_db
label: Set Volume (absolute dB)
kind: action
command: "GET /Volume?abs_db={db}&tell_slaves={tell_slaves}"
params:
- name: db
type: number
description: Absolute dB volume within configured range (typically -80..0)
- name: tell_slaves
type: integer
description: 0 = only this player, 1 = apply to all grouped players
- id: set_volume_relative_db
label: Adjust Volume (relative dB)
kind: action
command: "GET /Volume?db={delta_db}&tell_slaves={tell_slaves}"
params:
- name: delta_db
type: number
description: Positive or negative dB delta
- name: tell_slaves
type: integer
description: 0 = only this player, 1 = apply to all grouped players
- id: volume_up
label: Volume Up
kind: action
command: "GET /Volume?db={db_value}"
params:
- name: db_value
type: number
description: dB increase (typical 2)
- id: volume_down
label: Volume Down
kind: action
command: "GET /Volume?db=-{db_value}"
params:
- name: db_value
type: number
description: dB decrease (typical 2)
- id: mute_on
label: Mute On
kind: action
command: "GET /Volume?mute=1"
params: []
- id: mute_off
label: Mute Off
kind: action
command: "GET /Volume?mute=0"
params: []
- id: play
label: Play
kind: action
command: "GET /Play"
params: []
- id: play_with_seek
label: Play with Seek
kind: action
command: "GET /Play?seek={seconds}"
params:
- name: seconds
type: integer
description: Position in seconds within current track
- id: play_with_seek_and_id
label: Play Track at Seek
kind: action
command: "GET /Play?seek={seconds}&id={trackid}"
params:
- name: seconds
type: integer
description: Position in seconds
- name: trackid
type: integer
description: Track id within the queue (1-based)
- id: play_url
label: Play Stream URL
kind: action
command: "GET /Play?url={encodedStreamURL}"
params:
- name: encodedStreamURL
type: string
description: URL-encoded audio stream URL
- id: pause
label: Pause
kind: action
command: "GET /Pause"
params: []
- id: pause_toggle
label: Pause Toggle
kind: action
command: "GET /Pause?toggle=1"
params: []
- id: stop
label: Stop
kind: action
command: "GET /Stop"
params: []
- id: skip
label: Skip (Next Track)
kind: action
command: "GET /Skip"
params: []
- id: back
label: Back (Previous Track)
kind: action
command: "GET /Back"
params: []
- id: shuffle
label: Set Shuffle
kind: action
command: "GET /Shuffle?state={state}"
params:
- name: state
type: integer
description: 0 = disable shuffle, 1 = enable shuffle
- id: repeat
label: Set Repeat
kind: action
command: "GET /Repeat?state={state}"
params:
- name: state
type: integer
description: 0 = repeat queue, 1 = repeat track, 2 = repeat off
- id: streaming_action
label: Streaming Radio Action
kind: action
command: "GET /Action?service={service-name}&action={action-URL}"
params:
- name: service-name
type: string
description: Streaming service name (e.g. Slacker)
- name: action-URL
type: string
description: URL from the <action> element in /Status response (skip/back/love/ban)
- id: playlist_list
label: List Play Queue
kind: action
command: "GET /Playlist"
params: []
- id: playlist_status
label: Play Queue Status
kind: action
command: "GET /Playlist?length=1"
params: []
- id: playlist_paginate
label: Play Queue Page
kind: action
command: "GET /Playlist?start={first}&end={last}"
params:
- name: first
type: integer
description: First entry index (0-based)
- name: last
type: integer
description: Last entry index
- id: playlist_delete
label: Delete Track
kind: action
command: "GET /Delete?id={position}"
params:
- name: position
type: integer
description: Track position in queue to remove
- id: playlist_move
label: Move Track
kind: action
command: "GET /Move?new={destination}&old={origin}"
params:
- name: destination
type: integer
description: New track position
- name: origin
type: integer
description: Old track position
- id: playlist_clear
label: Clear Queue
kind: action
command: "GET /Clear"
params: []
- id: playlist_save
label: Save Queue as Playlist
kind: action
command: "GET /Save?name={playlist_name}"
params:
- name: playlist_name
type: string
description: Saved playlist name
- id: presets_list
label: List Presets
kind: action
command: "GET /Presets"
params: []
- id: preset_load
label: Load Preset
kind: action
command: "GET /Preset?id={presetId}"
params:
- name: presetId
type: string
description: Preset id, or +1 (next), or -1 (previous)
- id: browse
label: Browse
kind: action
command: "GET /Browse?key={key-value}"
params:
- name: key-value
type: string
description: URL-encoded browseKey from earlier response; omit for top-level
- id: browse_with_context
label: Browse with Context Menu
kind: action
command: "GET /Browse?key={key-value}&withContextMenuItems=1"
params:
- name: key-value
type: string
description: URL-encoded browseKey
- id: search
label: Search Music
kind: action
command: "GET /Browse?key={key-value}&q={searchText}"
params:
- name: key-value
type: string
description: URL-encoded searchKey from earlier response
- name: searchText
type: string
description: Search query string
- id: radio_browse_capture
label: List Capture Inputs
kind: action
command: "GET /RadioBrowse?service=Capture"
params: []
- id: play_active_input
label: Play Active Input (URL)
kind: action
command: "GET /Play?url={URL_value}"
params:
- name: URL_value
type: string
description: URL attribute from /RadioBrowse?service=Capture response
- id: play_external_input_legacy
label: Play External Input (pre-v4.2.0)
kind: action
command: "GET /Play?inputIndex={IndexId}"
params:
- name: IndexId
type: integer
description: 1-based input index (excludes Bluetooth); firmware between v3.8.0 and v4.2.0
- id: play_external_input
label: Play External Input (v4.2.0+)
kind: action
command: "GET /Play?inputTypeIndex={type-index}"
params:
- name: type-index
type: string
description: "{type}-{index}" e.g. spdif-2; type ∈ spdif/analog/coax/bluetooth/arc/earc/phono/computer/aesebu/balanced/microphone
- id: group_add_slave
label: Group One Player
kind: action
command: "GET /AddSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}&group={GroupName}"
params:
- name: secondaryPlayerIP
type: string
description: IP of secondary player
- name: secondaryPlayerPort
type: integer
description: Port of secondary player (default 11000)
- name: GroupName
type: string
description: Optional group name
- id: group_add_slaves
label: Group Multiple Players
kind: action
command: "GET /AddSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: secondaryPlayerIPs
type: string
description: Comma-separated secondary player IPs
- name: secondaryPlayerPorts
type: string
description: Comma-separated secondary player ports
- id: group_remove_slave
label: Remove One Player From Group
kind: action
command: "GET /RemoveSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}"
params:
- name: secondaryPlayerIP
type: string
description: IP of secondary player to ungroup
- name: secondaryPlayerPort
type: integer
description: Port of secondary player
- id: group_remove_slaves
label: Remove Multiple Players From Group
kind: action
command: "GET /RemoveSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: secondaryPlayerIPs
type: string
description: Comma-separated IPs to remove
- name: secondaryPlayerPorts
type: string
description: Comma-separated ports
- id: reboot
label: Reboot Player
kind: action
command: "POST /reboot body: yes={any}"
params:
- name: any
type: string
description: Any value (e.g. 1)
- id: doorbell_play
label: Play Doorbell Chime
kind: action
command: "GET /Doorbell?play=1"
params: []
- id: set_bluetooth_mode
label: Set Bluetooth Mode
kind: action
command: "GET /audiomodes?bluetoothAutoplay={value}"
params:
- name: value
type: integer
description: 0=Manual, 1=Automatic, 2=Guest, 3=Disabled
- id: status
label: Playback Status
kind: query
command: "GET /Status"
params: []
- id: status_long_poll
label: Playback Status (Long Poll)
kind: query
command: "GET /Status?timeout={seconds}&etag={etag-value}"
params:
- name: seconds
type: integer
description: Long-poll interval (recommended 100)
- name: etag-value
type: string
description: etag attribute from previous /Status response
- id: sync_status
label: Player and Group Sync Status
kind: query
command: "GET /SyncStatus"
params: []
- id: sync_status_long_poll
label: Sync Status (Long Poll)
kind: query
command: "GET /SyncStatus?timeout={seconds}&etag={etag-value}"
params:
- name: seconds
type: integer
description: Long-poll interval (recommended 180)
- name: etag-value
type: string
description: etag attribute from previous /SyncStatus response
- id: capture_settings
label: Capture Input Settings
kind: query
command: "GET /Settings?id=capture&schemaVersion={n}"
params:
- name: n
type: integer
description: Schema version (latest is 32 per source)
Feedbacks
- id: status_root
type: object
description: Root <status> element returned by /Status. Attributes include etag, volume (0..100 or -1 for fixed), db, mute (0/1), muteDb, muteVolume, state (play/pause/stop/stream/connecting), song, totlen, secs, shuffle (0/1), repeat (0/1/2), service, quality, pid, prid, syncStat, groupName, groupVolume, battery{level,charging,icon}, and now-playing title1/title2/title3 elements.
- id: sync_status_root
type: object
description: Root <SyncStatus> element. Attributes: etag, volume, modelName, name, model, brand, group, syncStat, id (ip:port), mac, schemaVersion, initialized (true/false), outlevel. Children: <master port=…>ip</master>, <slave port=… id=ip/> for grouped players.
- id: volume_response
type: object
description: <volume db="" mute="" muteDb="" muteVolume="" offsetDb="" etag="">level</volume> returned by /Volume and /Volume?mute. Text content is 0..100 (or -1 for fixed volume).
- id: playback_state
type: enum
values: [play, pause, stop, stream, connecting]
- id: mute_state
type: enum
values: [muted, unmuted]
- id: playlist_response
type: object
description: <playlist name="" modified="" length="" shuffle="" repeat="" id=""> with <song> children containing albumid/service/artistid/songid/id/title/art/alb/fn attributes.
- id: presets_response
type: object
description: <presets prid=""><preset id="" name="" url="" image=""/></presets>
- id: browse_response
type: object
description: <browse sid="" service="" serviceName="" serviceIcon="" searchKey="" type=""> with <item> and <category> children. type ∈ menu, contextMenu. Error variant is <error> with <message> + <detail>.
- id: skip_response
type: object
description: <id>{track-id}</id> after /Skip
- id: back_response
type: object
description: <id>{track-id}</id> after /Back
- id: shuffle_response
type: object
description: <playlist name="" modified="" length="" shuffle="" id=""/> after /Shuffle
- id: repeat_response
type: object
description: <playlist length="" id="" repeat=""/> after /Repeat
- id: delete_response
type: object
description: <deleted>{position}</deleted> after /Delete
- id: move_response
type: object
description: <moved>moved</moved> after /Move
- id: clear_response
type: object
description: <playlist modified="" length="" id=""/> after /Clear
- id: save_response
type: object
description: <saved><entries>N</entries></saved> after /Save
- id: preset_load_response_playlist
type: object
description: <loaded service=""><entries>N</entries></loaded> when preset is a track list
- id: preset_load_response_stream
type: enum
values: [stream]
description: Returned as <state>stream</state> when preset is a radio
- id: add_slave_response
type: object
description: <addSlave><slave port="" id=""/></addSlave> after /AddSlave
- id: action_ack_skip_back
type: enum
values: [skip, back]
description: Acknowledgement root elements <skip/> and <back/> for streaming radio skip/back actions
- id: action_ack_love
type: integer
description: <love>1</love> acknowledgement
- id: action_ack_ban
type: object
description: <love skip="1">0</love> acknowledgement for ban
- id: doorbell_response
type: object
description: <status enable="" volume="" chime=""/> after /Doorbell
- id: capture_browse_response
type: object
description: <radiotime service="Capture"><item/><category/></radiotime> after /RadioBrowse?service=Capture
- id: reboot_response
type: string
description: Plain HTML/text page containing "Settings Updated" and "Rebooting. Please close this window."
Variables
# UNRESOLVED: no continuous/variable parameters beyond the discrete command arguments are documented in source.
Events
# UNRESOLVED: source describes long-polling via /Status and /SyncStatus but does not document unsolicited push events.
Macros
# UNRESOLVED: source does not document named device-side macro sequences.
Safety
confirmation_required_for: []
interlocks: []
# UNRESOLVED: no safety warnings or interlock procedures found in source.
Notes
- Default TCP port 11000. CI580 uses 11000/11010/11020/11030 per node; CI580 is out-of-scope for B400S but port discovery via mDNS services
musc.tcp/musp.tcpis the recommended discovery method. - All volume commands are constrained to the player's configured volume range (typically -80..0 dB); the range is adjustable only via the BluOS Controller app.
- Polling guidance: ≤1 request / 30s when not using long polling; long-poll /Status recommended 100s interval (never faster than 10s); long-poll /SyncStatus recommended 180s. Long-poll requests for the same resource must be ≥1s apart.
- /Play?inputIndex requires firmware between v3.8.0 and v4.2.0; /Play?inputTypeIndex requires firmware v4.2.0 or newer. Both exclude Bluetooth; Bluetooth input selection requires /audiomodes + source connect flow.
- /Skip and /Back are valid only when /Status has no element; streaming radio skip/back go through /Action.
- HUB inputs are reached via /RadioBrowse?service=Capture then /Play?url=Hub://ip:port/inputN.
- LSDP discovery (UDP port 11430) is documented in section 13 but is a discovery protocol, not a control protocol — outside scope of this control spec.
Provenance
source_domains:
- bluos.io
source_urls:
- https://bluos.io/wp-content/uploads/2025/06/BluOS-Custom-Integration-API_v1.7.pdf
retrieved_at: 2026-07-12T08:05:42.496Z
last_checked_at: 2026-09-02T22:17:38.819Z
Verification Summary
verdict: verified
checked_at: 2026-09-02T22:17:38.819Z
matched_actions: 47
action_count: 47
confidence: medium
summary: "All 47 spec actions map to documented BluOS CI HTTP endpoints (port 11000) with correct parameter shapes; transport values verified. (6 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "source document covers the whole BluOS player API family; device-specific hardware capabilities of the B400S (number of zones, input count, fixed-vs-variable volume range, HUB connections) are not separately stated."
- "no continuous/variable parameters beyond the discrete command arguments are documented in source."
- "source describes long-polling via /Status and /SyncStatus but does not document unsolicited push events."
- "source does not document named device-side macro sequences."
- "no safety warnings or interlock procedures found in source."
- "device-specific hardware limits (number of inputs, fixed-vs-variable volume capability, B400S-specific behaviors) are not stated in this generic BluOS CI document. The Lenbrook reference applies the same API surface to all BluOS players listed (Bluesound, NAD, DALI); confirm B400S supports each command against the specific firmware revision shipped on the unit."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0