Skip to content

IMMERSE Runtime HTTP API Reference

Version: 0.1.0 Default port: 7880 Default bind: 0.0.0.0 (all network interfaces) Authentication: none

This is the HTTP API exposed by IMMERSE Runtime. The web dashboard at / is one consumer; you can build your own operator clients (mobile apps, MIDI-to-HTTP bridges, voice assistants, scheduled show triggers) against the same endpoints.

Network security note. Runtime has no auth in v0.1.0 — anyone reachable on the network can fire cues. Run on a trusted local network only. Use --bind 127.0.0.1 to restrict to localhost.


Endpoints

Method Path Body Returns
GET / — Dashboard HTML
GET /dashboard.css — CSS for the dashboard
GET /dashboard.js — JS for the dashboard
GET /status — Status object (see below)
GET /cuelist — CueList object — full list of cues currently active
POST /go none / {} { ok, fired } or { ok: false, reason }
POST /back none { ok, nextCue }
POST /stop none { ok: true }
POST /fire { "cueId": "..." } { ok, fired }
POST /load { "path": "..." } { ok, projectName }

All API responses are JSON. Errors return { "ok": false, "error": "..." } plus an HTTP 4xx/5xx status code.


Response shapes

Status

{
  "projectName": "Main Stage Opening Night",
  "schema": "0.5.0",
  "activeCueList": "Cue List A",
  "nextCue": {
    "id": "cue-3",
    "num": "3.0",
    "name": "Lights up — Sunrise",
    "type": "dmx"
  },
  "tc": { "state": "playing", "ms": 12480 },
  "rooms": 1,
  "cues": 24
}

nextCue is null if there's no active cue list or all cues have been fired (pointer cleared).

tc.state is one of "stopped" | "playing" | "paused". tc.ms is the timecode position in milliseconds.

CueList

{
  "id": "cl-1",
  "name": "Cue List A",
  "cues": {
    "cue-1": { "num": "1.0", "type": "dmx", "name": "Sunrise", "dur": "2.00", "preWait": "0.00", "mode": "MANUAL", ... },
    "cue-2": { "num": "2.0", "type": "audio", ... }
  },
  "cueOrder": ["cue-1", "cue-2", ...]
}

The full per-cue fields depend on the cue's type. See ishow-schema.md for all 10 types and their fields.

Fire result

{ "ok": true, "fired": "3.0 Lights up" }

or on failure:

{ "ok": false, "reason": "no cue to fire — add one first" }

The fired string is "<num> <name>" for human display. Don't parse it — use /status to see what fired and what's next.


Endpoint details

GET /status

Snapshot of the show's current state. Safe to poll; the web dashboard polls every 250 ms.

Returns: Status object (see above), HTTP 200.

Example:

curl http://10.0.0.10:7880/status

GET /cuelist

Returns the active cue list with all of its cues. Use this when you need details Runtime's /status doesn't include — durations, modes, full names of every cue (not just the next one).

Returns: CueList object, HTTP 200. Or 404 with { "error": "no active cue list" } if no cue list is active.

Performance note. cueOrder length up to ~500 is fine; beyond that, prefer fetching once at dashboard startup and only refetching when the active list changes (the dashboard does this).

POST /go

Fires the next cue in the active cue list and advances the pointer.

If a specific cue is "selected" (in operator UI terms), Runtime fires that cue instead and positions the pointer right after it. If no cue list is active or the list is empty, returns { ok: false, reason: "..." }.

Body: none, or {}.

Returns:

{ "ok": true, "fired": "3.0 Lights up" }

Example:

curl -X POST http://10.0.0.10:7880/go

POST /back

Retreats the cue pointer by one. Does not fire a cue.

Returns: { "ok": true, "nextCue": "cue-2" } (the new "next" cue id).

POST /stop

Resets the cue pointer back to the top of the list and stops the timecode transport. Does not fire any cleanup cues — DMX channels hold their last value, audio/video continue if already playing.

To stop everything currently playing, you'd need to: 1. POST /stop to clear the pointer 2. POST /fire a "blackout" cue and a "stop all audio" cue separately

A future "panic stop" endpoint is under consideration.

POST /fire

Fires a specific cue by its id. Does not advance the cue pointer.

Body: { "cueId": "cue-12" }

Returns: Same shape as /go. 400 if cueId is missing. The fire result has ok: false if the cue id doesn't exist.

When to use: jumping to a specific cue out of order, building "scene jump" buttons in a custom operator UI, scripted show automation.

POST /load

Loads a different show file at runtime, without restarting Runtime.

Body: { "path": "/path/to/another-show.ishow" }

Returns:

{ "ok": true, "projectName": "Halloween Show 2026" }

or:

{ "ok": false, "error": "show failed validation with 2 error(s): ..." }

The path must be a server-side path that Runtime can read. If you're sending a show from a remote operator UI, you need to copy/upload the file to the Runtime PC first via some other channel (rsync, scp, etc.) — Runtime has no file upload endpoint in v0.1.0.


Error handling

HTTP code Meaning
200 OK; body is the result. May still be { ok: false, reason: ... } if the operation didn't succeed semantically (e.g. firing a nonexistent cue)
400 Bad request — malformed JSON, missing required field
404 Endpoint or resource not found
405 Wrong HTTP method (e.g. PUT to /go)
500 Runtime threw an unhandled exception. Check Runtime's log file.

The distinction between 200 with ok: false vs. 4xx is: - 2xx: the request was structurally valid, Runtime understood and processed it; the result might just be "no, that didn't work" (no cue to fire, etc.) - 4xx: the request itself was malformed or the endpoint doesn't exist


Common workflows

Custom operator UI

Poll /status every 250-500 ms. Render nextCue.num + nextCue.name. Wire up a GO button that POSTs to /go, a STOP button that POSTs to /stop, a BACK button that POSTs to /back. Show connection status from whether /status is responsive.

MIDI controller bridge

A small process listens for MIDI note events; on each "GO" note it POSTs to /go. On each cue jump (program change), it POSTs to /fire with the right cue id from a lookup table.

Scheduled show start

Cron job at 9:00am: curl -X POST http://localhost:7880/go. Script that fires a "houselights up + ambient music" sequence.

Show automation (no operator)

Author the show with mode: "AUTO" cues so each cue auto-advances after its duration. Configure Runtime to GO on startup. Show plays itself.


What this API doesn't do (yet)

These are reasonable additions for v0.2 if customers ask:

  • WebSocket/SSE for push updates — currently you must poll /status
  • Authentication — anyone on the network controls Runtime
  • Cue manipulation — can't add/edit/delete cues at runtime (re-author in Studio + reload)
  • Volume / level control — can't adjust audio volume mid-show without a custom cue
  • Live DMX channel inspection — /status doesn't include current DMX values
  • Node health — current API doesn't surface which nodes are online (planned v0.2 feature)