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.1to 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¶
or on failure:
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:
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:
Example:
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:
or:
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 —
/statusdoesn't include current DMX values - Node health — current API doesn't surface which nodes are online (planned v0.2 feature)