HTTP and WebSocket
Route tables below are generated from crates/booth-api/src/{lib,lab,lab_learning,lab_packs,live_dj}.rs.
The Implemented sections list every route the daemon actually serves; the
Proposed section keeps the target contract that has no implementation yet.
See current status and the
software wire contract
for exact DTOs.
Every route is mounted under /api/v1 except GET /healthz, which is unauthenticated
and used by the Kubernetes probes. All other routes require Authorization: Bearer <token>
matching the daemon's configured booth token; a missing or wrong token returns 401 with
{"error": "Authentication required"}. CORS allows only the origins in BOOTH_UI_ORIGINS
(default http://localhost:3000,http://127.0.0.1:3000) and only GET/POST.
In deployment the browser never holds this token: aidj-ui keeps it server-side and
exposes scoped routes such as /api/live-clubs/{club}/autopilot. Ownership and role
checks (owner / DJ / listener) are enforced per request inside the handlers, not by the
router.
Booth state and commands
| Method / path | Purpose |
|---|---|
GET /healthz | Liveness/readiness probe. Unauthenticated, returns ok |
GET /api/v1/state | Metadata booth snapshot |
POST /api/v1/commands | Submit a CommandEnvelope |
GET /api/v1/ws | WebSocket upgrade for the metadata playground |
The four-deck metadata booth behind these routes is a developer harness. It does not control the audible offline renderer or the live club runtime.
Library
| Method / path | Purpose |
|---|---|
GET /api/v1/lab | Lab capability and configuration summary |
GET /api/v1/library | Workspace tracks |
GET /api/v1/library/catalog | Paged, filterable catalog view |
GET /api/v1/library/compatibility | Tempo/key compatibility view |
POST /api/v1/library/import | Upload and import an asset (150 MB body limit) |
POST /api/v1/library/demo | Create the procedural demo library |
GET /api/v1/library/{id} | Track detail |
GET /api/v1/library/{id}/audio | Track audio stream |
POST /api/v1/library/{id}/review | Submit reviewed BPM, first beat, phrase length and key |
POST /api/v1/library/{id}/analyze | Recompute native descriptors without changing reviewed values |
GET /api/v1/library/{id}/musical-analysis | Stored deep analysis report |
GET/POST /api/v1/library/{id}/annotations | Human reference labels for downbeats, phrases and vocals |
POST /api/v1/library/{id}/similar | Qdrant similarity with Mongo revalidation |
GET/POST /api/v1/library/jobs | List or enqueue processing jobs |
POST /api/v1/library/jobs/{id}/control | Pause, resume, cancel or retry a job |
GET /api/v1/library/sources | Configured folder sources |
GET /api/v1/library/sources/{id}/files | Files discovered under a source |
POST /api/v1/library/sources/{id}/control | Pause or resume a source scan |
GET/POST /api/v1/library/packs | List or create library packs |
GET/PUT /api/v1/library/packs/{id} | Read or update one pack |
Annotations are stored and served, but no planner or grid-review path reads them yet. Submitting a human phrase label does not currently make a grid verified.
Offline B2B sessions
| Method / path | Purpose |
|---|---|
GET/POST /api/v1/sessions | List sessions, or start a render job |
GET /api/v1/sessions/{id} | Progress, decisions and metrics |
POST /api/v1/sessions/{id}/control | Pause, resume or cancel |
POST /api/v1/sessions/{id}/replay | Re-render from recorded decisions |
GET /api/v1/sessions/{id}/artifacts/{name} | Fetch mix.wav, manifest.json, booth.jsonl and similar |
Cancelling a render preserves partial artifacts with an incomplete status. Replay verifies execution against the original output hash and does not insert new learning observations.
Transition memory
| Method / path | Purpose |
|---|---|
GET/POST /api/v1/transition-recipes | List seeded recipes, or save a new immutable id/version |
GET /api/v1/transitions | Ranked attempts with technical metrics and reviews |
POST /api/v1/transition-auditions | Render a controlled pair/recipe experiment |
POST /api/v1/transitions/{id}/reviews | Submit a listening review, including avoid |
GET/POST /api/v1/transitions/preferences | List, or record, one blind comparison: winner, loser, tie, reviewer, notes |
GET /api/v1/transitions/next-comparison | The uncompared pairs most worth listening to, fewest differing factors first. Only renders whose mix.wav is still on disk are offered; the response counts the renders left out (skipped_missing_audio) and earlier ratings on now-unplayable pairs (unheard_ratings) |
POST /api/v1/transitions/preferences/discard-unheard | Withdraw every comparison with a side whose audio is no longer on disk (rated without listening). Archived to preferences_voided with the reason, never deleted; returns discarded and remaining |
GET /api/v1/transitions/loop-status | Experiments by provenance, labels, comparisons needed, factor effects against noise, what blocks training |
Learning studio
| Method / path | Purpose |
|---|---|
GET/POST /api/v1/learning | Learning state, or update settings |
GET /api/v1/learning/jobs | Queued and completed practice experiments |
GET /api/v1/learning/catalog | External research catalog |
GET /api/v1/learning/techniques | Versioned technique concept catalog |
POST /api/v1/learning/links | Link a catalog entry to a local recording |
GET /api/v1/llm/usage | Model request counts and budget state |
Training itself is not served over HTTP. analyzerd dj-learn fits the pairwise model on
stored comparisons and saves it unapproved; analyzerd dj-learn approve LABEL deploys it
only if held-out accuracy beat the coin flip. Both rankers load the approved model at
planning time. analyzerd dj-priors refreshes the per-genre human-practice prior.
Live booth
| Method / path | Purpose |
|---|---|
GET/POST /api/v1/live-dj | Live session status, or a control action |
GET /api/v1/live-dj/recipes | Recipes the live executor can run |
POST /api/v1/live-dj accepts a tagged action: start, stop, mode, energy,
skip_next, refresh_advice, model_budget, recipe, mixing, takeover, execute,
manual, manual_loaded and roster (save the AI DJ roster; refused during a set). The status payload includes the current and next track,
position, phase, ranked alternatives, region evidence, the selected plan and mix_point
(the planned exit position and section, entry cue and section, technique and overlap).
Live sets
| Method / path | Purpose |
|---|---|
GET/POST /api/v1/live-sets | Recorded and edited sets; create a mix from a recording or from tracks |
GET/POST /api/v1/live-sets/{id} | A set with its offline schedule; edit actions (rename, reorder, settings, seam_options, seam_apply, seam_clear, seam_edit, step_cue, paste, auto_fill, delete) |
GET/POST /api/v1/live-sets/{id}/render | Render progress; start an offline render (no model) |
GET /api/v1/live-sets/{id}/render/mix.wav | The rendered mix |
GET /api/v1/live-sets/{id}/render/peaks | Waveform overview of the rendered mix (peaks per column) |
POST/GET /api/v1/live-sets/{id}/preview[/{session}[/mix.wav]] | Render and fetch a short clip of one seam |
See Set studio.
Runtime engine endpoints are server-owned and never accepted from a client:
BOOTH_LIVE_MIXER_URL, BOOTH_LIVE_PLAYER_URLS and BOOTH_LIVE_MEDIA_PREFIX.
Proposed, not implemented
These appeared in earlier revisions of this page as though they existed. They do not.
| Method / path | Intent | Status |
|---|---|---|
GET /api/v1/devices | Device identities, modes, freshness, capabilities | Hardware adapters are post-MVP |
GET /api/v1/tracks | Registered track metadata | Superseded by /api/v1/library |
GET /api/v1/config | Effective non-secret configuration | Not implemented |
POST /api/v1/simulator/start | Instantiate a scenario | No simulator lifecycle route exists |
POST /api/v1/simulator/stop | Stop simulation explicitly | No simulator lifecycle route exists |
POST /api/v1/sessions/{id}/stop | Finalize a recording | Use POST /api/v1/sessions/{id}/control |
There is also no route that returns a track's derived arrangement — its phrase-aligned mix-in and mix-out candidates. The planner computes them and the live status exposes the chosen one, but no client can list them for a track.
Recording lifecycle and simulation lifecycle are intended to stay distinct: stopping a recording must not stop playback.
Illustrative command exchange
{
"schema_version": 1,
"session_id": "demo",
"command_id": "cmd-001",
"ownership_generation": 1,
"payload": { "type": "Play", "deck_id": 1 }
}
The server derives actor identity from the authenticated connection. It first returns a receipt tied to command_id; an applied event later supplies the sequence, output frame, and resulting state revision. Rejected commands carry stable reason codes such as unsupported, not_owner, stale_revision, or invalid_value.
Use JSON initially. A stream starts with a versioned snapshot and cursor; subscription setup must avoid a race between snapshot capture and subsequent events. Bound outbound queues, coalesce meters, and force resynchronization rather than silently dropping authoritative events. Reject incompatible schema versions explicitly.
Bind to loopback by default. For LAN operation, define authentication, allowed browser origins, viewer/controller roles, and transport protection. Require authentication on control-plane HTTP routes as well as WebSocket upgrades. Avoid logging credentials or raw track filesystem paths.