The Lucent Cube runs an HTTP service (cubed) on your local network. Everything the companion app does is available over this open, JSON API — playback, settings, playlists, the parameters of any running app, casting, emulators, shaders and smart-home — so you can script, automate, or build your own controllers and apps. The cube also speaks Art-Net and sACN for lighting rigs.
Calls go to your cube on your LAN. Responses are JSON; errors return a non-2xx status with {"error":"…"}.
| Item | Value |
|---|---|
| Base URL | http://<cube-ip>:8000 (port configurable) |
| Format | JSON request bodies and responses |
| CORS | Open (Access-Control-Allow-Origin: *) — callable from browser apps |
| Auth | None — access is scoped to your local network |
curl http://<cube-ip>:8000/status
curl -X POST http://<cube-ip>:8000/brightness -d '{"brightness":60}'
{"service":"cubed","version":"1.0.0"}.voltage, soc, temp_c, chip, psu_present (or null values + error if no reading yet).| Field | Type | Notes |
|---|---|---|
images | string or string[] | Required. A path/glob, or an array of them. |
brightness | number | Optional. Omit to keep current. |
random | bool / 0–1 | Optional. Shuffle the set. |
offset (int, default 1; negatives go back).brightness (required).{"ok":true}.which — welcome or wifi.| Field | Range | Meaning |
|---|---|---|
brightness | 0–100 | Display brightness (%) |
transition_ms | 0–10000 | Crossfade/transition duration |
crossfade | bool | Enable crossfade between items |
seconds_per_entry | 0–3600 | Dwell time per playlist item |
pingpong | bool | Bounce playlists instead of looping |
face_mask | 0–63 | Bitmask of active faces |
cub_display_mode | 0–2 | Standard / Vertex / Flat wrap |
ar_mode · ar_intensity | — | Audio-reactivity mode and strength |
audio_gain · audio_noise_gate | — | Audio input tuning |
viz_mode | -1–999 | Active visualiser (-1 = off/auto) |
viz_gain_bass · _lowmid · _highmid · _highs | — | Per-band visualiser gain |
viz_cube_mode | 0–3 | How a visualiser maps across faces |
viz_cycle_secs | 0–3600 | Auto-cycle interval for visualisers |
viz_text | string | Typography visualiser's display text |
accel_invert | bool | Invert accelerometer axis |
volume · volume_precise | 0–100 | Output volume (coarse / fine) |
sound_mono | bool | Downmix game/app SFX to mono |
boot_anim | bool | Play the boot animation on startup |
startup | string | Name of the app/game to launch on boot |
startup_schedule_enabled | bool | Restrict the startup app to a daily time window |
startup_from_min · startup_to_min | 0–1439 | Window start/end, minutes since midnight |
led_rgb_sequence | string | Panel colour-channel order (e.g. BGR) |
game_difficulty | int | Default difficulty for games that support it |
audio_device | string | ALSA capture device for audio-reactivity |
index, name, description, tags, date_added.name, path, description, tags, thumbnail, type, date_added.name and/or path (name is resolved against games then apps).modes (int[], required), random (optional).Apps declare their own controls (sliders, toggles, selects, buttons) and can publish live values back. This is the same channel the companion's settings pages use, so anything you can change by hand you can change from a script — including the DMX app, Orbi, Aquarium and the rest.
app (empty if the current activity has no controls), launch_seq, plus controls and status arrays. Each slot carries:| Field | Meaning |
|---|---|
id | Control id, as used by /app-param |
kind | 1 trigger · 2 bool · 3 int/select · 4 float/slider · 5 string/label |
int · float · text | Current value, by kind |
trigger_seq | Increments each time a button fires |
status holds values the app publishes back — live readouts rather than settings.id plus a value. Use value and the cube coerces it to the control's declared type, or name the type explicitly:| Field | Type | Notes |
|---|---|---|
id | string | Required. Must match a control on the running app. |
value | any | Coerced to the control's kind. Easiest option. |
bool · int · float · text | typed | Explicit alternatives to value. |
trigger | any | Presence fires a button control. |
# what can I change on whatever is running?
curl http://<cube-ip>:8000/app-params
# put the DMX app into 16x16 pixel mode, then run a demo look
curl -X POST http://<cube-ip>:8000/app-param -d '{"id":"mode","value":3}'
curl -X POST http://<cube-ip>:8000/app-param -d '{"id":"testpat","value":15}'
w, h (16–512, default 256×192); pixel data in the body.{"count":n}.images (required path/glob); optional thumbnails via thumb_frame, thumb_size (max 128), thumb_block (0 standard / 1 vertex / 2 flat).filename (required).path (required).paths (string[], required)./library).id (required).id, name, type, items (string[]), action (default set).id (required), random (optional).id (required).The cube serves two of its own browser UIs — /roms (ROM manager) and /shaders (shader editor). Both return HTML, not JSON; the endpoints below are the JSON API behind them.
system to filter to one.system, url (http/https only).system, name (extension must match the system); file in the body.system, file.text/plain. Query: name.name (must end .frag); GLSL in the body, 64 KB max.file.receiver, spotify, airplay, youtube) keeps advertising in the background. POST body: app, enabled.app, enabled.bass, lowmid, highmid, treble.released. When true, drops live cast sessions and stops advertising — how "off" is made to stick.enabled, mac, name.mac.The cube can appear as a Matter device on your local network — no cloud, no account linking, no skill to enable.
{"enabled":bool,"control_port":8090}.enabled.event (string, 24 chars max). Lets your own code stand in for a controller.{"count":n}.The cube also speaks the lighting industry's own protocols, which are not part of this HTTP API. Run the DMX app and the cube listens for Art-Net (UDP 6454) and sACN / E1.31 (UDP 5568), so any lighting console or media server can drive it — as a fixture with a 21-channel personality, as six colour zones, or as a pixel-mapped display up to 32×32 per face. It answers Art-Net polls, so it appears by name in a console's node list. Configure it from the app's own settings page; there is nothing to set up here.
hw_model. POST fields (all trigger a renderer restart):| Field | Range | Meaning |
|---|---|---|
led_slowdown_gpio | 0–4 (-1 = auto) | GPIO timing for the panel chain |
led_pwm_bits | 1–11 | Colour depth vs refresh trade-off |
render_cpu | -1–3 | CPU core pinning for the render thread |
rt_priority | 1–99 | Real-time scheduling priority |
enable_thread_pinning | bool | Pin render thread to a core |