Files
ledgrab/docs/API.md
T
alexei.dolgolyov 0409cd8b66 feat(calibration): auto edge-calibration backend core (phase 1)
Backend engine for guided LED-chase calibration, driven by the upcoming
auto-calibration UI (phase 3) and first-run wizard (phase 4).

- solve_calibration(): pure function mapping start corner + direction + 4
  corner-tap indices to per-edge LED counts, consistent with EDGE_ORDER/
  EDGE_REVERSE so it round-trips through build_segments().
- CalibrationChaseMixin.set_calibration_pixel(): light a specific LED index
  (+ optional window) on a device, reusing the device_test_mode idle-client
  send path.
- CalibrationSession: single-active session with start/position/stop/cancel,
  a 60s idle-timeout watchdog, and a concurrency lock so interleaved calls
  can't corrupt the stop/restore bookkeeping — start() stops + remembers any
  running target on the device and stop/cancel/timeout always restore it
  (never leaves the device dark or stuck in chase).
- Routes /api/v1/calibration/{session,session/position,session/stop,
  session/cancel,session/state,solve} (all AuthRequired, bounds-validated);
  calibration is persisted by reusing the existing PUT /color-strip-sources/
  {id} (hot-reloads running streams) rather than a duplicate endpoint.
- Tests: 19 solver pure-logic + 19 route/bounds. docs/API.md updated.

Part of the edge-calibration + first-run-wizard feature (Big Bang; intermediate
phase — full build/suite gated at the final phase).
2026-06-08 14:59:58 +03:00

