Skip to content

API Reference

The HOS server exposes four public communication surfaces: REST API (HTTP), Socket.IO (real-time client events), raw WebSocket (remote driver protocol), and SSE (server-sent events for live state). This page documents those surfaces plus the local process protocol used by OS-local uploaded drivers.

This page is a human-friendly summary of the HOS API surfaces. If an endpoint behaves unexpectedly, the running server is always the source of truth.


REST API — OS API

Base paths: /app/os, /api/os, /v1/os

Auth: Bearer token required (scope: os_api_admin). Pass as Authorization: Bearer <token>. Obtain a token via POST /auth/login.

Do not include actual tokens in requests from this docs page. Use <token> as a placeholder when sharing examples.

Auth

MethodPathAuthDescription
POST/auth/loginNoneLogin with credentials, returns bearer token
GET/auth/meRequiredAuthenticated principal info
POST/auth/stream-tokenRequiredIssue a short-lived token for SSE clients that cannot send auth headers

Bootstrap and Preferences

MethodPathDescription
GET/bootstrapFull system bootstrap — devices, spaces, programs, media, and current state in one payload
GET/preferences/homeHome screen preferences
POST/preferences/homeUpdate home preferences
GET/preferences/home/favoritesCurrent home favorite device keys
POST/preferences/home/favoritesSave home favorite device keys
GET/design-profilesList available design profiles
POST/design-profiles/selectSelect the active design profile
GET/design/liveCurrent live design

Devices

MethodPathDescription
GET/devicesList all logical devices
GET/devices/:idDevice details
GET/devices/:id/appsList launchable apps for app-capable devices
GET/devices/:id/apps/:appId/iconStream a device app icon
POST/devices/:id/apps/:appId/launchLaunch an app on a supported device
GET/devices/:id/equalizerRead equalizer-capable command/state summary
POST/devices/:id/equalizerDispatch an equalizer or sound-mode command
POST/devices/:id/commandDispatch a command (Standard or IR-mapped)
GET/devices/:id/scenesList scenes exposed by a supported device
POST/devices/:id/metadataUpdate tags, primary room, or remote-source metadata

IR Device Properties

Devices using the GENERIC_IR driver include specific metadata in their properties object:

  • extenderIp: The target hardware bridge IP address.
  • irCommands: A dictionary of command keys to raw IR pulse objects.
    json
    {
      "turn_on": {
        "freq_khz": 38,
        "raw": [4500, 4500, 560, ...]
      }
    }

Spaces

MethodPathDescription
GET/spacesList all spaces
POST/spaces/saveCreate or update a space
POST/spaces/:id/removeRemove a space
GET/spaces/:id/devicesDevices assigned to a space
GET/spaces/:id/remote-sourcesRemote sources for a space
POST/spaces/:id/remote-sources/:sourceId/activateActivate a remote source
POST/spaces/:id/devices/assignAssign devices to a space

Programs

MethodPathDescription
GET/programsList all programs
POST/programs/saveCreate or update a program. Accepts canonical script arrays and YAML authoring fields; see Program YAML Scripts.
POST/programs/:id/runExecute a program
POST/programs/:id/run-offExecute the program off path
POST/programs/:id/removeRemove a program
POST/programs/:id/copyDuplicate a program
POST/programs/:id/timerUpdate a program timer
POST/programs/:id/scriptUpdate a program script
POST/programs/:id/lighting/offTurn off program lighting

Activities, Zones, Macros, and Alerts

MethodPathDescription
GET/activity-presetsList activity presets generated from programs and mapped controls
POST/activity-presets/:id/runRun an activity preset
GET/zonesList zones with resolved device/program references
POST/zones/:id/volumeSet zone volume on one or more volume-capable devices
POST/zones/:id/program/runRun a program assigned to a zone
GET/zone-groupsList zone groups
POST/zone-groups/saveCreate or update a zone group
POST/zone-groups/:id/removeRemove a zone group
POST/zone-groups/:id/zones/assignAssign zones to a zone group
GET/macrosList macros
POST/macros/saveCreate or update a macro
POST/macros/:id/removeRemove a macro
POST/macros/:id/runRun a macro
GET/alerts/submissionsList submitted alert events
POST/alerts/submissionsSubmit an alert event

State Stream

MethodPathDescription
GET/state/snapshotCurrent device state snapshot (point-in-time)
GET/state/streamSSE live state stream — see SSE section below
GET/state/telemetry/:deviceIdTelemetry data for a specific device

Haptique Music API

The dedicated developer guide for music apps and playback endpoints is now available at Haptique Music API.

