# API documentation Last updated: 2026-05-12 The active app is `app.py`, a FastAPI application. ## Start server ```bash uvicorn app:app --host 0.0.0.0 --port 7860 ``` ## `GET /api/health` Returns backend health. ```json {"status":"ok"} ``` ## `GET /api/config` Returns supported models, stems, default pipeline params, stage definitions, and clustering mode labels. ```bash curl http://127.0.0.1:7860/api/config ``` Important response keys: | Key | Meaning | |---|---| | `separation_backends` | Supported separation engines: `spleeter`, `demucs`, and `none`. | | `spleeter_models` | Supported Spleeter model profiles. | | `spleeter_stems` | Valid stems per Spleeter model, plus `all`. | | `demucs_models` | Supported Demucs model names. | | `demucs_stems` | Valid stems per Demucs model, plus `all`. | | `defaults` | Default `PipelineParams`. | | `stages` | Pipeline stage definitions. | | `clustering_modes` | Human-readable labels for batch and online clustering modes. | ## `GET /api/jobs` Lists active in-memory jobs and completed run manifests found under `.runs/`. ```bash curl http://127.0.0.1:7860/api/jobs?limit=50 ``` Response: ```json { "active": [], "history": [ { "id": "58ca0db4ac74", "status": "complete", "filename": "song.wav", "created_at": 1778540000.0, "duration_sec": 2.4, "audio_duration_sec": 8.0, "realtime_factor": 0.3, "bpm": 120.0, "hit_count": 32, "cluster_count": 8, "clustering_mode": "online_preview", "stem": "all", "error": null } ] } ``` `created_at` is the manifest file modification time as a Unix timestamp. ## `POST /api/jobs` Creates an extraction job. The endpoint accepts browser-form-style JSON values for numeric and boolean params. For example, `{ "subdivision": "16" }` is coerced to integer `16` before validation. Invalid values return `400` with an actionable `detail` message suitable for direct UI display. Content type: `multipart/form-data` Fields: | Field | Type | Required | Description | |---|---|---:|---| | `file` | file | yes | Audio source. | | `params` | JSON string | no | Partial or full pipeline params. | Example: ```bash curl -F 'file=@song.wav' \ -F 'params={"separation_backend":"spleeter","spleeter_model":"spleeter:4stems","stem":"drums","clustering_mode":"online_preview","target_min":4,"target_max":12,"synthesize":true}' \ http://127.0.0.1:7860/api/jobs ``` Response status: `202 Accepted` Invalid params response example: ```json {"detail":"Invalid extraction parameter: subdivision must be one of 4, 8, 16, 32, 64"} ``` ```json { "id": "58ca0db4ac74", "status": "pending", "filename": "song.wav", "params": {"stem": "all", "clustering_mode": "online_preview"}, "stages": [], "logs": [], "result": null, "error": null } ``` ## `GET /api/jobs/{job_id}` Poll job status and retrieve results. This works for active in-memory jobs and completed historical jobs whose manifest is still present in `.runs/`. Statuses: | Status | Meaning | |---|---| | `pending` | Job is queued. | | `running` | Job is executing. | | `complete` | Result and artifacts are ready. | | `error` | Pipeline failed; `error` and `traceback` are populated. | Completed jobs contain: | Key | Meaning | |---|---| | `duration_sec` | Total wall time. | | `audio_duration_sec` | Duration of processed stem/source. | | `realtime_factor` | `duration_sec / audio_duration_sec`. | | `bpm` | Detected tempo. | | `hit_count` | Number of accepted onsets/hits. | | `cluster_count` | Number of sample clusters. | | `stages` | Per-stage timing/status/detail list. | | `samples` | Representative sample rows with score, duration, first onset, and playback/download URL. | | `hits` | Per-detected-hit review rows with onset, duration, label, cluster, representative flag, and playback/download URL. | | `overview` | Decimated envelope and clickable onset markers for waveform display. | | `files` | Relative artifact paths. Includes `source`, `stem`, `context_bed`, `target_reconstruction`, `reconstruction`, `midi`, and `archive` when available. | | `file_urls` | Direct API URLs for top-level artifacts. | ## `GET /api/jobs/{job_id}/events` Streams job snapshots as server-sent events. This is the preferred progress channel for the frontend; polling remains supported via `GET /api/jobs/{job_id}`. ```bash curl -N http://127.0.0.1:7860/api/jobs/58ca0db4ac74/events ``` Event shape: ```text event: job data: {"id":"58ca0db4ac74","status":"running","stages":[...]} ``` The stream closes after `complete` or `error`. Completed historical jobs emit one final `job` event and close. ## Top-level artifact meanings | Key | Path | Meaning | |---|---|---| | `source` | `source.wav` | Normalized source mix used for source preview. | | `stem` | `stem.wav` | Target stem being sampled. | | `context_bed` | `context_bed.wav` | Non-target stems/context bed; silent for `stem=all`. | | `target_reconstruction` | `target_reconstruction.wav` | Sample-triggered reconstruction of only the target stem. | | `reconstruction` | `reconstruction.wav` | Full-context reproduced mix: context bed plus target reconstruction. | | `midi` | `reconstruction.mid` | MIDI trigger reconstruction. | | `archive` | `sample-pack.zip` | Complete sample pack and reproduction artifacts. | ## `GET /api/jobs/{job_id}/files/{relative_path}` Downloads an artifact from a completed job. Examples: ```bash curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/sample-pack.zip curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/reconstruction.mid curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/reconstruction.wav curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/target_reconstruction.wav curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/samples/hihat_open_0.wav curl -O http://127.0.0.1:7860/api/jobs/58ca0db4ac74/files/review/hits/hit_00000_kick.wav ``` The endpoint prevents path traversal by resolving downloads under `.runs//output/` and requiring the final path to remain relative to that output root. ## `POST /api/cache/clear` Clears the in-memory DSP cache and disk stem/source cache. ```bash curl -X POST http://127.0.0.1:7860/api/cache/clear ``` Response: ```json {"status":"cleared","scope":"memory+disk"} ``` ## Pipeline parameters Defined in `pipeline_runner.PipelineParams`. | Parameter | Default | Meaning | |---|---:|---| | `stem` | `drums` | Source/stem to extract, or `all` to bypass source separation. Valid values depend on the selected backend/model. | | `separation_backend` | `spleeter` | Source-separation engine: `spleeter`, `demucs`, or `none`. | | `spleeter_model` | `spleeter:4stems` | Spleeter model profile used by the default backend. | | `demucs_model` | `htdemucs_ft` | Demucs model used when `separation_backend=demucs` or fallback is needed. | | `demucs_shifts` | `1` | Test-time shifts for Demucs quality/speed tradeoff. | | `demucs_overlap` | `0.25` | Demucs chunk overlap. | | `onset_mode` | `auto` | `auto`, `percussive`, `harmonic`, or `broadband`. | | `onset_delta` | `0.12` | Peak-pick threshold. | | `energy_threshold_db` | `-35` | RMS gate for accepting hits. | | `pre_pad` | `0.003` | Seconds of audio before onset. | | `min_dur` | `0.02` | Minimum hit duration. | | `max_dur` | `1.5` | Maximum hit duration. | | `min_gap` | `0.03` | Minimum time between onsets. | | `ncc_threshold` | `0.80` | Similarity threshold. Also used by online clustering assignment. | | `attack_ms` | `25` | Transient window used for NCC/prototypes. | | `mel_threshold` | `0.75` | Candidate prefilter threshold. For online mode, lower values such as `0.62` are useful. | | `linkage` | `average` | Agglomerative linkage for `batch_quality`. | | `clustering_mode` | `batch_quality` | `batch_quality` or `online_preview`. | | `target_min` | `5` | Lower cluster target; `0` disables target mode in batch mode. | | `target_max` | `20` | Upper cluster target; `0` disables target/cap mode. | | `synthesize` | `true` | Write synthesized alternates for clusters with multiple hits. | | `quantize_midi` | `true` | Snap MIDI notes to grid. | | `subdivision` | `16` | MIDI grid subdivision. | | `device` | `cpu` | Torch device for Demucs. | | `use_disk_cache` | `true` | Cache decoded full mix/stems by source digest and extraction settings. | | `allow_backend_fallback` | `true` | If Spleeter is selected but unavailable/fails, fall back to Demucs instead of failing the job. | ## Sample-card action API These endpoints back the simplified card workflow in the reference-style UI. They mutate `supervision_state.json` and preserve the original batch manifest. ### `POST /api/jobs/{job_id}/export-selected` Exports only the currently selected representative sample labels into `selected/` artifacts. Body: ```json {"labels":["kick_0","snare_0"],"synthesize":true} ``` Response shape: ```json { "export": { "kind": "selected-sample-export", "files": {"archive": "selected/sample-pack.zip", "midi": "selected/reconstruction.mid"}, "file_urls": {} }, "state": {} } ``` Rules: - `labels` must contain at least one visible sample label. - Only selected semantic clusters are rendered. - Suppressed hits remain excluded. - Pinned/drawn representatives are honored. - The export is written under `.runs//output/selected/` and does not mutate the original pack. ### `POST /api/jobs/{job_id}/samples/{sample_label}/draw` Cycles a card to the next active representative hit in that semantic cluster. The chosen hit is persisted as a representative override, so later selected/all edited exports use the same choice. Response: ```json {"sample": {"label": "kick_0", "url": "..."}, "state": {}} ``` ### `POST /api/jobs/{job_id}/samples/{sample_label}/edit` Applies a timing edit to the current representative and rewrites its preview WAV immediately. Body: ```json {"start_offset_ms":-8,"tail_offset_ms":24} ``` The backend slices from `stem.wav`, writes `overrides/hits/*_edited.wav`, updates the representative hit in semantic state, and returns a refreshed card row. ## Interactive supervision API The interactive supervision API is backed by `supervised_state.py` and persists state as: ```text .runs//output/supervision_state.json ``` The batch `manifest.json` remains immutable. Supervised edits update semantic state and can be rendered into a separate edited export under `supervised/` without mutating original artifacts. ### `GET /api/jobs/{job_id}/state` Returns the supervised state for a completed job. If the state file does not exist yet, it is created from the batch manifest. Response keys: | Key | Meaning | |---|---| | `summary` | Counts for hits, clusters, constraints, events, suggestions, suppressed/forced hits, locked clusters, latest export, undo availability. | | `hits` | Semantic hit rows with confidence, suppression/favorite/review flags, file URLs, and current cluster assignment. | | `clusters` | Semantic clusters with hit IDs, representative hit, confidence, locked state, and suppressed count. | | `review_queue` | Low-confidence/high-priority hits sorted for review. | | `constraints` | Recent replayable constraints. | | `events` | Recent state mutation events. | | `suggestions` | Open move/split/suppress suggestions, including exact `diff` previews. | ```bash curl http://127.0.0.1:7860/api/jobs//state ``` ### `POST /api/jobs/{job_id}/hits/force-onset` Creates a user-forced hit slice from `stem.wav` and adds it to semantic state. Body: ```json { "onset_sec": 0.123, "duration_ms": 160, "target_cluster_id": "cluster:0", "label": "snare" } ``` Required fields: | Field | Required | Meaning | |---|---:|---| | `onset_sec` | yes | Onset location in seconds. | | `duration_ms` | no | Slice length. If omitted, the system slices until the next active onset or a bounded default. | | `target_cluster_id` | no | Existing cluster to place the hit into. If omitted, a new user cluster is created. | | `label` | no | Override label. If omitted, the rule-based classifier labels the forced slice. | Effects: - writes `review/hits/hit_NNNNN_