Summary
NAD 450 is a BluOS-enabled streaming player. This spec covers the BluOS Custom Integration HTTP API for playback control, volume, queue management, presets, content browsing, grouping, and direct input selection, plus the Lenbrook Service Discovery Protocol (LSDP) for UDP-based device discovery.
Transport
protocols:
- http
- udp
addressing:
port: 11000 # BluOS CI HTTP port (CI580 uses 11000/11010/11020/11030 per node)
auth:
type: none # inferred: no auth procedure in source
LSDP discovery:
protocols:
- udp
addressing:
port: 11430 # LSDP discovery port (IANA assigned to Lenbrook)
Traits
# - powerable (soft reboot via POST /reboot only; no power on/off)
# - routable # inferred from input selection commands (/Play?url=, /Play?inputTypeIndex=)
# - queryable # inferred from /Status, /SyncStatus, /Playlist, /Presets queries
# - levelable # inferred from /Volume?level=, /Volume?db=, /Volume?mute= commands
- routable
- queryable
- levelable
Actions
# --- Status queries ---
- id: status
label: Playback Status
kind: query
command: "/Status"
params: []
- id: status_long_poll
label: Playback Status (long poll)
kind: query
command: "/Status?timeout={timeout}&etag={etag}"
params:
- name: timeout
type: integer
description: Long-poll interval in seconds (recommended 100; never faster than 10).
- name: etag
type: string
description: etag value from previous /Status response.
- id: sync_status
label: Player and Group Sync Status
kind: query
command: "/SyncStatus"
params: []
- id: sync_status_long_poll
label: Sync Status (long poll)
kind: query
command: "/SyncStatus?timeout={timeout}&etag={etag}"
params:
- name: timeout
type: integer
description: Long-poll interval in seconds (recommended 180).
- name: etag
type: string
description: etag value from previous /SyncStatus response.
# --- Volume control ---
- id: volume_set
label: Set Volume Level
kind: action
command: "/Volume?level={level}&tell_slaves={tell_slaves}"
params:
- name: level
type: integer
description: Absolute volume 0-100.
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to all grouped players.
- id: volume_mute_set
label: Set Mute State
kind: action
command: "/Volume?mute={mute}&tell_slaves={tell_slaves}"
params:
- name: mute
type: integer
description: 0 = mute; 1 = unmute.
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to all grouped players.
- id: volume_set_db
label: Set Volume (dB)
kind: action
command: "/Volume?abs_db={db}&tell_slaves={tell_slaves}"
params:
- name: db
type: number
description: Absolute volume in dB.
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to all grouped players.
- id: volume_change_db
label: Change Volume (relative dB)
kind: action
command: "/Volume?db={delta}&tell_slaves={tell_slaves}"
params:
- name: delta
type: number
description: Relative dB change (positive = up, negative = down; typical step 2dB).
- name: tell_slaves
type: integer
description: 0 = only this player; 1 = apply to all grouped players.
# --- Playback control ---
- id: play
label: Play
kind: action
command: "/Play"
params: []
- id: play_seek
label: Play with Seek
kind: action
command: "/Play?seek={seconds}"
params:
- name: seconds
type: integer
description: Position to jump to in current track.
- id: play_seek_id
label: Play with Seek and Track ID
kind: action
command: "/Play?seek={seconds}&id={trackid}"
params:
- name: seconds
type: integer
description: Position to jump to in track.
- name: trackid
type: integer
description: Track id within the queue.
- id: play_url
label: Play Stream URL
kind: action
command: "/Play?url={encodedStreamURL}"
params:
- name: encodedStreamURL
type: string
description: URL-encoded stream URL.
- id: pause
label: Pause
kind: action
command: "/Pause"
params: []
- id: pause_toggle
label: Pause Toggle
kind: action
command: "/Pause?toggle=1"
params: []
- id: stop
label: Stop
kind: action
command: "/Stop"
params: []
- id: skip
label: Skip Next Track
kind: action
command: "/Skip"
params: []
- id: back
label: Skip Previous Track
kind: action
command: "/Back"
params: []
- id: shuffle
label: Shuffle Queue
kind: action
command: "/Shuffle?state={state}"
params:
- name: state
type: integer
description: 0 = disable shuffle; 1 = enable shuffle.
- id: repeat
label: Repeat Mode
kind: action
command: "/Repeat?state={state}"
params:
- name: state
type: integer
description: 0 = repeat queue; 1 = repeat current track; 2 = repeat off.
# --- Streaming radio actions ---
- id: action_radio
label: Streaming Radio Action
kind: action
command: "/Action?service={service-name}&action={action-URL}"
params:
- name: service-name
type: string
description: Music service name (e.g. Slacker).
- name: action-URL
type: string
description: URL provided in /Status <action> element (skip/back/love/ban).
# --- Play queue management ---
- id: playlist
label: List Play Queue
kind: query
command: "/Playlist"
params: []
- id: playlist_status
label: Play Queue Status
kind: query
command: "/Playlist?length=1"
params: []
- id: playlist_range
label: Play Queue Range
kind: query
command: "/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: delete_track
label: Delete Track
kind: action
command: "/Delete?id={position}"
params:
- name: position
type: integer
description: Track position in queue to remove.
- id: move_track
label: Move Track
kind: action
command: "/Move?new={destination}&old={origin}"
params:
- name: destination
type: integer
description: New track position.
- name: origin
type: integer
description: Old track position.
- id: clear_queue
label: Clear Play Queue
kind: action
command: "/Clear"
params: []
- id: save_queue
label: Save Play Queue
kind: action
command: "/Save?name={playlist_name}"
params:
- name: playlist_name
type: string
description: Name for saved BluOS playlist.
# --- Presets ---
- id: presets
label: List Presets
kind: query
command: "/Presets"
params: []
- id: preset_load
label: Load Preset
kind: action
command: "/Preset?id={presetId}"
params:
- name: presetId
type: string
description: Preset id, or +1 for next preset, or -1 for previous preset.
# --- Content browsing / search ---
- id: browse
label: Browse Content
kind: query
command: "/Browse?key={key-value}"
params:
- name: key-value
type: string
description: URL-encoded browseKey from prior response.
- id: browse_with_context
label: Browse with Context Menu
kind: query
command: "/Browse?key={key-value}&withContextMenuItems=1"
params:
- name: key-value
type: string
description: URL-encoded browseKey from prior response.
- id: browse_search
label: Search Music Content
kind: query
command: "/Browse?key={key-value}&q={searchText}"
params:
- name: key-value
type: string
description: URL-encoded searchKey from prior response.
- name: searchText
type: string
description: Search term.
# --- Player grouping ---
- id: add_slave
label: Group One Player
kind: action
command: "/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: add_slaves
label: Group Multiple Players
kind: action
command: "/AddSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: secondaryPlayerIPs
type: string
description: Comma-separated IPs of secondary players.
- name: secondaryPlayerPorts
type: string
description: Comma-separated ports of secondary players.
- id: remove_slave
label: Remove One Player From Group
kind: action
command: "/RemoveSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}"
params:
- name: secondaryPlayerIP
type: string
description: IP of secondary player to remove.
- name: secondaryPlayerPort
type: integer
description: Port of secondary player to remove.
- id: remove_slaves
label: Remove Multiple Players From Group
kind: action
command: "/RemoveSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
params:
- name: secondaryPlayerIPs
type: string
description: Comma-separated IPs of secondary players.
- name: secondaryPlayerPorts
type: string
description: Comma-separated ports of secondary players.
# --- System ---
- id: reboot
label: Soft Reboot Player
kind: action
command: "POST /reboot"
params: []
- id: doorbell
label: Play Doorbell Chime
kind: action
command: "/Doorbell?play=1"
params: []
# --- Input selection ---
- id: active_input
label: Select Active Input (URL-based)
kind: action
command: "/Play?url={URL_value}"
params:
- name: URL_value
type: string
description: URL from /RadioBrowse?service=Capture response.
- id: external_input_legacy
label: Select External Input (legacy, firmware >3.8.0 and <4.2.0)
kind: action
command: "/Play?inputIndex={IndexId}"
params:
- name: IndexId
type: integer
description: Input index from /Settings?id=capture (Bluetooth excluded; starts at 1).
- id: external_input
label: Select External Input (firmware >=4.2.0)
kind: action
command: "/Play?inputTypeIndex={type-index}"
params:
- name: type-index
type: string
description: "Type and index (e.g. spdif-2). Types: spdif, analog, coax, bluetooth, arc, earc, phono, computer, aesebu, balanced, microphone."
# --- Bluetooth ---
- id: bluetooth_mode
label: Set Bluetooth Mode
kind: action
command: "/audiomodes?bluetoothAutoplay={value}"
params:
- name: value
type: integer
description: 0 = Manual; 1 = Automatic; 2 = Guest; 3 = Disabled.
# --- LSDP discovery (UDP broadcast) ---
- id: lsdp_query_standard
label: LSDP Query (Broadcast Response)
kind: action
command: "UDP 11430 broadcast Query Message Type Q (0x51)"
params:
- name: classes
type: string
description: List of 16-bit service class identifiers to query.
- id: lsdp_query_unicast
label: LSDP Query (Unicast Response)
kind: action
command: "UDP 11430 unicast Query Message Type R (0x52)"
params:
- name: classes
type: string
description: List of 16-bit service class identifiers to query.
Feedbacks
- id: playback_state
type: enum
values: [play, pause, stop, stream, connecting]
description: Reported via <state> in /Status and command responses.
- id: volume_level
type: integer
description: 0..100, or -1 if volume fixed. From <volume> in /Status or /Volume response.
- id: volume_db
type: number
description: Current volume in dB. From <db> in /Status or /Volume response.
- id: mute_state
type: integer
description: 0 = unmuted; 1 = muted. From <mute> in /Status or /Volume response.
- id: shuffle_state
type: integer
description: 0 = off; 1 = on. From <shuffle> in /Status.
- id: repeat_state
type: integer
description: 0 = repeat queue; 1 = repeat track; 2 = repeat off. From <repeat> in /Status.
- id: etag
type: string
description: Opaque change-detection token returned in /Status and /SyncStatus root attributes.
- id: sync_stat
type: integer
description: Change id for /SyncStatus; matches <syncStat> in /Status.
- id: group_name
type: string
description: Name of the player group. From <group> in /SyncStatus.
- id: player_name
type: string
description: Player name. From <name> in /SyncStatus.
- id: player_model
type: string
description: Player model name. From <modelName> in /SyncStatus.
- id: player_brand
type: string
description: Player brand name. From <brand> in /SyncStatus.
- id: player_mac
type: string
description: Player unique id (often MAC address). From <mac> in /SyncStatus.
- id: track_title
type: string
description: Title of current track. From <title1>/<title2>/<title3> in /Status.
- id: track_artist
type: string
description: Artist of current track.
- id: track_album
type: string
description: Album of current track.
- id: service
type: string
description: Current music service id. From <service> in /Status.
- id: track_position_secs
type: integer
description: Seconds elapsed in current track. From <secs> in /Status.
- id: track_length_secs
type: integer
description: Total track length in seconds. From <totlen> in /Status.
- id: can_seek
type: integer
description: 1 if seeking is allowed. From <canSeek> in /Status.
Variables
# UNRESOLVED: volume range is configured per-player (default -80..0 dB); not settable via documented CI commands.
Events
# UNRESOLVED: unsolicited push notifications are not described in source; clients poll /Status or /SyncStatus with long polling.
Macros
# UNRESOLVED: source does not document named macros.
Safety
confirmation_required_for:
- delete # context-menu delete action: "User confirmation should be requested" (per source)
interlocks: []
# UNRESOLVED: no other safety procedures or interlocks documented in source.
Notes
- All BluOS CI requests are HTTP GET to
http://<player_ip>:11000/<request>unless noted. Reboot is HTTP POST to/reboot. - Default port is 11000. The NAD CI580 (4-streamer chassis) uses 11000/11010/11020/11030; not applicable to NAD 450 but mentioned for completeness.
- Discover port via mDNS services
musc.tcpandmusp.tcp, or use LSDP (UDP 11430 broadcast). - Long polling recommended for /Status (100s) and /SyncStatus (180s); do not poll /Status faster than once per 10s without long polling.
- Streaming radio actions (/Action) use URLs returned in the /Status
<actions>block — endpoint and parameters vary by service. - /Skip and /Back require no
<streamUrl>in /Status; use /Action for streaming radio navigation. - Input selection has two flavors: URL-based (active inputs via /RadioBrowse) and inputTypeIndex (firmware >=4.2.0). The legacy /Play?inputIndex= form applies only to firmware >3.8.0 and <4.2.0.
Self-check: no voltage/current invented, port 11000 + 11430 stated, no baud assumed, status=draft, confidence=low, YAML valid, unresolved markers present.
## Provenance
```yaml
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-14T19:51:48.199Z
last_checked_at: 2026-09-12T22:18:26.887Z
Verification Summary
verdict: verified
checked_at: 2026-09-12T22:18:26.887Z
matched_actions: 44
action_count: 44
confidence: medium
summary: "All 44 spec actions have literal source matches and transport values are confirmed; coverage ratio above 0.9. (6 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- /RadioBrowse
- /Settings
- "power on/off commands not documented in source (only soft reboot via POST /reboot is shown)"
- "volume range is configured per-player (default -80..0 dB); not settable via documented CI commands."
- "unsolicited push notifications are not described in source; clients poll /Status or /SyncStatus with long polling."
- "source does not document named macros."
- "no other safety procedures or interlocks documented in source."
- "NAD 450-specific firmware version not stated in source; protocol applicability based on BluOS family coverage."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0