739 lines
39 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# LedGrab API Reference
Complete REST + WebSocket API reference for the LedGrab server.
- **Base URL:** `http://localhost:8080`
- **API version:** `v1` (all REST paths are under `/api/v1`, except `/health`)
- **Interactive docs:** Swagger UI at [`/docs`](http://localhost:8080/docs), ReDoc at [`/redoc`](http://localhost:8080/redoc), raw schema at [`/openapi.json`](http://localhost:8080/openapi.json). The interactive docs are always the authoritative, up-to-date source for request/response schemas — this file is a hand-maintained overview.
> The application version is reported by `GET /api/v1/version`; this document is version-agnostic.
---
## Table of Contents
- [Authentication](#authentication)
- [Conventions](#conventions)
- [WebSocket protocol](#websocket-protocol)
- [Worked examples](#worked-examples)
- **Endpoint reference**
- [Health & system info](#health--system-info)
- [System settings](#system-settings)
- [User preferences](#user-preferences)
- [Backup, restore & server control](#backup-restore--server-control)
- [Updates](#updates)
- [Snapshot](#snapshot)
- [Devices](#devices)
- [Capture templates, engines & filters](#capture-templates-engines--filters)
- [Picture sources](#picture-sources)
- [Post-processing templates](#post-processing-templates)
- [Output targets](#output-targets)
- [Output target control & live preview](#output-target-control--live-preview)
- [Color strip sources](#color-strip-sources)
- [Color strip processing templates](#color-strip-processing-templates)
- [Pattern templates](#pattern-templates)
- [Gradients](#gradients)
- [Audio devices](#audio-devices)
- [Audio sources](#audio-sources)
- [Audio templates & engines](#audio-templates--engines)
- [Audio processing templates](#audio-processing-templates)
- [Audio filters](#audio-filters)
- [Value sources](#value-sources)
- [Weather sources](#weather-sources)
- [Automations](#automations)
- [Scene presets](#scene-presets)
- [Scene playlists](#scene-playlists)
- [Sync clocks](#sync-clocks)
- [Webhooks](#webhooks)
- [HTTP endpoints](#http-endpoints)
- [Game integration](#game-integration)
- [Home Assistant](#home-assistant)
- [MQTT sources](#mqtt-sources)
- [Assets](#assets)
- [Graph wiring](#graph-wiring)
- [Web UI & PWA](#web-ui--pwa)
---
## Authentication
LedGrab uses API-key authentication. The behavior depends on whether any keys are configured under `auth.api_keys` (see [INSTALLATION.md](../INSTALLATION.md)):
| Situation | Loopback (`127.0.0.1` / `::1` / `localhost`) | LAN / remote |
| --------- | -------------------------------------------- | ------------ |
| **No keys configured** (default) | Allowed anonymously | **Rejected with `401`** |
| **Keys configured** | Valid Bearer token required | Valid Bearer token required |
Pass the key as a Bearer token:
```http
Authorization: Bearer <your-api-key>
```
A few **sensitive endpoints require a real API key even from localhost** (they reject the loopback-anonymous identity): the backup download/restore endpoints, and any endpoint that reveals stored secrets (e.g. `GET /api/v1/home-assistant/sources?include_secrets=true`). Configure a key to use those.
WebSocket endpoints authenticate with a [first-message handshake](#websocket-protocol) rather than the `Authorization` header.
---
## Conventions
- **Content type:** request and response bodies are JSON (`application/json`) unless noted (file uploads use `multipart/form-data`; some endpoints stream binary or file responses).
- **Errors:** failures return the standard FastAPI shape with an HTTP status code and a body of `{"detail": "<message>"}`. Validation errors return `422` with a structured `detail` array.
- **IDs:** entities are addressed by string IDs (e.g. `dev_…`, `ot_…`, `css_…`) generated on creation.
- **Common create/update fields:** most configurable entities accept `name`, `description`, `tags` (string array), and UI styling fields `icon` and `icon_color`.
- **Referential integrity:** deleting an entity that is still referenced (e.g. a device used by an output target) returns `409 Conflict`.
- **Timestamps:** ISO-8601 UTC strings.
---
## WebSocket protocol
All WebSocket endpoints share the same auth handshake:
1. The client connects. The server accepts the socket.
2. The client sends a JSON auth message as the **first** message, within ~3 seconds: `{"type": "auth", "token": "<your-api-key>"}`. On loopback with no keys configured, `token` may be `null` or the message omitted.
3. The server replies `{"type": "auth_ok"}` on success, or `{"type": "auth_error", "reason": "..."}` then closes (close code `4401`) on failure. A cross-site `Origin` is rejected with close code `4403`.
Browser clients must connect from an allowed `cors_origins` origin. After `auth_ok`, the stream payload depends on the endpoint (JSON event objects, JSON spectrum/metric frames, or binary RGB frames — see each endpoint's description).
The WebSocket endpoints are listed within their resource sections below (method `WS`).
---
## Worked examples
> Example values are illustrative.
**Health check**`GET /health` (no auth on loopback):
```json
{
"status": "healthy",
"timestamp": "2026-05-29T12:00:00Z",
"version": "0.8.1",
"demo_mode": false,
"auth_required": false,
"setup_required": false,
"uptime_seconds": 3600
}
```
**Create a WLED device**`POST /api/v1/devices`:
```json
{
"name": "Living Room TV",
"url": "http://192.168.1.100",
"device_type": "wled",
"led_count": 150
}
```
Response `201 Created` returns the stored device, including its generated `id`. (For Adalight, send `device_type: "adalight"`, the serial `url` like `COM3` or `/dev/ttyUSB0`, `led_count`, and `baud_rate`. Each device type accepts its own fields — see `/docs`.)
**Start / stop a target**`POST /api/v1/output-targets/{target_id}/start`:
```json
{ "status": "started", "target_id": "ot_abc123" }
```
**Authenticated request with a configured key:**
```bash
curl -H "Authorization: Bearer your-api-key" \
http://localhost:8080/api/v1/devices
```
---
## Endpoint reference
## Health & system info
Health checks, version information, displays, system metrics, and integration status.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/health` | Service health: status, version, uptime, and whether auth/setup is required. |
| GET | `/api/v1/version` | Application version, Python version, and API version. |
| GET | `/api/v1/tags` | All tags used across every entity in the system. |
| GET | `/api/v1/config/displays` | Available displays/monitors for screen capture (optional `engine_type` query, e.g. `scrcpy`). |
| GET | `/api/v1/system/processes` | Running process names, for use in automation conditions. |
| GET | `/api/v1/system/performance` | Current CPU, RAM, and GPU utilization metrics. |
| GET | `/api/v1/system/metrics-history` | Last ~2 minutes of system and per-target metrics for dashboard charts. |
| GET | `/api/v1/system/api-keys` | API-key labels with masked values (read-only; keys live in YAML config). |
| GET | `/api/v1/system/integrations-status` | Connection status for MQTT and Home Assistant integrations. |
## System settings
Server configuration: MQTT broker, external URL, shutdown action, log level, ADB connection, and live log streaming.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/system/mqtt/settings` | Current MQTT broker settings (password masked). |
| PUT | `/api/v1/system/mqtt/settings` | Update MQTT broker settings (empty password preserves existing). |
| GET | `/api/v1/system/external-url` | Configured external base URL. |
| PUT | `/api/v1/system/external-url` | Set the external base URL for webhooks and user-visible links. |
| GET | `/api/v1/system/shutdown-action` | Configured server shutdown action (`stop_targets` or `nothing`). |
| PUT | `/api/v1/system/shutdown-action` | Set what happens to targets when the server shuts down. |
| WS | `/api/v1/system/logs/ws` | Live server log stream with a buffered backlog. |
| POST | `/api/v1/adb/connect` | Connect to a Wi-Fi ADB device by IP (auto-appends `:5555`). |
| POST | `/api/v1/adb/disconnect` | Disconnect a Wi-Fi ADB device. |
| GET | `/api/v1/system/log-level` | Current root logger level. |
| PUT | `/api/v1/system/log-level` | Change the log level at runtime without restart. |
## User preferences
Dashboard layout, notification settings, card display modes, and the global daylight timezone.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/preferences/dashboard-layout` | Read the saved dashboard layout (empty when unset). |
| PUT | `/api/v1/preferences/dashboard-layout` | Save the dashboard layout (opaque versioned JSON blob). |
| DELETE | `/api/v1/preferences/dashboard-layout` | Delete the saved layout; revert to default. |
| GET | `/api/v1/preferences/notifications` | Read notification preferences (server defaults when unset). |
| PUT | `/api/v1/preferences/notifications` | Persist notification preferences (channels, discovery, grace/debounce). |
| GET | `/api/v1/preferences/card-modes` | Read per-surface card-mode preferences. |
| PUT | `/api/v1/preferences/card-modes` | Save per-surface card modes (comfortable/compact/dense/row). |
| DELETE | `/api/v1/preferences/card-modes` | Delete card-mode preferences; revert to defaults. |
| GET | `/api/v1/preferences/daylight-timezone` | Read the global IANA timezone for daylight cycles. |
| PUT | `/api/v1/preferences/daylight-timezone` | Persist the daylight-cycle timezone (empty = server local). |
## Backup, restore & server control
Database backup/restore, server restart/shutdown, and auto-backup management.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/system/backup` | Download a full backup `.zip` (database + assets). 🔒 requires a key. |
| POST | `/api/v1/system/restore` | Upload a `.db`/`.zip` backup to restore config and trigger a restart. 🔒 requires a key. |
| POST | `/api/v1/system/restart` | Schedule a server restart and return immediately. |
| POST | `/api/v1/system/shutdown` | Gracefully shut down the server. |
| GET | `/api/v1/system/auto-backup/settings` | Auto-backup settings and status (enabled, interval, retention, last/next). |
| PUT | `/api/v1/system/auto-backup/settings` | Update auto-backup settings. |
| POST | `/api/v1/system/auto-backup/trigger` | Trigger a backup now and return its metadata. |
| GET | `/api/v1/system/backups` | List saved auto-backup files. |
| GET | `/api/v1/system/backups/{filename}` | Download a specific saved backup file. |
| DELETE | `/api/v1/system/backups/{filename}` | Delete a specific saved backup file. |
> 🔒 = requires a real API key even from localhost (rejects loopback-anonymous access).
## Updates
Auto-update management: check, apply, dismiss, and configure.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/system/update/status` | Current update status (available version, install type, capability). |
| POST | `/api/v1/system/update/check` | Trigger an immediate update check. |
| POST | `/api/v1/system/update/dismiss` | Dismiss the notification for a specific version. |
| POST | `/api/v1/system/update/apply` | Download and apply the available update, then shut down. |
| GET | `/api/v1/system/update/settings` | Update settings (enabled, interval, include prereleases). |
| PUT | `/api/v1/system/update/settings` | Change auto-update settings. |
## Snapshot
A single aggregated poll endpoint for low-overhead clients.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/snapshot` | Full poll payload (targets, states, metrics, devices, brightness, color/value sources, scene presets, scene playlists + cycling state, sync clocks, system) in one response. Use `?include=` to request a subset; per-section fault isolation. |
## Devices
LED device CRUD, pairing, discovery, health checks, brightness/power control, and the WS pixel stream.
| Method | Path | Description |
| ------ | ---- | ----------- |
| POST | `/api/v1/devices` | Create/attach a new LED device (validates connectivity). |
| POST | `/api/v1/devices/pair` | Run a pairing handshake before creating a device. |
| GET | `/api/v1/devices` | List all attached devices. |
| GET | `/api/v1/devices/discover` | Scan the network for devices (optional `timeout`, `device_type`). |
| GET | `/api/v1/devices/openrgb-zones` | List zones on an OpenRGB device (`url` query). |
| GET | `/api/v1/devices/batch/states` | Health/connection state for all devices at once. |
| GET | `/api/v1/devices/{device_id}` | Get a device by ID. |
| PUT | `/api/v1/devices/{device_id}` | Update device configuration. |
| DELETE | `/api/v1/devices/{device_id}` | Delete/detach a device (`409` if referenced). |
| GET | `/api/v1/devices/{device_id}/state` | Get device health/connection state. |
| POST | `/api/v1/devices/{device_id}/ping` | Force an immediate health check. |
| GET | `/api/v1/devices/{device_id}/brightness` | Get current (cached) brightness. |
| PUT | `/api/v1/devices/{device_id}/brightness` | Set brightness (`0255`). |
| GET | `/api/v1/devices/{device_id}/power` | Get current power state. |
| PUT | `/api/v1/devices/{device_id}/power` | Turn the device on or off. |
| WS | `/api/v1/devices/{device_id}/ws` | Pixel stream for `ws` device type (`[brightness][R G B …]`). |
## Capture templates, engines & filters
Capture template CRUD/testing, capture engine discovery, and post-processing filter discovery.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/capture-templates` | List all capture templates. |
| POST | `/api/v1/capture-templates` | Create a capture template. |
| GET | `/api/v1/capture-templates/{template_id}` | Get a capture template by ID. |
| PUT | `/api/v1/capture-templates/{template_id}` | Update a capture template (partial). |
| DELETE | `/api/v1/capture-templates/{template_id}` | Delete a template (`409` if used by streams). |
| GET | `/api/v1/capture-engines` | List capture engines with platform availability. |
| POST | `/api/v1/capture-templates/test` | Test a capture config; returns FPS metrics + preview. |
| WS | `/api/v1/capture-templates/test/ws` | Real-time capture test with intermediate frame previews. |
| GET | `/api/v1/filters` | List post-processing filter types and option schemas. |
| GET | `/api/v1/strip-filters` | List filter types that support 1D LED-strip processing. |
## Picture sources
Screen captures, static images, video files, and processed streams used for color extraction.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/picture-sources` | List all picture sources. |
| POST | `/api/v1/picture-sources/validate-image` | Validate an image source and return a preview thumbnail. |
| GET | `/api/v1/picture-sources/full-image` | Serve a full-resolution image for lightbox preview (`source` query). |
| POST | `/api/v1/picture-sources` | Create a picture source (`raw`/`processed`/`static`/`video`). |
| GET | `/api/v1/picture-sources/{stream_id}` | Get a picture source by ID. |
| PUT | `/api/v1/picture-sources/{stream_id}` | Update a picture source. |
| DELETE | `/api/v1/picture-sources/{stream_id}` | Delete a picture source (`409` if referenced). |
| GET | `/api/v1/picture-sources/{stream_id}/thumbnail` | Thumbnail (first frame) for a video source. |
| POST | `/api/v1/picture-sources/{stream_id}/test` | Resolve the chain and run a capture test. |
| WS | `/api/v1/picture-sources/{stream_id}/test/ws` | Test stream with intermediate frame previews. |
## Post-processing templates
Reusable filter chains applied to picture sources.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/postprocessing-templates` | List all post-processing templates. |
| POST | `/api/v1/postprocessing-templates` | Create a template (name + filter list). |
| GET | `/api/v1/postprocessing-templates/{template_id}` | Get a template by ID. |
| PUT | `/api/v1/postprocessing-templates/{template_id}` | Update a template (partial). |
| DELETE | `/api/v1/postprocessing-templates/{template_id}` | Delete a template (`409` if referenced). |
| POST | `/api/v1/postprocessing-templates/{template_id}/test` | Capture from a source and apply the filters. |
| WS | `/api/v1/postprocessing-templates/{template_id}/test/ws` | Real-time test with intermediate frame previews. |
## Output targets
LED strips, Home Assistant light groups, and Zigbee2MQTT bulb groups.
| Method | Path | Description |
| ------ | ---- | ----------- |
| POST | `/api/v1/output-targets` | Create a target (`led` / `ha_light` / `z2m_light`). |
| GET | `/api/v1/output-targets` | List all output targets. |
| GET | `/api/v1/output-targets/batch/states` | Processing state for all targets at once. |
| GET | `/api/v1/output-targets/batch/metrics` | Metrics for all targets at once. |
| GET | `/api/v1/output-targets/{target_id}` | Get a single target. |
| PUT | `/api/v1/output-targets/{target_id}` | Update a target (partial, per type). |
| DELETE | `/api/v1/output-targets/{target_id}` | Delete a target (stops processing first). |
## Output target control & live preview
Start/stop processing, state & metrics, the calibration overlay, the global event stream, and live color/LED preview WebSockets.
| Method | Path | Description |
| ------ | ---- | ----------- |
| POST | `/api/v1/output-targets/bulk/start` | Start processing for multiple targets. |
| POST | `/api/v1/output-targets/bulk/stop` | Stop processing for multiple targets. |
| POST | `/api/v1/output-targets/{target_id}/start` | Start processing for one target. |
| POST | `/api/v1/output-targets/{target_id}/stop` | Stop processing for one target. |
| GET | `/api/v1/output-targets/{target_id}/state` | Current processing state (FPS, timing, device, errors). |
| GET | `/api/v1/output-targets/{target_id}/metrics` | Processing metrics (uptime, frames, error count). |
| WS | `/api/v1/events/ws` | Real-time state-change events across all targets. |
| POST | `/api/v1/output-targets/{target_id}/overlay/start` | Start the on-screen sampling/LED overlay. |
| POST | `/api/v1/output-targets/{target_id}/overlay/stop` | Stop the overlay. |
| GET | `/api/v1/output-targets/{target_id}/overlay/status` | Whether the overlay is active. |
| POST | `/api/v1/output-targets/{target_id}/ha-light/turn-off` | Turn off all HA light entities for the target. |
| WS | `/api/v1/output-targets/{target_id}/ha-light/ws` | Live HA light color preview. |
| POST | `/api/v1/output-targets/{target_id}/z2m-light/turn-off` | Publish OFF to all Zigbee2MQTT bulbs for the target. |
| WS | `/api/v1/output-targets/{target_id}/z2m-light/ws` | Live Zigbee2MQTT bulb color preview. |
| WS | `/api/v1/output-targets/{target_id}/led-preview/ws` | Live LED-strip preview (binary RGB frames). |
## Color strip sources
CRUD, calibration, raw color push, notifications, and preview streaming for color strip sources.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/color-strip-sources` | List all color strip sources. |
| POST | `/api/v1/color-strip-sources` | Create a color strip source (by `source_type`). |
| GET | `/api/v1/color-strip-sources/{source_id}` | Get a color strip source by ID. |
| PUT | `/api/v1/color-strip-sources/{source_id}` | Update a source; hot-reloads running streams. |
| DELETE | `/api/v1/color-strip-sources/{source_id}` | Delete a source (`409` if referenced). |
| POST | `/api/v1/color-strip-sources/{source_id}/overlay/start` | Start the screen overlay (picture-type, calibrated). |
| POST | `/api/v1/color-strip-sources/{source_id}/overlay/stop` | Stop the screen overlay. |
| GET | `/api/v1/color-strip-sources/{source_id}/overlay/status` | Whether the overlay is active. |
| POST | `/api/v1/color-strip-sources/{source_id}/colors` | Push raw LED colors to an `api_input` source. |
| POST | `/api/v1/color-strip-sources/{source_id}/notify` | Trigger a one-shot notification effect. |
| GET | `/api/v1/color-strip-sources/os-notifications/history` | Recent OS-notification capture history. |
| PUT | `/api/v1/color-strip-sources/{source_id}/calibration/test` | Light up LED edges to verify calibration. |
| POST | `/api/v1/color-strip-sources/{source_id}/key-colors/test` | Test a `key_colors` source (extract colors from rectangles). |
| WS | `/api/v1/color-strip-sources/{source_id}/key-colors/test/ws` | Real-time key-colors test preview. |
| WS | `/api/v1/color-strip-sources/preview/ws` | Transient ad-hoc source preview stream. |
| WS | `/api/v1/color-strip-sources/{source_id}/ws` | Push raw colors to an `api_input` source over WS. |
| WS | `/api/v1/color-strip-sources/{source_id}/test/ws` | Real-time source preview (binary RGB, optional JPEG). |
## Color strip processing templates
Reusable filter chains applied to color strips (1D LED data).
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/color-strip-processing-templates` | List all color-strip processing templates. |
| POST | `/api/v1/color-strip-processing-templates` | Create a template (name + filter list). |
| GET | `/api/v1/color-strip-processing-templates/{template_id}` | Get a template by ID. |
| PUT | `/api/v1/color-strip-processing-templates/{template_id}` | Update a template. |
| DELETE | `/api/v1/color-strip-processing-templates/{template_id}` | Delete a template (`409` if referenced). |
| WS | `/api/v1/color-strip-processing-templates/{template_id}/test/ws` | Real-time preview: apply the filter chain to an input source. |
## Pattern templates
Layout templates of named rectangles for LED device configuration.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/pattern-templates` | List all pattern templates. |
| POST | `/api/v1/pattern-templates` | Create a pattern template (named rectangles). |
| GET | `/api/v1/pattern-templates/{template_id}` | Get a pattern template by ID. |
| PUT | `/api/v1/pattern-templates/{template_id}` | Update a pattern template. |
| DELETE | `/api/v1/pattern-templates/{template_id}` | Delete a template (`409` if referenced by targets). |
## Gradients
Reusable gradient definitions (color stops). Built-in gradients are read-only but clonable.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/gradients` | List all gradients (built-in and user-created). |
| POST | `/api/v1/gradients` | Create a user-defined gradient. |
| GET | `/api/v1/gradients/{gradient_id}` | Get a gradient by ID. |
| PUT | `/api/v1/gradients/{gradient_id}` | Update a gradient (built-ins are read-only). |
| POST | `/api/v1/gradients/{gradient_id}/clone` | Clone a gradient into a customizable copy. |
| DELETE | `/api/v1/gradients/{gradient_id}` | Delete a gradient (`400` if built-in or referenced). |
## Audio devices
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/audio-devices` | List audio input/output devices (flat list + per-engine grouping). |
## Audio sources
Audio capture and processing sources for audio-reactive effects.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/audio-sources` | List all audio sources (optional `source_type`). |
| POST | `/api/v1/audio-sources` | Create an audio source (`capture` or `processed`). |
| GET | `/api/v1/audio-sources/{source_id}` | Get an audio source by ID. |
| PUT | `/api/v1/audio-sources/{source_id}` | Update an audio source (partial). |
| DELETE | `/api/v1/audio-sources/{source_id}` | Delete an audio source (`409` if referenced). |
| WS | `/api/v1/audio-sources/{source_id}/test/ws` | Real-time spectrum/RMS/peak/beat analysis (~20 Hz). |
## Audio templates & engines
Audio capture templates and engine discovery.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/audio-templates` | List all audio capture templates. |
| POST | `/api/v1/audio-templates` | Create an audio capture template. |
| GET | `/api/v1/audio-templates/{template_id}` | Get an audio template by ID. |
| PUT | `/api/v1/audio-templates/{template_id}` | Update an audio template. |
| DELETE | `/api/v1/audio-templates/{template_id}` | Delete a template (cascades to audio sources). |
| GET | `/api/v1/audio-engines` | List audio capture engines and availability. |
| WS | `/api/v1/audio-templates/{template_id}/test/ws` | Real-time spectrum test for a template + device. |
## Audio processing templates
Reusable audio filter chains.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/audio-processing-templates` | List all audio processing templates. |
| POST | `/api/v1/audio-processing-templates` | Create a template (name + filter list). |
| GET | `/api/v1/audio-processing-templates/{template_id}` | Get a template by ID. |
| PUT | `/api/v1/audio-processing-templates/{template_id}` | Update a template (hot-updates running streams). |
| DELETE | `/api/v1/audio-processing-templates/{template_id}` | Delete a template (`409` if referenced). |
## Audio filters
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/audio-filters` | List audio filter types and their option schemas. |
## Value sources
Dynamic data inputs (brightness and other parameters): static, animated, audio, adaptive, color, sensor, HTTP, Home Assistant, and `template` — a sandboxed-Jinja **combinator** that evaluates an expression over the live values of other value sources.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/value-sources` | List all value sources (optional `source_type`). |
| POST | `/api/v1/value-sources` | Create a value source (discriminated by `source_type`). |
| POST | `/api/v1/value-sources/validate-template` | Validate a template expression + inputs (advisory; always `200` with `{valid, error, errors, warnings, variables}`). |
| GET | `/api/v1/value-sources/{source_id}` | Get a value source by ID. |
| PUT | `/api/v1/value-sources/{source_id}` | Update a value source; hot-reloads running streams. |
| DELETE | `/api/v1/value-sources/{source_id}` | Delete a value source (`400` if referenced by a target or another value source). |
| WS | `/api/v1/value-sources/{source_id}/test/ws` | Real-time value output stream (~20 Hz). |
### Template value source (`source_type: "template"`)
A `float` combinator. Fields: `template` (a Jinja *expression*), `inputs` (`[{name, value_source_id}]` bindings to other value sources), `default_value` (fallback in `[0,1]` on any error), and `eval_interval` (optional re-eval throttle in seconds; `0`/null = every poll). At runtime each input is exposed by its `name` (the source's normalized `0..1` value) plus `raw[name]` (its un-normalized value, where available). Globals: `min`, `max`, `abs`, `round`, `clamp(x, lo=0, hi=1)`. The expression runs in a hardened `ImmutableSandboxedEnvironment` (no statements/blocks, filters, attribute access, `**`, or string repetition); results are coerced, NaN/inf-rejected, and clamped to `[0,1]`. Reference cycles and over-deep nesting are rejected at save time. For time-of-day logic, bind an `adaptive_time` or `daylight` source as an input.
## Weather sources
Weather data providers feeding weather-driven value sources.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/weather-sources` | List all weather sources. |
| POST | `/api/v1/weather-sources` | Create a weather source (provider, lat/lon, interval). |
| GET | `/api/v1/weather-sources/{source_id}` | Get a weather source by ID. |
| PUT | `/api/v1/weather-sources/{source_id}` | Update a weather source. |
| DELETE | `/api/v1/weather-sources/{source_id}` | Delete a weather source. |
| POST | `/api/v1/weather-sources/{source_id}/test` | Force-fetch current weather and return it. |
## Automations
Rules that trigger scene presets (time, display state, MQTT, webhooks, Home Assistant, HTTP polling, active window).
| Method | Path | Description |
| ------ | ---- | ----------- |
| POST | `/api/v1/automations` | Create an automation (rules + scene preset + deactivation). |
| GET | `/api/v1/automations` | List automations with current activity state. |
| GET | `/api/v1/automations/{automation_id}` | Get an automation by ID (includes webhook URL if any). |
| PUT | `/api/v1/automations/{automation_id}` | Update an automation (partial); re-evaluates if enabled. |
| DELETE | `/api/v1/automations/{automation_id}` | Delete and deactivate an automation. |
| POST | `/api/v1/automations/{automation_id}/enable` | Enable and immediately evaluate rules. |
| POST | `/api/v1/automations/{automation_id}/disable` | Disable and deactivate. |
## Scene presets
Captured snapshots of target state that can be restored.
| Method | Path | Description |
| ------ | ---- | ----------- |
| POST | `/api/v1/scene-presets` | Create a preset by capturing current target state. |
| GET | `/api/v1/scene-presets` | List all scene presets. |
| GET | `/api/v1/scene-presets/{preset_id}` | Get a scene preset by ID. |
| PUT | `/api/v1/scene-presets/{preset_id}` | Update metadata and optionally change targets. |
| DELETE | `/api/v1/scene-presets/{preset_id}` | Delete a scene preset. |
| POST | `/api/v1/scene-presets/{preset_id}/recapture` | Re-capture current state into the preset. |
| POST | `/api/v1/scene-presets/{preset_id}/activate` | Activate the preset (restore captured state). |
## Scene playlists
Ordered, timed sequences of scene presets that auto-cycle. The engine drives
**one** playlist at a time — starting a playlist stops any other. Each item
references a scene preset and holds it for its `duration_seconds` (min 1s)
before advancing; `loop` repeats from the start and `shuffle` randomises the
order each cycle.
| Method | Path | Description |
| ------ | ---- | ----------- |
| POST | `/api/v1/scene-playlists` | Create a playlist (items reference scene presets). |
| GET | `/api/v1/scene-playlists` | List all playlists plus the current cycling `state`. |
| GET | `/api/v1/scene-playlists/state` | Get the current cycling state (idle if nothing runs). |
| GET | `/api/v1/scene-playlists/{playlist_id}` | Get a playlist by ID. |
| PUT | `/api/v1/scene-playlists/{playlist_id}` | Update metadata, items, and `loop`/`shuffle`. |
| DELETE | `/api/v1/scene-playlists/{playlist_id}` | Delete a playlist (stops it first if running). |
| POST | `/api/v1/scene-playlists/{playlist_id}/start` | Start cycling (stops any other playlist first). |
| POST | `/api/v1/scene-playlists/stop` | Stop the active playlist (leaves the last scene applied). |
## Sync clocks
Shared clocks that drive linked animations with configurable speed.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/sync-clocks` | List all synchronization clocks. |
| POST | `/api/v1/sync-clocks` | Create a sync clock. |
| GET | `/api/v1/sync-clocks/{clock_id}` | Get a sync clock by ID. |
| PUT | `/api/v1/sync-clocks/{clock_id}` | Update a clock (speed changes hot-applied). |
| DELETE | `/api/v1/sync-clocks/{clock_id}` | Delete a clock (`409` if referenced). |
| POST | `/api/v1/sync-clocks/{clock_id}/pause` | Pause the clock (freeze linked animations). |
| POST | `/api/v1/sync-clocks/{clock_id}/resume` | Resume a paused clock. |
| POST | `/api/v1/sync-clocks/{clock_id}/reset` | Reset the clock to `t=0`. |
## Webhooks
Inbound trigger endpoint for external services.
| Method | Path | Description |
| ------ | ---- | ----------- |
| POST | `/api/v1/webhooks/{token}` | Trigger an automation by secret token (`activate`/`deactivate`; rate-limited 30/min/IP). |
## HTTP endpoints
Outbound HTTP polling endpoints for integrations. 🔒 These require a real API key even on loopback.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/http/endpoints` | List all HTTP polling endpoints. |
| POST | `/api/v1/http/endpoints` | Create an endpoint (URL, method, auth token, headers). |
| GET | `/api/v1/http/endpoints/{endpoint_id}` | Get an endpoint by ID. |
| PUT | `/api/v1/http/endpoints/{endpoint_id}` | Update an endpoint. |
| DELETE | `/api/v1/http/endpoints/{endpoint_id}` | Delete an endpoint. |
| POST | `/api/v1/http/endpoints/test` | One-shot test fetch to validate a config before saving. |
| POST | `/api/v1/http/endpoints/{endpoint_id}/test` | Test a stored endpoint without re-entering its token. |
## Game integration
Game event ingestion, adapter metadata, presets, and diagnostics.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/game-integrations/presets` | List built-in effect presets. |
| GET | `/api/v1/game-integrations` | List all game integration configs. |
| POST | `/api/v1/game-integrations` | Create a game integration config. |
| GET | `/api/v1/game-integrations/{integration_id}` | Get a config by ID. |
| PUT | `/api/v1/game-integrations/{integration_id}` | Update a config. |
| DELETE | `/api/v1/game-integrations/{integration_id}` | Delete a config. |
| POST | `/api/v1/game-integrations/{integration_id}/event` | Ingest a game event (adapter-level auth; 1664 Hz). |
| GET | `/api/v1/game-integrations/{integration_id}/status` | Runtime status (connected state, event counts). |
| GET | `/api/v1/game-integrations/{integration_id}/events` | Recent events for debugging (`limit`). |
| GET | `/api/v1/game-adapters` | List adapter types and supported events. |
| POST | `/api/v1/game-integrations/{integration_id}/apply-preset` | Apply a built-in preset (optionally replacing mappings). |
| POST | `/api/v1/game-integrations/{integration_id}/auto-setup` | Write game config files and generate an auth token. |
## Home Assistant
Home Assistant WebSocket sources, entity discovery, and live status.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/home-assistant/sources` | List HA sources with status and entity counts (`?include_secrets=true` 🔒). |
| POST | `/api/v1/home-assistant/sources` | Create an HA source (host, long-lived token, filters). |
| GET | `/api/v1/home-assistant/sources/{source_id}` | Get an HA source (`?include_secrets=true` 🔒). |
| PUT | `/api/v1/home-assistant/sources/{source_id}` | Update an HA source; refreshes the connection. |
| DELETE | `/api/v1/home-assistant/sources/{source_id}` | Delete an HA source and release its runtime. |
| GET | `/api/v1/home-assistant/sources/{source_id}/entities` | List available HA entities (live + cache fallback). |
| POST | `/api/v1/home-assistant/sources/{source_id}/test` | Test connection/auth and report HA version. |
| GET | `/api/v1/home-assistant/status` | Overall HA integration status per source. |
## MQTT sources
MQTT broker connections (sources) and status monitoring.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/mqtt/sources` | List MQTT sources with connection status. |
| POST | `/api/v1/mqtt/sources` | Create an MQTT source (broker connection). |
| GET | `/api/v1/mqtt/sources/{source_id}` | Get an MQTT source by ID. |
| PUT | `/api/v1/mqtt/sources/{source_id}` | Update a source; restarts the broker runtime. |
| DELETE | `/api/v1/mqtt/sources/{source_id}` | Delete a source and release its runtime. |
| POST | `/api/v1/mqtt/sources/{source_id}/test` | Test connection to the broker (10s timeout). |
| GET | `/api/v1/mqtt/status` | Overall MQTT integration status per source. |
## Assets
Media files (sounds, images, videos) used by effects and notifications.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/assets` | List assets (optional `asset_type` filter). |
| GET | `/api/v1/assets/{asset_id}` | Get asset metadata by ID. |
| POST | `/api/v1/assets` | Upload a new asset file (`multipart/form-data`). |
| PUT | `/api/v1/assets/{asset_id}` | Update asset metadata. |
| DELETE | `/api/v1/assets/{asset_id}` | Delete an asset (prebuilt assets are soft-deleted/restorable). |
| GET | `/api/v1/assets/{asset_id}/file` | Serve the asset file (download). |
| POST | `/api/v1/assets/restore-prebuilt` | Re-import any deleted prebuilt assets. |
## Graph wiring
The wiring-graph: schema registry, topology, dependents, validation, and subgraph duplication.
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/api/v1/graph/schema` | Registry of connectable reference fields. |
| GET | `/api/v1/graph` | Full wiring topology (nodes + edges) and validation report. |
| GET | `/api/v1/graph/dependents/{kind}/{entity_id}` | Every entity that references `(kind, entity_id)`. |
| POST | `/api/v1/graph/validate-connection` | Validate a proposed wiring edit (existence, kind, no cycle). |
| POST | `/api/v1/graph/duplicate` | Deep-clone selected value/color-strip sources with remapped wiring. |
## Calibration
Guided LED chase and auto-solver for the `CalibrationConfig` stored on a
color-strip source. The flow is:
1. **Start** a session (`POST /session`) — stops any running target on the
device and remembers it for restore on stop.
2. **Position** the chase pixel (`POST /session/position`) to walk through
each physical corner and record the LED index.
3. **Solve** (`POST /solve`) — the server computes per-edge LED counts.
4. **Persist** — call `PUT /api/v1/color-strip-sources/{id}` with the solved
`calibration` object to save and hot-reload.
5. **Stop** (`POST /session/stop`) — clears the device and restores the prior
target.
| Method | Path | Description |
| ------ | ---- | ----------- |
| POST | `/api/v1/calibration/session` | Start a calibration session on a device (stops the running target, clears to black). |
| POST | `/api/v1/calibration/session/position` | Advance the chase pixel to LED `index``window` dim neighbours). |
| POST | `/api/v1/calibration/session/stop` | End the session: clear to black and restore the prior target. |
| POST | `/api/v1/calibration/session/cancel` | Alias for stop — no calibration is applied. |
| GET | `/api/v1/calibration/session/state` | Current session state (active, device_id, led_count, last_activity). |
| POST | `/api/v1/calibration/solve` | Solve per-edge LED counts from 4 corner tap indices. Returns solved config dict (does NOT persist). |
**Session state** response shape:
```json
{
"active": true,
"device_id": "dev_abc123",
"led_count": 100,
"prior_target_id": "ot_xyz456",
"last_activity": "2026-06-08T12:34:56.789Z"
}
```
**Solve request** (body):
```json
{
"device_id": "dev_abc123",
"start_position": "bottom_left",
"layout": "clockwise",
"corner_indices": [0, 30, 60, 80],
"offset": 0
}
```
`corner_indices` must be exactly 4 integers, one per screen corner, in the
strip-walk order defined by `(start_position, layout)`. Provide either
`device_id` (preferred — server derives `led_count`) or `led_count` directly.
**Important session behavior:**
- **Stops the running output target** — starting a calibration session immediately
stops any output target currently running on that device. Other clients driving
that device will lose their output for the duration of the session.
- **Single session only** — only one calibration session runs at a time across the
whole server. Starting a new session automatically ends the previous one (clearing
and restoring its device first), regardless of which device each session is on.
- **Idle auto-end** — a session that receives no `position` calls for ~60 seconds is
automatically stopped and the prior target restored, so devices are never left dark
indefinitely.
**Idle timeout:** a session that receives no `position` calls for 60 seconds
is automatically stopped and the prior target restored.
## Web UI & PWA
App-level routes served by FastAPI (not under `/api/v1`).
| Method | Path | Description |
| ------ | ---- | ----------- |
| GET | `/` | The web dashboard UI. |
| GET | `/manifest.json` | PWA manifest (root scope). |
| GET | `/sw.js` | Service worker (root scope). |
| GET | `/openapi.json` | OpenAPI schema. |
| GET | `/docs` | Swagger UI (interactive API docs). |
| GET | `/redoc` | ReDoc API reference. |
---
## Next steps
- [Installation Guide](../INSTALLATION.md)
- [Calibration Guide](CALIBRATION.md)
- Interactive, always-current schemas: [`/docs`](http://localhost:8080/docs)