Appearance
Client API
The Lumora Controller desktop app runs a lightweight HTTP server on your local machine, accessible to any device on the same network. Use it to fire hotkey-equivalent actions like take on, take off, advance, panic, and refresh, and to query which graphic and channel are currently active. No API key required; access is gated by the local network only.
Server API
Looking for the cloud-side API for triggering specific graphics by ID from anywhere on the internet? See the Server API.
When to use which
| Use this | If you want to… |
|---|---|
| Server API | Trigger a specific graphic by ID from anywhere on the internet, regardless of what the operator has selected. Authenticated, internet-exposed. |
| Client API | Drive whatever the operator currently has selected. Same outcome as pressing a hotkey. LAN-only, no auth. |
The Client API is the right fit for hardware controllers (Stream Deck, foot pedals, deck builders) that sit beside the operator on the same network and act as remote hotkeys. Pressing a Stream Deck button feels exactly like pressing Numpad +.
Network access
The controller binds the API server to all network interfaces, so any device on the same LAN can reach it:
text
http://<controller-ip>:<port>- No authentication. There's no PIN, header, or token. Anyone on the same network can hit the endpoints.
- HTTP, not HTTPS. Local-network-only, plain HTTP. Don't expose the port to the public internet.
- Same-LAN only by default. If you need cross-network access (e.g. a Stream Deck on a different VLAN), use a reverse proxy or VPN. Don't port-forward directly.
Security model
The Client API trusts the local network. On a production network this is fine, as only the operator's gear can reach it. On a shared or public Wi-Fi network it isn't. Treat the controller's port like any other unauthenticated LAN service.
Port configuration
The default port is 3031. To change it, open the controller and go to Settings → API → Client tab.
- Port range: 1024–65535
- Default: 3031
- Changing the port restarts the local API server immediately. Any in-flight Stream Deck / Companion bindings need updating to the new port.
To find the controller's local IP, the Client tab in the API modal shows it inline (e.g. http://192.168.1.42:3031). On Windows you can also run ipconfig and look for the IPv4 address on your active adapter.
Endpoints
All endpoints are rooted at http://<controller-ip>:<port>. None of them take path or query parameters. They all act on the operator's currently-selected graphic and active channel.
GET Requests
| Endpoint | Description |
|---|---|
/graphic/name | Name of the currently selected graphic as a JSON string, or null if nothing is selected |
/channel/number | Active output channel number (1-based integer) |
/channel/name | Active output channel name as a JSON string |
POST Requests
| Endpoint | Description | Hotkey equivalent |
|---|---|---|
/take/on | Take the selected graphic on to the active channel | Numpad Enter |
/take/off | Take the selected graphic off the active channel (no advance) | Numpad − (without advance) |
/take/on/next | Take on, then advance selection to the next graphic | Numpad + |
/take/off/next | Take off, then advance selection to the next graphic | Numpad − |
/clear | Clear all graphics from the active channel | (none) |
/panic | Instantly clear all graphics from all channels | Esc Esc |
/refresh-preview | Reload the graphic preview iframe | F8 |
See Hotkeys for the full keyboard reference.
Responses
POST requests
json
{ "ok": true }GET requests
GET endpoints return raw JSON values, not wrapped objects:
json
"Lower Third"json
3json
nullThe null value is returned when nothing is selected (/graphic/name) or when no channel is active.
Status codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 404 | Endpoint not found (typo in path) |
| 500 | Controller error. Check the controller log |
There's no 401 because there's no authentication, and no 409 because POST actions are always accepted and behave as no-ops if there's nothing to act on (e.g. /take/on with no graphic selected).
Examples
Read the active channel name
bash
curl http://192.168.1.42:3031/channel/nameTake the selected graphic on-air
bash
curl -X POST http://192.168.1.42:3031/take/onTake on and advance (Numpad + equivalent)
bash
curl -X POST http://192.168.1.42:3031/take/on/nextPanic, clear everything
bash
curl -X POST http://192.168.1.42:3031/panicReload the preview
bash
curl -X POST http://192.168.1.42:3031/refresh-previewCommon integrations
The Client API has no Lumora-specific plugins. All of these drive the endpoints above with each tool's generic HTTP action.
- Stream Deck. Elgato's built-in HTTP Request action fires a request per button press. The Client API is particularly well-suited here: one button per hotkey-equivalent action, with no need to track graphic IDs as the show evolves.
- Bitfocus Companion. Point Companion at
http://<controller-ip>:<port>and use generic HTTP actions for each button. - Foot pedals / hardware controllers. Anything that can fire an HTTP request on press works. The "no auth" model is a feature here: hardware integrations can be set up in seconds.
- Custom scripts. Useful for show-day automation that needs to read state (
GET /graphic/name) and react.
Troubleshooting
Connection refused. The controller isn't running, or it's running but the API server is bound to a different port. Open the controller and check Settings → API → Client for the actual port.
Endpoint reachable from the controller machine but not from the Stream Deck PC. Usually a Windows Firewall block. Allow the controller through the firewall on private networks. Alternatively, check that both devices are on the same subnet.
Wrong graphic fires. The Client API acts on whatever the operator has selected. If the Stream Deck button takes the wrong thing on-air, the operator's selection drifted from what you expected. Use the Server API instead if you need to target a specific graphic by ID regardless of operator selection.
Port in use. Another application on the controller machine is already bound to the same port (common conflicts: 3000, 8080, 8000). Pick a port in the range 1024–65535 that nothing else uses. The controller will refuse to start with a clear error if the port is taken.
Returns 404 on a known endpoint. Check for trailing slashes. POST /take/on/ with a trailing slash may differ from POST /take/on.