Appearance
Server API
Lumora exposes an HTTP API for triggering graphics from external tools. Stream Deck via Bitfocus Companion, automation scripts, vision-mixer macros, anything that can fire an HTTP request. Requests are authenticated with a long-lived API key minted from the control panel.
Client API
If you're running the Lumora Controller application on your Windows PC, you also have access to the Client API, documented here.
Authentication
Every /api/* endpoint requires an API key on the standard Authorization header:
http
Authorization: Bearer lumora_live_sk_<43 chars>Keys are long-lived workspace credentials. Stream Deck, Companion, and CI scripts store one once and reuse it indefinitely.
Minting a key
- In the control panel, open Settings → API Keys.
- Give it a label (e.g. "Stream Deck") then click Create key
- The raw key is shown once. Copy it into your automation tool immediately, as you can't retrieve it again.
API keys are available on Standard, Professional, and Enterprise plans. The Free plan does not include API access. Paid plans can mint as many keys as needed.
Key format
| Part | Length | Detail |
|---|---|---|
| Prefix | 15 chars | lumora_live_sk_ |
| Body | 43 chars | Base64URL random |
| Total | 58 chars | 256 bits of entropy |
Scope and safety
- Keys can call any
/api/*endpoint within the workspace they were minted in. - Keys only work against their own workspace. Using a key from one workspace against a different workspace's URL returns
403. - Keys cannot mint or revoke other keys. Only a signed-in human operator can manage keys via the modal.
- A leaked key's blast radius is bounded to
/api/*and can be cut off with one click from Settings → API Keys → Revoke. - Treat keys like passwords: don't commit them to git, don't paste them in screenshots, don't share them between workspaces.
Endpoints
All endpoints are rooted at your workspace's origin, e.g. https://your-workspace.app.lumora.live.
GET Requests
| Endpoint | Description |
|---|---|
/api/status/channelId | List all graphics currently live on a channel Returns: { "live": [...] } |
/api/status/channelId/graphicId | Check if a specific graphic is currently live on a channel Returns: { "live": true/false } |
/api/tally/channelId/pgm | Returns true if the channel is on program, false if not |
/api/tally/channelId/pvw | Returns true if the channel is on preview, false if not |
POST Requests
| Endpoint | Description |
|---|---|
/api/trigger/channelId/graphicId/on | Take a graphic live on a channel |
/api/trigger/channelId/graphicId/off | Take a graphic off on a channel |
/api/trigger/channelId/graphicId/action/actionName | Fire a named action on a live graphic (e.g. Advance, Reset). The graphic must be live |
/api/refresh-all | Refresh all data sources (Google Sheets, etc.). Equivalent to pressing F9 in the control panel. |
Parameters
| Name | Where to find it |
|---|---|
channelId | Output channel ID, e.g. cg1. Found in Outputs → Configure Outputs. |
graphicId | Unique graphic instance ID. Found in the graphic's Edit modal. |
actionName | Action name as defined in the template, e.g. Advance. Case-sensitive. |
Responses
Success
POST triggers and refresh-all return:
json
{ "ok": true }GET /status/{channelId}/{graphicId} returns:
json
{ "live": true }Error
json
{ "error": "Graphic not found" }Status codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 401 | Missing or invalid token |
| 403 | Workspace URL doesn't match API key |
| 404 | Channel, graphic, or action not found |
| 409 | Graphic is not live (action endpoints only) |
Examples
Read channel status
bash
curl -H "Authorization: Bearer lumora_live_sk_<your key>" \
https://your-workspace.app.lumora.live/api/status/cg1Take a graphic on-air
bash
curl -X POST \
-H "Authorization: Bearer lumora_live_sk_<your key>" \
https://your-workspace.app.lumora.live/api/trigger/cg1/<graphicId>/onFire a custom action
bash
curl -X POST \
-H "Authorization: Bearer lumora_live_sk_<your key>" \
https://your-workspace.app.lumora.live/api/trigger/cg1/<graphicId>/action/AdvanceRefresh all data sources
bash
curl -X POST \
-H "Authorization: Bearer lumora_live_sk_<your key>" \
https://your-workspace.app.lumora.live/api/refresh-allCommon integrations
There's no Lumora-specific plugin for any of these. They all drive the HTTP endpoints above directly. Configure each tool's generic HTTP action with your endpoint URL, set the method (GET or POST), and add the Authorization: Bearer ... header.
- Stream Deck. Elgato's built-in HTTP Request action (or the Web Requests plugin on older firmware) fires a request per button press. One button per endpoint is the typical setup: a "take on" button and a "take off" button per graphic you control regularly.
- Bitfocus Companion. Drop these endpoints into Companion's generic HTTP action; the
Authorizationheader is set per-button or globally in connection config. - OBS / vMix macros. Most switchers can fire an HTTP POST as part of a macro; use the trigger endpoints with the relevant
channelId/graphicId. - Custom scripts. Any language with an HTTP client works. The endpoints are stateless, so retry logic is straightforward.
Rate limits
API requests are rate-limited per workspace across two dimensions: a 60-second burst ceiling and a rolling 24-hour daily ceiling. Both apply on every request; whichever runs out first triggers a 429 Too Many Requests with a Retry-After header.
| Plan | Burst (per minute) | Daily |
|---|---|---|
| Standard | 100 | 10,000 |
| Professional | 300 | 30,000 |
| Enterprise | Set per account, contact us | Set per account, contact us |
Stream Deck / Companion typical usage (a handful of triggers per minute) is well within these limits. They exist to protect the workspace from runaway scripts.
Every response carries the standard RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers so you can pace yourself without waiting for a 429.
Troubleshooting
401 Unauthorized. The Authorization header is missing, malformed, or the key has been revoked. Re-mint a key and update your automation tool. Check for accidental whitespace before/after the key when pasting.
404 Not Found. Usually the wrong channelId or graphicId. The channel ID is the short ID (e.g. cg1), not the channel name. The graphic ID is shown in the graphic's Edit modal, not in the graphic list.
409 Conflict on an action endpoint. The graphic isn't currently live on that channel. Custom actions can only fire while the graphic is on-air. Take it on first, then fire the action.
Triggers fire but nothing happens on-air. Check the channel matches an actually-mapped output. A trigger to a channel with no output bound will return 200 but produce no visible result.