Core music routes:

MethodPathDescription
GET/media/playersCanonical playable media-player roster
POST/media/players/:id/commandNormalized media-player command
GET/media-services/statusFull music-service status snapshot
POST/media-services/statusFull music-service status snapshot with request-body options
GET/media-services/playersMusic Services player roster
GET/media-services/endpointsLocal and provider playback endpoints
POST/media-services/endpoints/discoverRefresh endpoint discovery
POST/media-services/endpoints/updateUpdate endpoint label or enabled state
POST/media-services/endpoints/airplay/pair/startStart AirPlay endpoint pairing
POST/media-services/endpoints/airplay/pair/finishFinish AirPlay endpoint pairing
POST/media-services/searchSearch connected music sources
POST/media-services/playStart playback on a target
POST/media-services/commandSend target-level playback command
POST/media-services/transferTransfer playback or queue to another target
GET/media-services/queue/:targetIdRead a playback queue
POST/media-services/bridge/endpoints/registerRegister a Music Bridge playback endpoint

Local Media Controller

These endpoints expose the local OS media-controller state and commands, currently used for local Apple Music style control surfaces.

MethodPathDescription
GET/media-controller/stateCurrent local media-controller snapshot
POST/media-controller/controlExecute a local media-controller action
GET/media-controller/streamSSE stream for local media-controller now-playing changes

Integration Releases

MethodPathDescription
GET/integration-releasesList integration releases
GET/integration-releases/:keyGet details for a specific release
GET/integration-releases/:key/submission-packageGet the submission package
POST/integration-releases/saveSave a release
POST/integration-releases/:key/submitSubmit a release
POST/integration-releases/:key/unsubmitUnsubmit a release
POST/integration-releases/:key/rollbackRoll back a release

Fleet Management (Phase 06)

These endpoints manage the HOS fleet and bridge connectivity.

MethodPathAuthDescription
GET/hos-fleet-devicesosApiAuthList HOS devices with their Fleet Release status
POST/hos-fleet-devices/releases/:key/statusosApiAuthUpdate Fleet Release status for a specific OS logical device
POST/device/hos/categoryappAuthCreate or update an HOS device category
POST/integration/hos/device/commandappAuthDispatch a command to a specific HOS device in the fleet
POST/bridge/devices/:fleetDeviceId/commandosBridgeAuthSend a command to a fleet device via the OS bridge

Bridge (Fleet)

Bridge endpoints serve two auth modes: osApiAuth (for HOS admin-level callers) and osBridgeAuth (for bridge/fleet peer callers).

MethodPathAuthDescription
GET/bridge/linkosApiAuthGet bridge link info
POST/bridge/link/saveosApiAuthSave bridge link
POST/bridge/tokenosApiAuthGet bridge token
GET/bridge/healthosBridgeAuthBridge health check
GET/bridge/capabilitiesosBridgeAuthBridge capabilities
GET/bridge/devicesosBridgeAuthList bridge devices
GET/bridge/devices/stateosBridgeAuthDevice states from bridge
POST/bridge/devices/registerosBridgeAuthRegister a bridge device
POST/bridge/devices/updateosBridgeAuthUpdate a bridge device
POST/bridge/devices/:fleetDeviceId/commandosBridgeAuthSend command to a fleet device

HomeKit

MethodPathDescription
GET/homekit/statusHomeKit bridge status
GET/homekit/accessoriesList HomeKit accessories
GET/homekit/import-accessoriesList importable accessories
GET/homekit/pluginsList HomeKit plugins
GET/homekit/plugins/searchSearch plugin catalog
GET/homekit/plugins/resolveResolve plugin metadata
GET/homekit/plugins/:pluginId/config-schemaPlugin configuration schema
GET/homekit/plugins/:pluginIdPlugin details
POST/homekit/plugins/customAdd a custom plugin catalog entry
POST/homekit/plugins/:pluginId/catalog-removeRemove a plugin catalog entry
POST/homekit/plugins/:pluginId/installInstall a plugin
POST/homekit/plugins/:pluginId/uninstallUninstall a plugin
POST/homekit/plugins/:pluginId/enableEnable a plugin
POST/homekit/plugins/:pluginId/disableDisable a plugin
POST/homekit/plugins/:pluginId/configConfigure a plugin
POST/homekit/settingsUpdate HomeKit settings
POST/homekit/resyncResync HomeKit bridge
POST/homekit/import-accessories/resyncRefresh importable HomeKit accessories
POST/homekit/import-accessories/:accessoryId/importImport a HomeKit accessory as an OS logical device
POST/homekit/import-accessories/:accessoryId/removeRemove an imported HomeKit accessory
GET/homekit/plugin/bootstrapPlugin bridge bootstrap (plugin bridge auth)
GET/homekit/plugin/state/streamPlugin state stream SSE (plugin bridge auth)
POST/homekit/plugin/devices/:id/commandSend command via plugin bridge
POST/homekit/plugin/external-accessories/syncSync external accessories from a plugin bridge
GET/homekit/plugin/import-commandsPull pending import commands for a plugin bridge
POST/homekit/plugin/import-commands/:commandId/ackAcknowledge a plugin import command

