# Host API ## Purpose The host API is the stable external boundary for: - the creative web UI - the existing engineering GUI - future external show-control adapters such as grandMA The core rule stays unchanged: - the API is a control and observation layer - the realtime engine remains the timing authority - no surface is allowed to become the LED clock ## Current Implementation Runtime pieces: - `crates/infinity_host/src/control.rs` - `crates/infinity_host/src/scene.rs` - `crates/infinity_host/src/simulation.rs` - `crates/infinity_host_api/src/dto.rs` - `crates/infinity_host_api/src/server.rs` The network-facing server is started with: ```powershell cargo run -p infinity_host_api -- --config config/project.example.toml --bind 127.0.0.1:9001 ``` Creative web UI V1 is served by the same process at: ```text http://127.0.0.1:9001/ ``` ## Versioning - HTTP and WebSocket routes are versioned under `/api/v1` - responses include `api_version: "v1"` - the external DTOs are intentionally not a direct 1:1 dump of internal core structs ## Endpoint Contract ### GET `/api/v1/snapshot` Returns the current state and preview in one response. Example: ```json { "api_version": "v1", "generated_at_millis": 241, "state": { "system": { "project_name": "Infinity Vis", "schema_version": 1, "topology_label": "6 nodes / 18 outputs / 106 LEDs" }, "global": { "blackout": false, "master_brightness": 0.2, "selected_pattern": "solid_color", "selected_group": null, "transition_duration_ms": 150 }, "engine": { "logic_hz": 120, "frame_hz": 60, "preview_hz": 15, "uptime_ms": 241, "frame_index": 14, "dropped_frames": 0, "active_transition": null }, "active_scene": { "preset_id": null, "pattern_id": "solid_color", "seed": 100, "palette": [ "#ffffff" ], "parameters": [], "target_group": null, "blackout": false } }, "preview": { "generated_at_millis": 241, "panels": [ { "node_id": "node-01", "panel_position": "top", "representative_color_hex": "#33CCFF", "sample_led_hex": [ "#33CCFF", "#28A3CC", "#1E7A99" ], "energy_percent": 28, "source": "scene" } ] } } ``` ### GET `/api/v1/catalog` Returns the creative catalog: - patterns - presets - groups ### GET `/api/v1/presets` Returns only preset summaries. Example: ```json { "api_version": "v1", "presets": [ { "preset_id": "ocean_gradient", "pattern_id": "gradient", "target_group": null, "transition_duration_ms": 320 } ] } ``` ### GET `/api/v1/groups` Returns only group summaries. Example: ```json { "api_version": "v1", "groups": [ { "group_id": "top_panels", "member_count": 6, "tags": [ "row", "top" ] } ] } ``` ### POST `/api/v1/command` Accepts a versioned command envelope. Example request: ```json { "request_id": "web-1713352662000", "command": { "type": "set_master_brightness", "payload": { "value": 0.42 } } } ``` Example response: ```json { "api_version": "v1", "accepted": true, "request_id": "web-1713352662000", "generated_at_millis": 522, "summary": "master brightness set to 42%" } ``` Errors use a stable error object: ```json { "api_version": "v1", "error": { "code": "invalid_command", "message": "command request was rejected: missing field `enabled`" } } ``` ### WS `/api/v1/stream` The WebSocket stream emits envelopes with a monotonic sequence and a typed payload. Stream message types: - `snapshot` - `preview` - `event` Example snapshot envelope: ```json { "api_version": "v1", "sequence": 17, "generated_at_millis": 875, "message": { "type": "snapshot", "payload": { "global": { "blackout": false, "master_brightness": 0.35, "selected_pattern": "gradient", "selected_group": "top_panels", "transition_duration_ms": 320 } } } } ``` Example preview envelope: ```json { "api_version": "v1", "sequence": 18, "generated_at_millis": 875, "message": { "type": "preview", "payload": { "generated_at_millis": 875, "panels": [ { "node_id": "node-01", "panel_position": "top", "representative_color_hex": "#FF8A5B", "sample_led_hex": [ "#FF8A5B", "#F36E43", "#D85A2F" ], "energy_percent": 47, "source": "transition" } ] } } } ``` Example event envelope: ```json { "api_version": "v1", "sequence": 19, "generated_at_millis": 880, "message": { "type": "event", "payload": { "kind": "info", "message": "preset recalled: ocean_gradient" } } } ``` ## Supported Commands The current API command set covers: - `set_blackout` - `set_master_brightness` - `select_pattern` - `recall_preset` - `select_group` - `set_scene_parameter` - `set_transition_duration_ms` - `trigger_panel_test` This is intentionally enough for: - creative look development in the web UI - engineering test triggers in the native GUI - future external show-control translation layers ## Web UI V1 The first creative web UI is intentionally limited to: - pattern selection - preset recall - group selection - global brightness - blackout - transition duration - scene parameter controls driven from the API schema - panel preview - snapshot display - event feed It does not absorb mapping, topology, or hardware-diagnostic workflows. Those stay in the native engineering UI. ## Contract Tests The API contract is currently verified in: - `crates/infinity_host_api/tests/contract.rs` Covered paths: - root web shell - `GET /api/v1/snapshot` - `GET /api/v1/catalog` - `GET /api/v1/presets` - `GET /api/v1/groups` - `POST /api/v1/command` - `WS /api/v1/stream` ## Future Direction Next adapters should be built on this boundary instead of reaching into the host core directly. That includes: - a richer web authoring surface - remote operator clients - a grandMA bridge that translates external show control into host API commands