API reference

HTTP API

REST endpoints for activating content, controlling outputs, and firing actions from external systems.

REST endpoints for controlling Lightpath from external systems. All paths are relative to your install's base URL — for the examples below, replace <your-install> with the actual host (e.g. http://192.168.1.50:3001).

# Default for a local install
BASE_URL="http://localhost:3001/api"

Authentication

Every endpoint except /api/health and /api/login requires a bearer token. Send it as Authorization: Bearer <token> on every request.

Get a token

TOKEN=$(curl -s -X POST "$BASE_URL/login" \
  -H "Content-Type: application/json" \
  -d '{ "username": "you@example.com", "password": "..." }' \
  | jq -r .token)

POST /api/login accepts either email or username plus password. It tries the cloud first (the default for Digital Ambiance and team accounts) and falls back to the project's local user store on LAN-only requests when a project is loaded — so air-gapped installs work with the same endpoint.

Use the token

Send it as a bearer token on any authenticated endpoint:

curl "$BASE_URL/looks" -H "Authorization: Bearer $TOKEN"

Local fallback only runs on LAN. Requests through a Cloudflare tunnel must succeed against the cloud — the server won't try local for tunnel requests.

The server also exposes /api/auth/refresh, /api/auth/refresh-session, /api/auth/reset-password, /api/auth/send-reset-email, and a few other token-management endpoints used by the official Lightpath client. These aren't part of the integration surface — third-party callers only need /api/login and the bearer token it returns.

System integrations

For machine-to-machine integrations (Crestron control systems, lighting boards, third-party show-control software) the simplest pattern is to create a dedicated service user — e.g. crestron-integration — with the operator role, then log in with that user's credentials and cache the returned token. Re-login when the token expires (default 30 days) or on a 401 response. Long-lived integration API keys are on the roadmap and will use the same Authorization: Bearer header, so any code you write against this auth model today will keep working.

Catalog

Read what's available in the loaded project. Authenticated.

MethodPathDescription
GET/sourcesAvailable sources published by TouchDesigner
GET/effectsAvailable effects published by TouchDesigner

Content queries

Read content definitions. All require Authorization: Bearer <token>.

MethodPathDescription
GET/looksAll looks
GET/looks/:nameA specific look
GET/scenesAll scenes
GET/scenes/:nameA specific scene
GET/sequencesAll sequences
GET/sequences/:nameA specific sequence
GET/playlistsAll playlists
GET/playlists/:nameA specific playlist
GET/palettesAll palettes
List looks
curl "$BASE_URL/looks" -H "Authorization: Bearer $TOKEN"

Content activation

Activate looks, scenes, and playlists. Authenticated.

MethodPathDescription
POST/looks/:name/activateActivate a look by name
POST/scenes/:name/activateActivate a scene across all outputs
POST/playlists/:name/activateStart a playlist (per-output or global, auto-detected)
Activate a look
curl -X POST "$BASE_URL/looks/Sunset/activate" \
  -H "Authorization: Bearer $TOKEN"

Each look is bound to a single output at design time — the look activates on that output automatically; no body is required.

Playlist control

Add ?output=Name for per-output, omit for global. Authenticated.

MethodPathDescription
POST/playlists/pausePause playlist
POST/playlists/resumeResume playlist
POST/playlists/stopStop playlist
POST/playlists/nextAdvance to next track (requires ?output=Name)
POST/playlists/prevGo to previous track (requires ?output=Name)
POST/playlists/trackJump to a specific track
POST/playlists/loopToggle loop mode
Jump to track 2 on Output 1
curl -X POST "$BASE_URL/playlists/track" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "index": 2, "output": "Output 1" }'

Actions

Execute actions and set toggle states. Authenticated.

MethodPathDescription
GET/actionsGet all actions
POST/actions/:name/executeExecute an action by name
POST/actions/:name/stateSet a toggle action to a specific state
Fire an action
curl -X POST "$BASE_URL/actions/All%20Lights%20On/execute" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "targetState": true }'

Output control

Brightness and power state per output. Authenticated.

MethodPathDescription
GET/outputsGet all outputs
POST/outputs/:name/dimmerSet output brightness (0.0 – 1.0)
POST/outputs/:name/enabledEnable or disable an output
Set output brightness
curl -X POST "$BASE_URL/outputs/Facade/dimmer" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "value": 0.75 }'

Playback

Global playback control and status. Authenticated.

MethodPathDescription
POST/playback/stopStop all playback across all outputs
GET/playback/statusGet playback status for all playlists

Health

The only public endpoint besides /api/login. Useful for liveness probes.

MethodPathDescription
GET/healthStatus, uptime, version

Errors

The API uses standard HTTP status codes.

StatusMeaning
200Success
400Bad request — missing/invalid body or query parameters
401Missing or expired bearer token
403Authenticated but not authorized (e.g., wrong org for the loaded project, or local login attempted over a tunnel)
404Resource not found (e.g., /looks/Unknown)
500Server error

Error responses are JSON:

{ "error": "Invalid or expired token" }

On this page