AI

MethodPathDescription
GET/ai/statusGet AI service status (installed, running, modelReady, download progress)
GET/ai/healthCheck AI service health
GET/ai/suggestionsGet AI chat suggestions/prompts
GET/ai/modelsList available AI models
POST/ai/installInstall a specific AI model
POST/ai/startStart the AI service
POST/ai/stopStop the AI service
POST/ai/promptSend a prompt to the AI. Use ?sync=true for immediate response.
GET/ai/eventsSSE stream for AI events (generation progress, status updates)
DELETE/ai/uninstallUninstall the current AI model

REST API — App API

Base paths: /app, /api

Auth: appAuth middleware (session-based for the legacy app surface)

This is the legacy API surface consumed by earlier mobile client versions and the web admin panel. Key endpoint families:

PrefixPurpose
/auth/*App login, register, logout
/devices/*Device listing and commands
/entity/*Entity-level operations
/room/*Room/space operations (legacy)
/integration/*Integration management
/programs/*Program CRUD and execution
/sequences/*Sequence operations
/zonesZone listing
/action-mapsAction map listing
/media-services/*Media service status and commands

REST API — Other Route Families

PrefixAuthPurpose
/remote, /v1/remoteremoteAuthRemote-controller API for pairing and command dispatch
/adminAdmin authAdmin panel routes
/osSessionServer-rendered EJS web UI (the OS frontend)
/devNone (dev only)Debug routes — available in development only

Socket.IO Events

Connection path: /socket.io (default Socket.IO path)

The server exposes multiple Socket.IO namespaces. Each namespace handles a specific concern.

Namespaces and Events

NamespaceEventDirectionPayload
/socket/device-statedevice:state:updateserver → client{ deviceId: string, state: object }
/socket/device-statedevice:state:snapshotserver → client{ deviceId: string, state: object }
/socket/haptique-protocolhaptique:commandclient → server{ command: string, payload: object }
/socket/haptique-protocolhaptique:responseserver → client{ command: string, data: unknown, ok: boolean }
/socket/haptique-protocolhaptique:eventserver → clientHaptiqueProtocolEvent
/socket/remote-connectremote:pairingclient → serverPairing request payload
/socket/remote-connectremote:pairing:statusserver → clientPairing result
/socket/designerdesigner:publishedserver → clientDesign payload
/socket/designerdesigner:refreshserver → clientRefresh signal
/socket/device-ir-testir:dataserver → clientIR signal data

Haptique Protocol Commands

Commands are sent client → server via the haptique:command event on the /socket/haptique-protocol namespace. Format: { command: "<COMMAND_NAME>", payload: { ... } }.

CommandDescription
GET_PROTOCOL_CAPABILITIESList capabilities supported by the protocol hub
LIST_EVENTSList available protocol event types
SYSTEM_SNAPSHOTFull system state snapshot
LIST_INTEGRATIONSList all loaded integrations
LIST_CONNECTIONSList active integration connections
LIST_SCENESList all scenes
SCENE_RUNExecute a scene by ID
LIST_ENTITY_DOMAINSList entity domains (lighting, climate, etc.)
LIST_ENTITIESList all entities
GET_ENTITYGet a single entity by ID
ENTITY_ACTIONPerform an action on an entity
LIST_STATESList all device states
GET_DEVICE_STATEGet state for a specific device
LIST_SENSORSList sensor entities
LIST_PROGRAMSList all programs
LIST_AUTOMATIONSList all automations
LIST_ACTION_MAPSList action maps
LIST_ZONESList zones
LIST_DRIVERSList active drivers
LIST_DEVICESList all devices (protocol-level)
LIST_DEVICE_COMMANDSList commands available for a device
GET_DEVICE_COMMANDGet a specific device command definition
EXECUTE_DEVICE_COMMANDExecute a device command
GET_HOME_GRAPHGet the home graph structure
LIST_CAPABILITY_MODELList the capability model definitions
LIST_PROGRAM_SEMANTICSList program semantic definitions
UPSERT_PROGRAM_SEMANTICCreate or update a program semantic
DELETE_PROGRAM_SEMANTICDelete a program semantic
GET_CONTEXT_SNAPSHOTGet contextual system snapshot
INTENT_PARSEParse a natural language intent
INTENT_EXECUTEExecute a parsed intent
PROGRAM_RUNRun a program by ID
AUTOMATION_RUNRun an automation by ID
ACTION_MAP_TRIGGERTrigger an action map
DEVICE_ACTIONDispatch a raw device action
DRIVER_MESSAGEForward a message to a driver

Remote Driver WebSocket Protocol

Transport: Raw WebSocket (ws library — NOT Socket.IO)

Path: /driver on DRIVER_WS_PORT (defaults to the same port as PORT if DRIVER_WS_PORT is not set)

This protocol is for external SDK-style driver processes only. Mobile clients and external callers should use the Socket.IO or REST surfaces above. OS-local uploaded Python, Lua, and JavaScript drivers use the local process protocol described below instead of opening this WebSocket.

For comprehensive driver protocol documentation with full message schemas, connection lifecycle diagrams, and driver authoring guidance, see the sdk/docs/ directory. The SDK has detailed protocol guides for driver authors.

Registration Handshake

When a driver WebSocket connection is established, the driver must immediately send a registration message:

json
{
  "method": "driver.register",
  "driverKey": "MY_DRIVER",
  "instanceId": "my-driver-001",
  "protocolVersion": 1
}
FieldTypeDescription
method"driver.register"Must be exactly this string
driverKeystringUnique identifier for the driver type (e.g., "HUE", "DENON")
instanceIdstringUnique identifier for this driver instance
protocolVersionnumberProtocol version — use 1

Driver → Server Event Types

After registration, drivers send events using the following types:

Event TypePurpose
DEVICE_DISCOVEREDNotify server of a new device found by this driver
DEVICE_UPDATEDNotify server that device metadata has changed
DEVICE_REMOVEDNotify server that a device is no longer available
STATE_UPDATEPush a device state update to the server
ACTION_RESULTReport the result of a command execution requested by the server
METRIC_UPDATEPush telemetry/metric data for a device

Server → Driver Messages

Message TypePurpose
ACTIONServer instructs driver to execute a command on a device
DRIVER_STATUSServer sends a status notification to the driver

Local Driver Process Protocol

OS-local drivers uploaded through Integration Manager are launched by DriverManager from a *.driver.json manifest. They communicate with HOS over newline-delimited JSON on stdin/stdout.

Supported local upload runtimes:

Manifest driverTypeFile extension
python.py
javascript.js
lua.lua

Runtime rules:

  • The manifest supplies driverKey, driverFile, setup properties, commands, io, and envMap.
  • HOS writes one command JSON object per stdin line.
  • Drivers write one event JSON object per stdout line.
  • JavaScript drivers are plain Node-compatible .js; TypeScript must be compiled before upload.
  • JavaScript should prefer Node 20+ built-ins (fetch, net, dgram, readline) and only include package.json when external dependencies are required.

Common local incoming messages:

Message TypePurpose
ACTIONExecute a user, automation, or mapped device action
COMMAND_EXECUTEExecute a command-catalog action
PINGOptional runtime health probe

Common local outgoing events match the WebSocket protocol event names: DEVICE_DISCOVERED, DEVICE_UPDATED, DEVICE_REMOVED, STATE_UPDATE, ACTION_RESULT, and optional METRIC_UPDATE.


SSE Stream

Endpoint: GET /app/os/state/stream

Auth: Bearer token passed as a query parameter: ?accessToken=<token>

The SSE stream delivers real-time device state changes and protocol events to any HTTP client that supports server-sent events.

Events

EventPayloadWhen
ready{}Sent immediately on connection established
snapshotFull device state map (all devices)Sent immediately after ready
state{ deviceId: string, state: object }Sent on every device state change
eventHaptiqueProtocolEventSent on protocol hub events
ping{}Periodic heartbeat to keep connection alive

Example SSE consumer (Node.js)

typescript
const EventSource = require('eventsource');
const es = new EventSource('http://localhost:8080/app/os/state/stream?accessToken=<token>');

es.addEventListener('snapshot', (e) => {
  const allState = JSON.parse(e.data);
  console.log('Initial state:', allState);
});

es.addEventListener('state', (e) => {
  const { deviceId, state } = JSON.parse(e.data);
  console.log(`${deviceId} updated:`, state);
});

Cross-References