{
  "openapi": "3.1.0",
  "info": {
    "title": "Song Creator Pro Desktop API",
    "description": "HTTP API for AI music generation, stem separation, and the Song Creator Pro library.\n\n## Base URL\n\nThe API runs on your computer at `http://127.0.0.1:8200`. Turn it on under\nSettings → HTTP API and restart the app. Change the port there or start the\napp with `--api-port`. Start with `--headless` to serve the API with no window.\nEvery route starts with `/api/v1/`.\n\nWhile the API is running, the app also serves this reference: the OpenAPI spec\nat `/openapi.json`, Swagger UI at `/docs` and ReDoc at `/redoc`. Once a key is\nset these need it too; open `/docs?api_key=...` and the page passes it on.\n\n## Quick start\n\n1. `GET /api/v1/health` — check the server is up\n2. `POST /api/v1/model/initialize` — load the model (required before generating)\n3. `GET /api/v1/model/status` — poll until `status: \"ready\"`\n4. `POST /api/v1/generation/start` — start a generation\n5. `GET /api/v1/generation/progress` — poll until `status: \"complete\"`\n6. `GET /api/v1/generation/result` — collect the result\n7. `GET /api/v1/audio/download?path=...` — download the audio\n\n## Generation is asynchronous\n\nGeneration runs for minutes, so there is no synchronous mode. Start, poll,\nthen collect. Only one generation runs at a time; starting a second returns 409.\n\n## Authentication\n\nNo key is needed unless you set one under Settings → HTTP API, start the app\nwith `--api-key`, or set `SCP_API_KEY`. Once set, send it as `X-API-Key`,\n`Authorization: Bearer`, or `?api_key=`. Only `/api/v1/health` and\n`/api/v1/system/version` are exempt. Binding to anything other than localhost\nwith `--host` requires a key.",
    "version": "1.0.0"
  },
  "paths": {
    "/api/v1/health": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Check the server is up",
        "description": "Cheapest way to confirm the API is reachable. Never requires an API key, so a client can probe a server before it knows the credentials.",
        "operationId": "health_api_v1_health_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/v1/system/version": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Get the app version",
        "description": "Version string from the bundled version.txt, or `dev` when running from a source checkout. Exempt from authentication so a client can identify a server before authenticating.",
        "operationId": "version_api_v1_system_version_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionResponse"
                },
                "example": {
                  "version": "1.4.4.0"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/v1/system/gpu": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Get GPU capabilities",
        "description": "Detected hardware and the limits it implies: capability tier, VRAM, the longest track and largest batch this machine can generate, and the devices that can be selected. Read this before choosing generation parameters. An ACE-Step text-to-music run that uses the language model stops at `max_duration` and says so in the result's `warnings`; other runs are not capped and can run out of GPU memory.",
        "operationId": "gpu_config_api_v1_system_gpu_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GpuConfigResponse"
                },
                "example": {
                  "tier": "high",
                  "gpu_name": "NVIDIA GeForce RTX 4090",
                  "gpu_memory_gb": 24.0,
                  "max_duration": 240.0,
                  "max_batch": 4,
                  "available_devices": [
                    "auto",
                    "cuda",
                    "cpu"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/system/backend": {
      "get": {
        "tags": [
          "System"
        ],
        "summary": "Get the active PyTorch backend",
        "description": "Which acceleration backend setup installed. Returns `unknown` before first-run setup has completed.",
        "operationId": "current_backend_api_v1_system_backend_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackendResponse"
                },
                "example": {
                  "backend": "cuda"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/setup/status": {
      "get": {
        "tags": [
          "Setup"
        ],
        "summary": "Check whether first-run setup is needed",
        "description": "True when the backend packages (PyTorch and friends) are not yet installed. Generation cannot start until setup completes.",
        "operationId": "status_api_v1_setup_status_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetupStatusResponse"
                },
                "example": {
                  "required": false
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/setup/options": {
      "get": {
        "tags": [
          "Setup"
        ],
        "summary": "List installable backends",
        "description": "Acceleration backends available for this machine, with the recommended one marked. Entries with `available: false` were detected but cannot run on this GPU. Feed an entry's id to `POST /api/v1/setup/start`.",
        "operationId": "options_api_v1_setup_options_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/SetupOption"
                  },
                  "type": "array",
                  "title": "Response 200 Options Api V1 Setup Options Get"
                },
                "example": [
                  {
                    "id": "cuda",
                    "name": "NVIDIA CUDA 12.8",
                    "gpu_name": "NVIDIA GeForce RTX 4090",
                    "recommended": true,
                    "download_size": "3.8 GB",
                    "description": "GPU acceleration for NVIDIA GPUs"
                  },
                  {
                    "id": "cpu",
                    "name": "CPU Only",
                    "recommended": false,
                    "download_size": "620 MB",
                    "description": "No GPU acceleration (slower)"
                  }
                ]
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/setup/start": {
      "post": {
        "tags": [
          "Setup"
        ],
        "summary": "Start installing a backend",
        "description": "Begins a multi-gigabyte download and install in the background and returns immediately. Poll `GET /api/v1/setup/progress` until status is `complete`. The app must be restarted afterwards. Returns `started: false` with a `reason` when an install is already running.",
        "operationId": "start_api_v1_setup_start_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetupStartRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartedResponse"
                },
                "example": {
                  "started": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/setup/progress": {
      "get": {
        "tags": [
          "Setup"
        ],
        "summary": "Poll setup progress",
        "description": "Current state of a running install. Status moves `idle` → `downloading` → `complete`, or `error` with the reason in `message`.",
        "operationId": "progress_api_v1_setup_progress_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetupProgressResponse"
                },
                "example": {
                  "status": "downloading",
                  "message": "Installing torch...",
                  "percent": 40
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/setup/reset": {
      "post": {
        "tags": [
          "Setup"
        ],
        "summary": "Queue a backend reinstall",
        "description": "Marks the installed packages for deletion on next launch — they cannot be removed while their DLLs are loaded. Optionally names the backend to install afterwards. Requires a restart to take effect.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "reset_api_v1_setup_reset_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetupResetRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResult"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings": {
      "get": {
        "tags": [
          "Settings"
        ],
        "summary": "Get all settings",
        "description": "Current generation settings: selected models per mode, device, quantization, CPU offload, and language-model options. Empty model choices are resolved to the defaults actually in use, so what you read is what generation will use.",
        "operationId": "get_settings_api_v1_settings_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsResponse"
                },
                "example": {
                  "device": "auto",
                  "config_path": "acestep-v15-turbo",
                  "config_path_custom": "acestep-v15-sft",
                  "config_path_cover": "acestep-v15-turbo",
                  "config_path_base": "acestep-v15-base",
                  "lm_model_path": "acestep-5Hz-lm-1.7B",
                  "init_llm": true,
                  "backend": "pt",
                  "quantization": false,
                  "offload_to_cpu": false,
                  "offload_dit_to_cpu": false,
                  "compile_model": false,
                  "use_flash_attention": true,
                  "gpu_tier": "high",
                  "yue2_quantization": "none"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Settings"
        ],
        "summary": "Update settings",
        "description": "Applies each supplied key and returns the full settings afterwards. Keys are applied individually and independently: an unknown or rejected key does not stop the others, and the response is still 200. Compare the returned values against what you sent to confirm each one landed.\n\nModel-selection changes take effect on the next generation; some others need a model reload.",
        "operationId": "update_settings_api_v1_settings_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SettingsUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsResponse"
                },
                "example": {
                  "device": "auto",
                  "config_path": "acestep-v15-turbo",
                  "config_path_custom": "acestep-v15-sft",
                  "config_path_cover": "acestep-v15-turbo",
                  "config_path_base": "acestep-v15-base",
                  "lm_model_path": "acestep-5Hz-lm-1.7B",
                  "init_llm": true,
                  "backend": "pt",
                  "quantization": false,
                  "offload_to_cpu": false,
                  "offload_dit_to_cpu": false,
                  "compile_model": false,
                  "use_flash_attention": true,
                  "gpu_tier": "high",
                  "yue2_quantization": "none"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/settings/preferences/{key}": {
      "get": {
        "tags": [
          "Settings"
        ],
        "summary": "Read a UI preference",
        "description": "Preferences are free-form UI state — panel widths, theme, volume. Returns null for a key that was never set.",
        "operationId": "get_preference_api_v1_settings_preferences__key__get",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Preference name. Free-form; the desktop UI uses keys such as `theme`, `player_volume` and `panel_left_width`. Separate from `/api/v1/settings`.",
              "title": "Key"
            },
            "description": "Preference name. Free-form; the desktop UI uses keys such as `theme`, `player_volume` and `panel_left_width`. Separate from `/api/v1/settings`."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreferenceResponse"
                },
                "example": {
                  "key": "theme",
                  "value": "dark"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Settings"
        ],
        "summary": "Write a UI preference",
        "description": "Stores any JSON-serialisable value under the key. Used by the desktop UI to persist layout and playback state.",
        "operationId": "set_preference_api_v1_settings_preferences__key__put",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Preference name. Free-form; the desktop UI uses keys such as `theme`, `player_volume` and `panel_left_width`. Separate from `/api/v1/settings`.",
              "title": "Key"
            },
            "description": "Preference name. Free-form; the desktop UI uses keys such as `theme`, `player_volume` and `panel_left_width`. Separate from `/api/v1/settings`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PreferenceRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResult"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/models": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "List locally available models",
        "description": "What is already on disk and usable without a download: generation checkpoints, language models, and LoRA adapters.",
        "operationId": "available_models_api_v1_models_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailableModelsResponse"
                },
                "example": {
                  "checkpoints": [
                    "acestep-v15-turbo"
                  ],
                  "lm_models": [],
                  "lora_models": [
                    "mylora.safetensors"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/models/catalog": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "List all known models with download state",
        "description": "Every model the app knows about, each flagged with whether it is downloaded. XL variants are listed on CUDA/ROCm GPUs with 12 GB or more of VRAM; below 16 GB they always load with INT8 quantization and CPU offload.",
        "operationId": "catalog_api_v1_models_catalog_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModelCatalogResponse"
                },
                "example": {
                  "dit_models": [
                    {
                      "id": "acestep-v15-turbo",
                      "downloaded": true
                    },
                    {
                      "id": "acestep-v15-sft",
                      "downloaded": false
                    }
                  ],
                  "lm_models": [
                    {
                      "id": "acestep-5Hz-lm-1.7B",
                      "downloaded": false
                    }
                  ],
                  "yue2_models": [
                    {
                      "id": "YuE2-3B",
                      "downloaded": true
                    },
                    {
                      "id": "YuE2-Vae",
                      "downloaded": true
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/models/download": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Start downloading a model",
        "description": "Begins a background download of several gigabytes and returns immediately. Poll `GET /api/v1/models/download/status`. Downloading is rarely necessary: generation fetches a missing model automatically.\n\nTo repair a damaged model, send `fresh: true`: the model's folder is deleted and downloaded again from scratch. `GET /api/v1/model/status` names the model to repair in `error.model`.\n\nA refused download is a 200 with `started: false` and the `reason`, such as another download already running.",
        "operationId": "start_download_api_v1_models_download_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ModelDownloadRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartedResponse"
                },
                "example": {
                  "started": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/models/download/status": {
      "get": {
        "tags": [
          "Models"
        ],
        "summary": "Poll download progress",
        "description": "State of the current or most recent model download.",
        "operationId": "download_status_api_v1_models_download_status_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DownloadStatusResponse"
                },
                "example": {
                  "status": "downloading",
                  "model": "acestep-v15-sft",
                  "percent": 12
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/models/download/cancel": {
      "post": {
        "tags": [
          "Models"
        ],
        "summary": "Cancel the running download",
        "description": "Signals the download to stop. Returns `cancelled: false` when nothing was running. Partial files are kept so a later download resumes from them.",
        "operationId": "cancel_download_api_v1_models_download_cancel_post",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelResponse"
                },
                "example": {
                  "cancelled": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/engines": {
      "get": {
        "tags": [
          "Engines"
        ],
        "summary": "List generation engines",
        "description": "ACE-Step and YuE2 with availability for this hardware, download state and FP8 support.",
        "operationId": "engine_catalog_api_v1_engines_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EngineCatalogResponse"
                },
                "example": {
                  "engines": [
                    {
                      "id": "acestep",
                      "display_name": "ACE-Step 1.5",
                      "available": true,
                      "downloaded": true,
                      "fp8_supported": false,
                      "cover_tools_downloaded": false,
                      "cover_tools_download_size_gb": 0.0,
                      "lyrics_transcriber_downloaded": false,
                      "lyrics_transcriber_download_size_gb": 4.7
                    }
                  ],
                  "active_engine": "acestep"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/engines/validate-abc": {
      "post": {
        "tags": [
          "Engines"
        ],
        "summary": "Validate an ABC score",
        "description": "Parse a YuE2 score and return a summary or the first error. Used by the score editor.",
        "operationId": "validate_abc_api_v1_engines_validate_abc_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidateAbcRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateAbcResponse"
                },
                "example": {
                  "ok": true,
                  "summary": "48 bars, meter 4/4, tempo 83"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/engines/move-note": {
      "post": {
        "tags": [
          "Engines"
        ],
        "summary": "Move a note in an ABC score",
        "description": "Moves the note between the given character offsets up or down by staff steps (negative is up). Every other note keeps its pitch: accidentals the move would disturb are written out explicitly. Tied notes cannot be moved. Offsets refer to the score with line endings normalised to LF, and the returned score uses LF.",
        "operationId": "move_note_api_v1_engines_move_note_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MoveNoteRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MoveNoteResponse"
                },
                "example": {
                  "ok": true,
                  "text": "X:1 ... (the full edited score)",
                  "pitch": 74
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/engines/score-map": {
      "post": {
        "tags": [
          "Engines"
        ],
        "summary": "Read a score as a song map",
        "description": "Splits a YuE2 score into its sections with bar ranges, timing and per-bar chords, pairs each section with a tagged lyric block by label and order, and lists the keys the song can move to. Returns `ok: false` with the validator's message for a score that does not parse.",
        "operationId": "score_map_api_v1_engines_score_map_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScoreMapRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScoreMapResponse"
                },
                "example": {
                  "ok": true,
                  "key": "C",
                  "tempo": 120,
                  "meter": "4/4",
                  "seconds": 16.0,
                  "bars": 8,
                  "has_chords": true,
                  "sections": [
                    {
                      "label": "verse",
                      "first_bar": 1,
                      "bar_count": 4,
                      "start": 0.0,
                      "seconds": 8.0,
                      "instrumental": false,
                      "lyric": {
                        "index": 0,
                        "label": "Verse",
                        "first_line": "Neon fades along the lane"
                      },
                      "bars": [
                        {
                          "number": 1,
                          "start": 0.0,
                          "rest": false,
                          "chords": [
                            {
                              "symbol": "C",
                              "offset": 0.0
                            }
                          ]
                        }
                      ]
                    }
                  ],
                  "unused_lyrics": [],
                  "transpose_options": [
                    {
                      "semitones": 2,
                      "key": "D"
                    }
                  ],
                  "key_chords": [
                    "C",
                    "Dm",
                    "Em",
                    "F",
                    "G",
                    "Am",
                    "Bdim"
                  ],
                  "chord_roots": [
                    "C",
                    "C#",
                    "Db"
                  ],
                  "chord_qualities": [
                    "",
                    "m",
                    "7"
                  ],
                  "tempo_range": [
                    40,
                    240
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/engines/edit-score": {
      "post": {
        "tags": [
          "Engines"
        ],
        "summary": "Apply a song map edit",
        "description": "Applies one change to a score and its lyrics. The `edit` object takes one of these shapes: `{\"op\": \"duplicate\"|\"delete\", \"section\": i}` (sections count from 0; the paired lyric block is copied or removed with it), `{\"op\": \"move\", \"section\": i, \"to\": j}` (the paired lyric block moves with it), `{\"op\": \"set_chord\", \"bar\": b, \"index\": k, \"chord\": \"Dm7\"}` (bars count from 1; `index` picks the chord within the bar, and 0 adds one to a bar without), `{\"op\": \"transpose\", \"semitones\": n}` (-6 to 6, not 0) or `{\"op\": \"set_tempo\", \"bpm\": q}` (a whole number from 40 to 240). For structure and chord edits every other note keeps its pitch. A change that would leave an invalid score is refused with a reason and nothing changes.",
        "operationId": "edit_score_api_v1_engines_edit_score_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EditScoreRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EditScoreResponse"
                },
                "example": {
                  "ok": true,
                  "text": "X:1 ... (the full edited score)",
                  "lyrics": "[Chorus]\n..."
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/model/initialize": {
      "post": {
        "tags": [
          "Model"
        ],
        "summary": "Load the generation model",
        "description": "**Required before any generation.** Loads the model in the background and returns immediately; poll `GET /api/v1/model/status` until status is `ready`. Missing model files are downloaded first, so a cold start can take a long time. Optionally accepts settings to apply before loading.",
        "operationId": "initialize_api_v1_model_initialize_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitializeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InitializeResponse"
                },
                "example": {
                  "success": true,
                  "message": "Initialization started"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "409": {
            "description": "Setup has not completed, so there is nothing to load. Run the setup endpoints first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/model/reinitialize": {
      "post": {
        "tags": [
          "Model"
        ],
        "summary": "Reload the model with new settings",
        "description": "Applies the supplied settings, drops the language model so it is recreated, and reloads. Use after changing quantization, device, or CPU offload, which cannot be applied to an already-loaded model.",
        "operationId": "reinitialize_api_v1_model_reinitialize_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitializeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InitializeResponse"
                },
                "example": {
                  "success": true,
                  "message": "Initialization started"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "409": {
            "description": "Setup has not completed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/model/status": {
      "get": {
        "tags": [
          "Model"
        ],
        "summary": "Poll model load progress",
        "description": "Status moves `idle` → `loading` → `ready`, or `error` with the reason in `message` and a full traceback in `detail`. Generation is refused until this reads `ready`.\n\nOn `error`, `error` names the cause and the steps that fix it. When `error.cause` is `checkpoint` and `error.model` is set, repair it with `POST /api/v1/models/download` and `fresh: true`, then `POST /api/v1/model/initialize`.",
        "operationId": "status_api_v1_model_status_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InitStatusResponse"
                },
                "example": {
                  "status": "ready",
                  "message": "Ready",
                  "percent": 100
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/model/llm/unload": {
      "post": {
        "tags": [
          "Model"
        ],
        "summary": "Unload the language model",
        "description": "Frees the VRAM held by the lyric and caption assistant while leaving the generation model loaded. Generation then runs without it until `init_llm` is set back to true; lyric generation, caption enhancement and source analysis still load it on demand.",
        "operationId": "unload_llm_api_v1_model_llm_unload_post",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResult"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generation/start": {
      "post": {
        "tags": [
          "Generation"
        ],
        "summary": "Start a generation",
        "description": "Starts generation in the background and returns immediately. Poll `GET /api/v1/generation/progress` until status is `complete`, then collect `GET /api/v1/generation/result`.\n\n`task_type` selects the mode: `text2music` (from a caption and lyrics), `cover` (restyle a source track), `repaint` (regenerate a section), `extract` (isolate one instrument), `complete` (add parts to a track), or `demucs` (stem separation). Modes other than `text2music` need source audio as `src_audio_base64`.\n\nUnknown fields are passed through to the engine, so parameters newer than this schema still work. The required model is loaded automatically if a different one is selected, and downloaded if missing.",
        "operationId": "start_api_v1_generation_start_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerationStartRequest"
              },
              "examples": {
                "text2music": {
                  "summary": "Text to music with ACE-Step",
                  "value": {
                    "task_type": "text2music",
                    "prompt": "lofi hip hop, mellow piano, vinyl crackle, rainy night",
                    "lyrics": "[Verse]\nRain on the window, coffee gone cold\n\n[Chorus]\nStay a while, stay a while",
                    "audio_duration": 60
                  }
                },
                "yue2": {
                  "summary": "A song with YuE2",
                  "value": {
                    "engine": "yue2",
                    "task_type": "text2music",
                    "prompt": "indie pop, bright guitars, female vocal, upbeat",
                    "lyrics": "[Verse]\nNeon fades along the lane\n\n[Chorus]\nLet the day come into view",
                    "yue2_planning": "full",
                    "yue2_max_seconds": 180
                  }
                },
                "yue2_cover": {
                  "summary": "A YuE2 cover from an analysed song",
                  "value": {
                    "engine": "yue2",
                    "task_type": "cover",
                    "prompt": "acoustic folk, warm guitar, male vocal",
                    "lyrics": "[Verse]\nNeon fades along the lane\n\n[Chorus]\nLet the day come into view",
                    "yue2_abc": "X:1 ... (the score from analyze-source)",
                    "yue2_planning": "melody"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartedResponse"
                },
                "example": {
                  "started": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "409": {
            "description": "Either a generation is already running — only one runs at a time — or no model is loaded. The detail says which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generation/progress": {
      "get": {
        "tags": [
          "Generation"
        ],
        "summary": "Poll generation progress",
        "description": "Status moves `idle` → `generating` → `complete`, or `error`. `step` and `total_steps` track diffusion progress; `message` names the current phase, which may be a model download or model switch before generation begins.",
        "operationId": "progress_api_v1_generation_progress_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateProgressResponse"
                },
                "example": {
                  "status": "generating",
                  "message": "Generating...",
                  "percent": 40,
                  "step": 4,
                  "total_steps": 10
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generation/result": {
      "get": {
        "tags": [
          "Generation"
        ],
        "summary": "Get the last generation result",
        "description": "The most recent result, held until the next generation replaces it. `audio_paths` are server-side absolute paths — fetch each through `GET /api/v1/audio/download?path=...`, which is the only route permitted to read them.\n\nReturned fields vary by task type: stem separation reports one path per stem, while text2music reports musical metadata such as bpm and key.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "result_api_v1_generation_result_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenerateResultResponse"
                },
                "example": {
                  "success": true,
                  "audio_paths": [
                    "C:\\...\\tmp\\output_0.wav"
                  ],
                  "seed": "12345",
                  "duration": 120.0,
                  "bpm": 128.0
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generation/cancel": {
      "post": {
        "tags": [
          "Generation"
        ],
        "summary": "Cancel the running generation",
        "description": "Stops the running generation or stem separation and reports `cancelled: true`, or `cancelled: false` when nothing is running. The run stops at its next checkpoint, such as the next diffusion step; a stem separation finishes its current pass and then discards it. Progress then returns to `idle` and the result's `error` is `Cancelled`.",
        "operationId": "cancel_api_v1_generation_cancel_post",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelResponse"
                },
                "example": {
                  "cancelled": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generation/analyze-source": {
      "post": {
        "tags": [
          "Generation"
        ],
        "summary": "Analyse source audio",
        "description": "Inspects base64-encoded audio. With `engine` `acestep` (the default) it reports a style caption, tempo, length and musical key, plus lyrics from the lyrics transcriber add-on when it is downloaded. Without it, `lyrics_transcriber_missing` is set and the other fields are still filled. Use it to fill sensible defaults before a cover or repaint rather than guessing. With `engine` `yue2` it transcribes the song into the `score` and section-tagged `lyrics` that a YuE2 cover (`task_type` `cover`, `engine` `yue2`) needs. The request returns when analysis finishes; `GET /api/v1/generation/progress` reports progress meanwhile.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "analyze_source_api_v1_generation_analyze_source_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SourceAudioRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyzeSourceResponse"
                },
                "example": {
                  "success": true,
                  "caption": "Dreamy synth pop",
                  "lyrics": "Hello there\nHow are you?",
                  "lyrics_found": true,
                  "bpm": 128.0,
                  "duration": 180.5,
                  "key_scale": "A minor"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generation/audio-hash": {
      "post": {
        "tags": [
          "Generation"
        ],
        "summary": "Hash audio for deduplication",
        "description": "SHA-256 of the base64-decoded file bytes, used to recognise the same source track across requests. Pair it with `GET /api/v1/generation/extract-group` to reuse a previous separation instead of paying for it twice. Returns an empty hash if the input could not be decoded.",
        "operationId": "audio_hash_api_v1_generation_audio_hash_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AudioBase64Request"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AudioHashResponse"
                },
                "example": {
                  "hash": "3b7f2c..."
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/generation/extract-group": {
      "get": {
        "tags": [
          "Generation"
        ],
        "summary": "Find a previous extraction",
        "description": "Looks up an earlier stem separation or extraction for the same source audio, identified by the hash from `/api/v1/generation/audio-hash`. When `found` is true, the existing history entry already holds the stems and re-running is unnecessary.",
        "operationId": "extract_group_api_v1_generation_extract_group_get",
        "parameters": [
          {
            "name": "source_hash",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "The `hash` from `POST /api/v1/generation/audio-hash` for the source track.",
              "title": "Source Hash"
            },
            "description": "The `hash` from `POST /api/v1/generation/audio-hash` for the source track."
          },
          {
            "name": "task_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Kind of earlier run to look for: `extract` (single-instrument extraction) or `demucs` (stem separation).",
              "default": "extract",
              "title": "Task Type"
            },
            "description": "Kind of earlier run to look for: `extract` (single-instrument extraction) or `demucs` (stem separation)."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractGroupResponse"
                },
                "example": {
                  "found": false
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audio/download": {
      "get": {
        "tags": [
          "Audio"
        ],
        "summary": "Download an audio file",
        "description": "Streams a generated file with the right content type, so it can be used directly as an `<audio>` source. Supply a path from a generation result or a history sample.\n\nPaths are confined to the app's temp and history directories. Anything else is refused, including paths that traverse out of them or reach them through a symlink.",
        "operationId": "download_api_v1_audio_download_get",
        "parameters": [
          {
            "name": "path",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Absolute server path of the file, URL-encoded: an entry of `audio_paths` from `GET /api/v1/generation/result`, or a history sample's `path`. History samples also carry a ready-made `url` that can be used instead.",
              "title": "Path"
            },
            "description": "Absolute server path of the file, URL-encoded: an entry of `audio_paths` from `GET /api/v1/generation/result`, or a history sample's `path`. History samples also carry a ready-made `url` that can be used instead."
          }
        ],
        "responses": {
          "200": {
            "description": "The audio file.",
            "content": {
              "audio/mpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/wav": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/flac": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/ogg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/opus": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/aac": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "403": {
            "description": "The path resolves outside the temp and history directories.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "404": {
            "description": "No file at that path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/history": {
      "get": {
        "tags": [
          "History"
        ],
        "summary": "List generation history",
        "description": "Every stored generation, newest first, with its samples and the parameters that produced it.\n\nEach sample carries a `url` that is origin-relative, so it resolves against whatever host you reached the API on and keeps working through a tunnel or over a LAN. Use it as-is rather than building a URL from `path`.",
        "operationId": "list_history_api_v1_history_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/HistoryEntry"
                  },
                  "type": "array",
                  "title": "Response 200 List History Api V1 History Get"
                },
                "example": [
                  {
                    "id": "gen_1712345678",
                    "timestamp": 1712345678.0,
                    "task_type": "text2music",
                    "prompt": "lofi hip hop, rainy",
                    "samples": [
                      {
                        "filename": "sample_0.wav",
                        "path": "C:\\...\\history\\gen_1712345678\\sample_0.wav",
                        "url": "/api/v1/audio/download?path=C%3A%5C...%5Csample_0.wav"
                      }
                    ]
                  }
                ]
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "History"
        ],
        "summary": "Delete all history",
        "description": "Removes every history entry and its audio. Irreversible. Generated files not yet downloaded are lost.",
        "operationId": "clear_history_api_v1_history_delete",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResult"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/history/{item_id}": {
      "delete": {
        "tags": [
          "History"
        ],
        "summary": "Delete one history entry",
        "description": "Removes the entry and all of its audio files. Irreversible.",
        "operationId": "delete_item_api_v1_history__item_id__delete",
        "parameters": [
          {
            "name": "item_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "History entry `id` from `GET /api/v1/history`.",
              "title": "Item Id"
            },
            "description": "History entry `id` from `GET /api/v1/history`."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResult"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "404": {
            "description": "No history entry with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/history/{history_id}/samples/{sample_index}": {
      "delete": {
        "tags": [
          "History"
        ],
        "summary": "Delete one sample from an entry",
        "description": "Removes a single audio file by its position in the entry's `samples` list. Deleting the last remaining sample deletes the whole entry, which the response reports as `empty: true`.",
        "operationId": "delete_sample_api_v1_history__history_id__samples__sample_index__delete",
        "parameters": [
          {
            "name": "history_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "History entry `id` from `GET /api/v1/history`.",
              "title": "History Id"
            },
            "description": "History entry `id` from `GET /api/v1/history`."
          },
          {
            "name": "sample_index",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "description": "Position in the entry's `samples` list, counting from 0.",
              "title": "Sample Index"
            },
            "description": "Position in the entry's `samples` list, counting from 0."
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteSampleResponse"
                },
                "example": {
                  "success": true,
                  "empty": false
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "404": {
            "description": "No such entry, or the sample index is out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "History"
        ],
        "summary": "Rename a sample",
        "description": "Sets the display label on one sample. Does not rename the file on disk, so URLs and paths stay valid.",
        "operationId": "rename_sample_api_v1_history__history_id__samples__sample_index__patch",
        "parameters": [
          {
            "name": "history_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "History entry `id` from `GET /api/v1/history`.",
              "title": "History Id"
            },
            "description": "History entry `id` from `GET /api/v1/history`."
          },
          {
            "name": "sample_index",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "description": "Position in the entry's `samples` list, counting from 0.",
              "title": "Sample Index"
            },
            "description": "Position in the entry's `samples` list, counting from 0."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameSampleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResult"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "404": {
            "description": "No such entry, or the sample index is out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/history/{history_id}/append": {
      "post": {
        "tags": [
          "History"
        ],
        "summary": "Add an audio file to an entry",
        "description": "Copies an existing file into a history entry as a new sample — used to keep separated stems alongside the track they came from.\n\nThe source path is confined to the app's temp and history directories, the same restriction the download route enforces.",
        "operationId": "append_api_v1_history__history_id__append_post",
        "parameters": [
          {
            "name": "history_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "History entry `id` from `GET /api/v1/history`.",
              "title": "History Id"
            },
            "description": "History entry `id` from `GET /api/v1/history`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AppendHistoryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The sample was added.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppendSampleResponse"
                },
                "example": {
                  "success": true,
                  "sample_index": 3
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "403": {
            "description": "The source path resolves outside the temp and history directories.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "404": {
            "description": "No history entry with that id, or no file at the source path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lyrics/generate": {
      "post": {
        "tags": [
          "Lyrics"
        ],
        "summary": "Write lyrics from a description",
        "description": "Asks the language model for lyrics matching a free-text brief, optionally in a named language. Loads the language model on first use, so the first call is slow.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "generate_lyrics_api_v1_lyrics_generate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GenerateLyricsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LyricsResponse"
                },
                "example": {
                  "success": true,
                  "lyrics": "[verse]\nRain on the window..."
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/lyrics/enhance": {
      "post": {
        "tags": [
          "Lyrics"
        ],
        "summary": "Rewrite existing lyrics",
        "description": "Improves lyrics you already have, using the caption as style context. Requires the language model, like the other endpoints in this group.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "enhance_lyrics_api_v1_lyrics_enhance_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnhanceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LyricsResponse"
                },
                "example": {
                  "success": true,
                  "lyrics": "[verse]\nRain taps the glass..."
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/caption/enhance": {
      "post": {
        "tags": [
          "Lyrics"
        ],
        "summary": "Rewrite a caption",
        "description": "Expands a short caption into the richer style description the generation model responds to best, using the lyrics as context.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "enhance_caption_api_v1_caption_enhance_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnhanceRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaptionResponse"
                },
                "example": {
                  "success": true,
                  "caption": "lofi hip hop, rainy night, warm tape saturation"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras": {
      "get": {
        "tags": [
          "LoRAs"
        ],
        "summary": "List LoRA adapters",
        "description": "Adapters found in the LoRA folder, with whether each is enabled, its blend strength, and the base model it was trained against. Enabled adapters apply to the next text2music generation only — other task types ignore them.",
        "operationId": "list_loras_api_v1_loras_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoraListResponse"
                },
                "example": {
                  "loras": [
                    {
                      "name": "mylora.safetensors",
                      "enabled": false,
                      "scale": 1.0,
                      "base_model": "acestep-v15-turbo"
                    }
                  ],
                  "quantized": false,
                  "active_model": "acestep-v15-turbo",
                  "yue2_quantized": false
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras/folder/path": {
      "get": {
        "tags": [
          "LoRAs"
        ],
        "summary": "Get the LoRA folder path",
        "description": "Where to put new adapter files. Returns a path rather than opening a file manager, since the caller may be on a different machine.",
        "operationId": "folder_path_api_v1_loras_folder_path_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PathResponse"
                },
                "example": {
                  "path": "C:\\Users\\you\\AppData\\Local\\SongCreatorPro\\loras"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras/hub/lookup": {
      "post": {
        "tags": [
          "LoRAs"
        ],
        "summary": "Find LoRAs in a Hugging Face repo",
        "description": "Takes a Hugging Face model link or an owner/name repo id and lists the safetensors files in it, with each file's size, the engine its tensor names suit, and the licence on the repo's model card. Only public repos work. Look a repo up before downloading from it.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "hub_lookup_api_v1_loras_hub_lookup_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HubLookupRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HubLookupResponse"
                },
                "example": {
                  "success": true,
                  "repo_id": "owner/yue2-style-lora",
                  "license": "apache-2.0",
                  "files": [
                    {
                      "path": "lora.safetensors",
                      "size_bytes": 36700160,
                      "engine": "yue2",
                      "companions": []
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras/hub/import": {
      "post": {
        "tags": [
          "LoRAs"
        ],
        "summary": "Import every LoRA in a Hugging Face repo",
        "description": "Looks the repo up and downloads each adapter in it that suits the engine: one file per folder, taking the smallest variant when a folder holds several precisions, and skipping adapters built for the other engine. Runs in the background; poll the status route. Without an engine, the saved engine is used.",
        "operationId": "hub_import_api_v1_loras_hub_import_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HubImportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartedResponse"
                },
                "example": {
                  "started": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras/hub/download": {
      "post": {
        "tags": [
          "LoRAs"
        ],
        "summary": "Download a LoRA from Hugging Face",
        "description": "Downloads one file from the repo most recently looked up, plus its adapter_config.json when it has one, into the LoRA folder. Runs in the background; poll the status route. Only safetensors files listed by the lookup can be downloaded.",
        "operationId": "hub_download_api_v1_loras_hub_download_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HubDownloadRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartedResponse"
                },
                "example": {
                  "started": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras/hub/status": {
      "get": {
        "tags": [
          "LoRAs"
        ],
        "summary": "Get LoRA download progress",
        "description": "Progress of the current or last Hugging Face download. When status is done, entry names the new LoRA as it appears in the list route.",
        "operationId": "hub_status_api_v1_loras_hub_status_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HubStatusResponse"
                },
                "example": {
                  "status": "downloading",
                  "message": "Downloading lora.safetensors",
                  "percent": 40,
                  "entry": ""
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras/hub/cancel": {
      "post": {
        "tags": [
          "LoRAs"
        ],
        "summary": "Cancel a LoRA download",
        "description": "Stops the current Hugging Face download. Nothing is added to the LoRA folder.",
        "operationId": "hub_cancel_api_v1_loras_hub_cancel_post",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResult"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras/{name}/state": {
      "put": {
        "tags": [
          "LoRAs"
        ],
        "summary": "Enable or disable a LoRA",
        "description": "Turns an adapter on or off and sets its blend strength. Enabling one that targets a different base model disables the conflicting selection, since adapters for different bases cannot be combined; `disabled` lists them.\n\nWhen the adapter's base model cannot be detected, enabling it returns `success: true` with `needs_base_model: true` and the adapter stays disabled. Set the base model with `PUT /api/v1/loras/{name}/base-model`, which also enables it. When the selection cannot be applied to the loaded model, the response is a 200 with `success: false` and the reason in `message`.",
        "operationId": "set_state_api_v1_loras__name__state_put",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Adapter `name` as listed by `GET /api/v1/loras`, URL-encoded.",
              "title": "Name"
            },
            "description": "Adapter `name` as listed by `GET /api/v1/loras`, URL-encoded."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoraStateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoraStateResponse"
                },
                "example": {
                  "success": true,
                  "disabled": [
                    "other-style.safetensors"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/loras/{name}/base-model": {
      "put": {
        "tags": [
          "LoRAs"
        ],
        "summary": "Set a LoRA's base model",
        "description": "Records which model the adapter was trained against, so generation loads the right one. Detected automatically where the adapter declares it; set it manually when detection fails. Setting it also enables the adapter and disables adapters for a different base, listed in `disabled`. When the selection cannot be applied to the loaded model, the response is a 200 with `success: false` and the reason in `message`.",
        "operationId": "set_base_model_api_v1_loras__name__base_model_put",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Adapter `name` as listed by `GET /api/v1/loras`, URL-encoded.",
              "title": "Name"
            },
            "description": "Adapter `name` as listed by `GET /api/v1/loras`, URL-encoded."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoraBaseModelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoraStateResponse"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/cache": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "Get cache sizes",
        "description": "How much disk the downloaded models use, human-readable, and which data folder holds them.",
        "operationId": "cache_info_api_v1_storage_cache_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CacheInfoResponse"
                },
                "example": {
                  "model_cache_size": "52.5 GB",
                  "data_folder": "C:\\Users\\you\\AppData\\Local\\SongCreatorPro",
                  "default_data_folder": "C:\\Users\\you\\AppData\\Local\\SongCreatorPro",
                  "is_custom_folder": false,
                  "folder_unavailable": false,
                  "unavailable_path": ""
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/cache/model/clear": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "Clear the model cache",
        "description": "Deletes the downloaded models: the generation models and the Demucs stem separation models. Each downloads again when next needed, so this frees space at the cost of future download time. LoRAs and the installed packages are not touched. Always succeeds.",
        "operationId": "clear_model_cache_api_v1_storage_cache_model_clear_post",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClearCacheResponse"
                },
                "example": {
                  "success": true,
                  "message": "Model cache cleared"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/clear-all": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "Delete all app data",
        "description": "**Irreversible.** Deletes downloaded models, LoRA adapters, the entire generation history, temp files, and caches — typically tens of gigabytes — and marks the backend packages for reinstall on next launch.\n\nUnlike the desktop menu item, this does not close the app. It returns `needs_restart: true` and leaves restarting to the caller, because closing the window would also stop this server mid-response.",
        "operationId": "clear_all_api_v1_storage_clear_all_post",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClearAllResponse"
                },
                "example": {
                  "success": true,
                  "needs_restart": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/data-folder": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "Get data folder locations",
        "description": "Where app data lives: the configured custom path if any, the platform default, and which is actually in effect. `unavailable` is true when a configured location cannot be reached, such as an unplugged external drive.",
        "operationId": "get_data_folder_api_v1_storage_data_folder_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DataFolderResponse"
                },
                "example": {
                  "custom_path": "",
                  "default_path": "C:\\Users\\you\\AppData\\Local\\SongCreatorPro",
                  "effective_path": "C:\\Users\\you\\AppData\\Local\\SongCreatorPro",
                  "is_custom": false,
                  "unavailable": false
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Storage"
        ],
        "summary": "Set the data folder path",
        "description": "Records a new location without moving anything, and requires a restart. To move the existing data instead, use `POST /api/v1/storage/data-folder/migrate`. Returns `success: false` when the location could not be saved.",
        "operationId": "set_data_folder_api_v1_storage_data_folder_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DataFolderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResult"
                },
                "example": {
                  "success": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/data-folder/validate": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "Check whether a path can be used",
        "description": "Replaces the desktop folder picker for callers that have no file dialog: supply a path and get back whether it is usable, with the reason if not. Rejects system directories, the current location, over-long Windows paths, unwritable locations, and destinations without room for the existing data.\n\nRead-only apart from a brief write test in the candidate directory.",
        "operationId": "validate_data_folder_api_v1_storage_data_folder_validate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DataFolderRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateFolderResponse"
                },
                "example": {
                  "ok": true,
                  "error": ""
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/data-folder/migrate": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "Move the data folder",
        "description": "Copies models, adapters, history, and caches to a new location, verifies the copy, then removes the originals. Runs in the background — poll `GET /api/v1/storage/data-folder/migration/progress`. Validate the destination first; a migration interrupted partway is rolled back on next launch.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "migrate_api_v1_storage_data_folder_migrate_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MigrateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MigrateResponse"
                },
                "example": {
                  "success": true,
                  "source_size": "52.1 GB"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          },
          "422": {
            "description": "The request body or query parameters failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/data-folder/migration/progress": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "Poll migration progress",
        "description": "Phase moves `idle` → `copying` → `verifying` → `cleaning_up` → `completed`. `current_file` names what is being copied.",
        "operationId": "migration_progress_api_v1_storage_data_folder_migration_progress_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MigrationProgressResponse"
                },
                "example": {
                  "phase": "copying",
                  "percent": 42,
                  "current_file": "checkpoints\\acestep-v15-turbo\\model.safetensors",
                  "copied": 120,
                  "total": 570,
                  "error": ""
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/data-folder/reset": {
      "post": {
        "tags": [
          "Storage"
        ],
        "summary": "Move data back to the default location",
        "description": "Migrates everything back to the platform default and clears the custom path. Reports `needs_restart` when a restart is required to finish.\n\nThis endpoint reports failure in the body rather than the status code: a 200 with `success: false` and an `error` string. Check `success`, not the status.",
        "operationId": "reset_data_folder_api_v1_storage_data_folder_reset_post",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RestartResponse"
                },
                "example": {
                  "success": true,
                  "needs_restart": true
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/data-folder/path": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "Get the data folder path",
        "description": "The directory in use, as a string. Returns a path rather than opening a file manager, since the caller may be on a different machine.",
        "operationId": "data_folder_path_api_v1_storage_data_folder_path_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PathResponse"
                },
                "example": {
                  "path": "C:\\Users\\you\\AppData\\Local\\SongCreatorPro"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storage/logs-folder/path": {
      "get": {
        "tags": [
          "Storage"
        ],
        "summary": "Get the logs folder path",
        "description": "Where daily log files are written. Logs always live beside the default data location, even when a custom data folder is configured.",
        "operationId": "logs_folder_path_api_v1_storage_logs_folder_path_get",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PathResponse"
                },
                "example": {
                  "path": "C:\\Users\\you\\AppData\\Local\\SongCreatorPro\\logs"
                }
              }
            }
          },
          "401": {
            "description": "No API key, or the wrong one. Send `X-API-Key`, `Authorization: Bearer`, or `?api_key=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AnalyzeSourceResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether analysis completed."
          },
          "caption": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Caption",
            "description": "A style caption describing the source."
          },
          "lyrics": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics",
            "description": "Lyrics heard by the lyrics transcriber; empty when it did not run or heard none."
          },
          "lyrics_found": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics Found",
            "description": "Whether the lyrics transcriber heard any lyrics."
          },
          "lyrics_transcriber_missing": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics Transcriber Missing",
            "description": "Set when lyrics were wanted but the lyrics transcriber add-on is not downloaded."
          },
          "lyrics_transcriber_downloading": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics Transcriber Downloading",
            "description": "Set with `lyrics_transcriber_missing` while the transcriber is downloading."
          },
          "lyrics_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics Error",
            "description": "Why the lyrics could not be transcribed; the other fields are still filled."
          },
          "bpm": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bpm",
            "description": "Detected tempo."
          },
          "duration": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration",
            "description": "Source length in seconds."
          },
          "key_scale": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Scale",
            "description": "Detected musical key."
          },
          "engine": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Engine",
            "description": "`yue2` for a YuE2 cover analysis; absent for ACE-Step."
          },
          "score": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Score",
            "description": "YuE2: the song's melody as an ABC score. Send it as `yue2_abc`."
          },
          "planning": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Planning",
            "description": "YuE2: `full` when the score has chords, otherwise `melody`. Send it as `yue2_planning`."
          },
          "has_chords": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Has Chords",
            "description": "YuE2: whether the score includes chords."
          },
          "summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Summary",
            "description": "YuE2: a one-line description of the score, such as its bar count, meter and tempo."
          },
          "warnings": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Warnings",
            "description": "YuE2: problems found in the transcription that did not stop it."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success"
        ],
        "title": "AnalyzeSourceResponse"
      },
      "AppendHistoryRequest": {
        "properties": {
          "audio_path": {
            "type": "string",
            "title": "Audio Path",
            "description": "Server-side path of the file to copy, such as an entry of a generation result's `audio_paths`. Must be inside the app's temp or history directory.",
            "examples": [
              "C:\\Users\\you\\AppData\\Local\\SongCreatorPro\\tmp\\demucs_vocals.mp3"
            ]
          },
          "track_name": {
            "type": "string",
            "title": "Track Name",
            "description": "Stem name used for the sample's label, e.g. `backing_vocals` becomes \"Backing Vocals\". Empty labels it \"Sample N\".",
            "default": "",
            "examples": [
              "vocals"
            ]
          },
          "audio_format": {
            "type": "string",
            "title": "Audio Format",
            "description": "File extension to use when `audio_path` has none, such as `wav` or `mp3`.",
            "default": "wav",
            "examples": [
              "mp3"
            ]
          }
        },
        "type": "object",
        "required": [
          "audio_path"
        ],
        "title": "AppendHistoryRequest"
      },
      "AppendSampleResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Always true; failures are returned as 403 or 404."
          },
          "sample_index": {
            "type": "integer",
            "title": "Sample Index",
            "description": "Position of the new sample in the entry's `samples` list."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success",
          "sample_index"
        ],
        "title": "AppendSampleResponse"
      },
      "AudioBase64Request": {
        "properties": {
          "audio_base64": {
            "type": "string",
            "title": "Audio Base64",
            "description": "Base64-encoded audio file (raw file bytes, no `data:` prefix). The hash is taken over the decoded bytes.",
            "examples": [
              "UklGRiQAAABXQVZFZm10IBAAAAABAAIAgLsAAADuAgAEABAAZGF0YQAAAAA="
            ]
          }
        },
        "type": "object",
        "required": [
          "audio_base64"
        ],
        "title": "AudioBase64Request"
      },
      "AudioHashResponse": {
        "properties": {
          "hash": {
            "type": "string",
            "title": "Hash",
            "description": "SHA-256 of the decoded audio. Empty when the input could not be decoded."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "hash"
        ],
        "title": "AudioHashResponse"
      },
      "AvailableModelsResponse": {
        "properties": {
          "checkpoints": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Checkpoints",
            "description": "Locally available DiT checkpoints."
          },
          "lm_models": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Lm Models",
            "description": "Locally available language models."
          },
          "lora_models": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Lora Models",
            "description": "LoRA files and directories found on disk."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "checkpoints",
          "lm_models",
          "lora_models"
        ],
        "title": "AvailableModelsResponse"
      },
      "BackendResponse": {
        "properties": {
          "backend": {
            "type": "string",
            "title": "Backend",
            "description": "Configured PyTorch backend, or `unknown` before setup."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "backend"
        ],
        "title": "BackendResponse"
      },
      "CacheInfoResponse": {
        "properties": {
          "model_cache_size": {
            "type": "string",
            "title": "Model Cache Size",
            "description": "Size of the downloaded generation and Demucs stem separation models, human-readable."
          },
          "data_folder": {
            "type": "string",
            "title": "Data Folder",
            "description": "Data folder in use."
          },
          "default_data_folder": {
            "type": "string",
            "title": "Default Data Folder",
            "description": "Platform default data folder."
          },
          "is_custom_folder": {
            "type": "boolean",
            "title": "Is Custom Folder",
            "description": "Whether a custom data folder is configured."
          },
          "folder_unavailable": {
            "type": "boolean",
            "title": "Folder Unavailable",
            "description": "True when the configured custom folder cannot be reached, such as an unplugged drive."
          },
          "unavailable_path": {
            "type": "string",
            "title": "Unavailable Path",
            "description": "The unreachable custom folder; empty otherwise."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "model_cache_size",
          "data_folder",
          "default_data_folder",
          "is_custom_folder",
          "folder_unavailable",
          "unavailable_path"
        ],
        "title": "CacheInfoResponse"
      },
      "CancelResponse": {
        "properties": {
          "cancelled": {
            "type": "boolean",
            "title": "Cancelled",
            "description": "True when something was running and has been told to stop."
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason",
            "description": "Why nothing was cancelled."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "cancelled"
        ],
        "title": "CancelResponse"
      },
      "CaptionResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the language model produced output."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Failure reason when success is false."
          },
          "caption": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Caption",
            "description": "Rewritten caption."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success"
        ],
        "title": "CaptionResponse"
      },
      "CatalogEntry": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "Model identifier used when downloading or selecting."
          },
          "downloaded": {
            "type": "boolean",
            "title": "Downloaded",
            "description": "Whether the model is already on disk."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "id",
          "downloaded"
        ],
        "title": "CatalogEntry"
      },
      "ClearAllResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the data was deleted."
          },
          "needs_restart": {
            "type": "boolean",
            "title": "Needs Restart",
            "description": "Always true. The caller restarts the app; the API does not close the window."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success",
          "needs_restart"
        ],
        "title": "ClearAllResponse"
      },
      "ClearCacheResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Always true."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "What was done, for showing to the user."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "title": "ClearCacheResponse"
      },
      "DataFolderRequest": {
        "properties": {
          "path": {
            "type": "string",
            "title": "Path",
            "description": "Absolute path of the folder on the machine running the app. Empty clears a custom location when setting it.",
            "examples": [
              "D:\\SongCreatorPro"
            ]
          }
        },
        "type": "object",
        "required": [
          "path"
        ],
        "title": "DataFolderRequest"
      },
      "DataFolderResponse": {
        "properties": {
          "custom_path": {
            "type": "string",
            "title": "Custom Path",
            "description": "Configured custom location, empty when using the default."
          },
          "default_path": {
            "type": "string",
            "title": "Default Path",
            "description": "Platform default location."
          },
          "effective_path": {
            "type": "string",
            "title": "Effective Path",
            "description": "Location actually in use."
          },
          "is_custom": {
            "type": "boolean",
            "title": "Is Custom",
            "description": "Whether a custom location is in effect."
          },
          "unavailable": {
            "type": "boolean",
            "title": "Unavailable",
            "description": "True when a configured custom location is missing, such as an unplugged drive."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "custom_path",
          "default_path",
          "effective_path",
          "is_custom",
          "unavailable"
        ],
        "title": "DataFolderResponse"
      },
      "DeleteSampleResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the sample was removed."
          },
          "empty": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Empty",
            "description": "True when that was the last sample and the whole entry was deleted."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success"
        ],
        "title": "DeleteSampleResponse"
      },
      "DownloadStatusResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status",
            "description": "One of `idle`, `downloading`, `complete`, `error`, `cancelled`."
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model",
            "description": "Model currently downloading."
          },
          "message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Message",
            "description": "Progress text, or the failure reason when status is `error`."
          },
          "percent": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Percent",
            "description": "Completion percentage, 0-100."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "status"
        ],
        "title": "DownloadStatusResponse"
      },
      "EditScoreRequest": {
        "properties": {
          "abc": {
            "type": "string",
            "title": "Abc",
            "description": "A YuE2 score in ABC notation.",
            "examples": [
              "X:1\nT:\nM:4/4\nL:1/16\nQ:1/4=88\nV: Vocal clef=treble name=\"Vocal Melody\" snm=\"Vocal\"\nV: Ins clef=treble name=\"Ins Melody\" snm=\"Inst.\"\nK:C\n% verse\nV: Vocal\n\"C\"E2G2A2G2E2D2C4|\"G\"D2E2G2E2D2C2D4|\"Am\"E2G2A2c2B2A2G4|\"F\"F2E2D2E2G2E2C4|\nV: Ins\nZ4|\n% chorus\nV: Vocal\n\"C\"G2A2c2B2A2G2E4|\"F\"F2A2G2E2D2E2G4|\"G\"A2c2B2A2G2E2D4|\"C\"E2G2A2G2E2D2C4|\nV: Ins\nZ4|\n"
            ]
          },
          "lyrics": {
            "type": "string",
            "title": "Lyrics",
            "description": "The lyrics paired with the score, edited along with it. May be empty.",
            "default": "",
            "examples": [
              "[Verse]\nNeon fades along the lane\n\n[Chorus]\nLet the day come into view\n"
            ]
          },
          "edit": {
            "additionalProperties": true,
            "type": "object",
            "title": "Edit",
            "description": "The one change to apply. `op` is `duplicate`, `delete`, `move`, `set_chord`, `transpose` or `set_tempo`; the operation description lists the fields each takes.",
            "examples": [
              {
                "op": "transpose",
                "semitones": 2
              }
            ]
          }
        },
        "type": "object",
        "required": [
          "abc",
          "edit"
        ],
        "title": "EditScoreRequest"
      },
      "EditScoreResponse": {
        "properties": {
          "ok": {
            "type": "boolean",
            "title": "Ok",
            "description": "Whether the change was applied."
          },
          "text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Text",
            "description": "The whole score after the change, with LF line endings."
          },
          "lyrics": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics",
            "description": "The lyrics after the change."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Why the change was refused. Nothing changes when it is."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "ok"
        ],
        "title": "EditScoreResponse"
      },
      "EngineCatalogResponse": {
        "properties": {
          "engines": {
            "items": {
              "$ref": "#/components/schemas/EngineEntry"
            },
            "type": "array",
            "title": "Engines",
            "description": "Every generation engine with availability and download state."
          },
          "active_engine": {
            "type": "string",
            "title": "Active Engine",
            "description": "Engine generation uses when a request does not name one: the saved choice, or `acestep` when that is unavailable."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "engines",
          "active_engine"
        ],
        "title": "EngineCatalogResponse"
      },
      "EngineEntry": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "Engine id: `acestep` or `yue2`."
          },
          "display_name": {
            "type": "string",
            "title": "Display Name",
            "description": "Name shown in the picker."
          },
          "available": {
            "type": "boolean",
            "title": "Available",
            "description": "Whether this hardware can run the engine."
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason",
            "description": "Why it is unavailable."
          },
          "downloaded": {
            "type": "boolean",
            "title": "Downloaded",
            "description": "Whether its weights are present and verified."
          },
          "fp8_supported": {
            "type": "boolean",
            "title": "Fp8 Supported",
            "description": "Whether the FP8 low-VRAM mode is offered."
          },
          "cover_tools_downloaded": {
            "type": "boolean",
            "title": "Cover Tools Downloaded",
            "description": "Whether the engine's cover tools add-on is present and verified."
          },
          "cover_tools_download_size_gb": {
            "type": "number",
            "title": "Cover Tools Download Size Gb",
            "description": "Download size of the cover tools add-on in GB, including the lyrics transcriber when it is missing; 0 when the engine has none."
          },
          "lyrics_transcriber_downloaded": {
            "type": "boolean",
            "title": "Lyrics Transcriber Downloaded",
            "description": "Whether the lyrics transcriber add-on is present and verified. It serves Analyze on every engine."
          },
          "lyrics_transcriber_download_size_gb": {
            "type": "number",
            "title": "Lyrics Transcriber Download Size Gb",
            "description": "Download size of the lyrics transcriber add-on in GB."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "id",
          "display_name",
          "available",
          "downloaded",
          "fp8_supported",
          "cover_tools_downloaded",
          "cover_tools_download_size_gb",
          "lyrics_transcriber_downloaded",
          "lyrics_transcriber_download_size_gb"
        ],
        "title": "EngineEntry"
      },
      "EnhanceRequest": {
        "properties": {
          "caption": {
            "type": "string",
            "title": "Caption",
            "description": "Style caption. Both enhance routes run the same language-model pass, which returns a rewritten caption and lyrics.",
            "default": "",
            "examples": [
              "lofi hip hop, rainy"
            ]
          },
          "lyrics": {
            "type": "string",
            "title": "Lyrics",
            "description": "Lyrics with section tags such as `[Verse]`. May be empty.",
            "default": "",
            "examples": [
              "[Verse]\nRain on the window, coffee gone cold"
            ]
          }
        },
        "type": "object",
        "title": "EnhanceRequest"
      },
      "ErrorDetail": {
        "properties": {
          "detail": {
            "type": "string",
            "title": "Detail",
            "description": "What went wrong and, where useful, how to proceed."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "detail"
        ],
        "title": "ErrorDetail"
      },
      "ExtractGroupResponse": {
        "properties": {
          "found": {
            "type": "boolean",
            "title": "Found",
            "description": "Whether a prior extraction for this source exists."
          },
          "history_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "History Id",
            "description": "History entry holding the existing extraction."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "found"
        ],
        "title": "ExtractGroupResponse"
      },
      "GenerateLyricsRequest": {
        "properties": {
          "query": {
            "type": "string",
            "title": "Query",
            "description": "Free-text brief for the song. Empty asks for a random one.",
            "examples": [
              "a hopeful song about leaving a small town at dawn"
            ]
          },
          "vocal_language": {
            "type": "string",
            "title": "Vocal Language",
            "description": "Language code for the lyrics, such as `en` or `ja`. Empty lets the model choose.",
            "default": "",
            "examples": [
              "en"
            ]
          }
        },
        "type": "object",
        "required": [
          "query"
        ],
        "title": "GenerateLyricsRequest"
      },
      "GenerateProgressResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status",
            "description": "One of `idle`, `generating`, `complete`, `error`. Poll until `complete`."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Current step."
          },
          "percent": {
            "type": "integer",
            "title": "Percent",
            "description": "Completion percentage, 0-100."
          },
          "step": {
            "type": "integer",
            "title": "Step",
            "description": "Current diffusion step."
          },
          "total_steps": {
            "type": "integer",
            "title": "Total Steps",
            "description": "Total diffusion steps for this run."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "status",
          "message",
          "percent",
          "step",
          "total_steps"
        ],
        "title": "GenerateProgressResponse"
      },
      "GenerateResultResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the generation produced audio."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Failure reason when success is false."
          },
          "audio_paths": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Audio Paths",
            "description": "Absolute paths to the generated files. Fetch them via /api/v1/audio/download."
          },
          "seed": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Seed",
            "description": "Seed used, for reproducing the run."
          },
          "generation_info": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Generation Info",
            "description": "Free-text summary of the parameters used."
          },
          "duration": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration",
            "description": "Track length in seconds."
          },
          "bpm": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bpm",
            "description": "Detected or requested tempo."
          },
          "sample_seeds": {
            "anyOf": [
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "string"
                    }
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sample Seeds",
            "description": "The seed of each file in `audio_paths`, in the same order."
          },
          "sample_codes": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sample Codes",
            "description": "ACE-Step: the audio codes behind each file in `audio_paths`. Send one back as `audio_codes` to retake that song."
          },
          "caption": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Caption",
            "description": "The style caption the songs were made from, after any language-model rewrite."
          },
          "lyrics": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics",
            "description": "The lyrics the songs were made from, after any language-model rewrite."
          },
          "key_scale": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Scale",
            "description": "ACE-Step: the key used."
          },
          "time_signature": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Time Signature",
            "description": "ACE-Step: the time signature used."
          },
          "vocal_language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vocal Language",
            "description": "ACE-Step: the vocal language used."
          },
          "warnings": {
            "anyOf": [
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Warnings",
            "description": "One entry per file in `audio_paths`: why that song may differ from the request, such as being cut short, or null when there is nothing to say about it. Absent when no song has a warning."
          },
          "engine": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Engine",
            "description": "`yue2` for a YuE2 result; absent for ACE-Step."
          },
          "planning": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Planning",
            "description": "YuE2: the planning mode used."
          },
          "scores": {
            "anyOf": [
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scores",
            "description": "YuE2: the ABC score behind each file in `audio_paths`, or null where none was planned. Send one back as `yue2_abc` to re-render it."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success",
          "audio_paths"
        ],
        "title": "GenerateResultResponse"
      },
      "GenerationStartRequest": {
        "properties": {
          "task_type": {
            "type": "string",
            "title": "Task Type",
            "description": "Mode: `text2music`, `cover` (restyle a source track), `repaint` (regenerate a region), `extract` (isolate one part), `complete` (add parts to a track) or `demucs` (stem separation). YuE2 runs `text2music` and `cover` only.",
            "default": "text2music",
            "examples": [
              "text2music"
            ]
          },
          "prompt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Prompt",
            "description": "Style caption: genre, instruments, mood. Required by YuE2. `extract` ignores it and uses `track_name`.",
            "examples": [
              "lofi hip hop, mellow piano, vinyl crackle, rainy night"
            ]
          },
          "lyrics": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics",
            "description": "Lyrics with section tags such as `[Verse]` and `[Chorus]`. `[Instrumental]` asks for a song without vocals; YuE2 also treats empty lyrics that way, except in a cover, which needs lyrics. `extract` ignores it.",
            "examples": [
              "[Verse]\nRain on the window, coffee gone cold\n\n[Chorus]\nStay a while"
            ]
          },
          "track_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Track Name",
            "description": "`extract` only: the part to isolate, one of `vocals`, `backing_vocals`, `drums`, `bass`, `guitar`, `keyboard`, `percussion`, `strings`, `synth`, `brass`, `woodwinds` or `fx`. Defaults to `vocals`.",
            "examples": [
              "vocals"
            ]
          },
          "track_classes": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Track Classes",
            "description": "`complete` only: the parts to add, from the same names as `track_name`. Empty or unset lets the model choose.",
            "examples": [
              [
                "drums",
                "bass"
              ]
            ]
          },
          "inference_steps": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Inference Steps",
            "description": "ACE-Step diffusion steps. Default 8, which suits turbo models; base and SFT models want 32 or more. YuE2 ignores it; see `yue2_ode_steps`.",
            "examples": [
              8
            ]
          },
          "guidance_scale": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Guidance Scale",
            "description": "ACE-Step classifier-free guidance: higher follows the caption more closely. Default 7.0. Has no effect on turbo models. YuE2 ignores it.",
            "examples": [
              7.0
            ]
          },
          "shift": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Shift",
            "description": "ACE-Step timestep shift. Default 3.0. YuE2 ignores it.",
            "examples": [
              3.0
            ]
          },
          "batch_size": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Batch Size",
            "description": "Number of takes. ACE-Step defaults to 2, capped at `max_batch` from `GET /api/v1/system/gpu`. YuE2 defaults to 1, at most 4.",
            "examples": [
              2
            ]
          },
          "seed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Seed",
            "description": "Random seed; -1 or unset picks one at random. ACE-Step applies it to the first take and randomises the rest; YuE2 uses seed, seed+1, ... for its takes.",
            "examples": [
              -1
            ]
          },
          "audio_duration": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Audio Duration",
            "description": "Track length in seconds; -1 or unset lets the model choose. `duration` is accepted as an alias. ACE-Step only: keep it within `max_duration` from `GET /api/v1/system/gpu`. A `text2music` run with `thinking` on stops there and says so in the result's `warnings`; other runs are not capped and can run out of GPU memory. YuE2 uses `yue2_max_seconds` instead.",
            "examples": [
              60
            ]
          },
          "cover_noise_strength": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cover Noise Strength",
            "description": "ACE-Step `cover` only: where denoising starts, from 0 (pure noise) to 1 (closest to the source audio). Default 0.",
            "examples": [
              0.25
            ]
          },
          "audio_cover_strength": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Audio Cover Strength",
            "description": "ACE-Step `cover` only: how strongly the source audio conditions the result, 0 to 1. Default 1.0; lower values such as 0.2 suit style transfer.",
            "examples": [
              0.15
            ]
          },
          "reference_audio_base64": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reference Audio Base64",
            "description": "Base64-encoded audio file (raw file bytes, no `data:` prefix) used as a style reference. ACE-Step only.",
            "examples": [
              "UklGRiQAAABXQVZFZm10IBAAAAABAAIAgLsAAADuAgAEABAAZGF0YQAAAAA="
            ]
          },
          "src_audio_base64": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Src Audio Base64",
            "description": "Base64-encoded source audio file (raw file bytes, no `data:` prefix), needed by `cover`, `repaint`, `extract`, `complete` and `demucs`. A YuE2 cover renders from `yue2_abc` and keeps this file in history.",
            "examples": [
              "UklGRiQAAABXQVZFZm10IBAAAAABAAIAgLsAAADuAgAEABAAZGF0YQAAAAA="
            ]
          },
          "engine": {
            "type": "string",
            "enum": [
              "acestep",
              "yue2"
            ],
            "description": "Generation engine. `GET /api/v1/engines` reports which are available. Ignored by `demucs`.",
            "default": "acestep",
            "examples": [
              "acestep"
            ]
          },
          "vocal_language": {
            "type": "string",
            "description": "ACE-Step vocal language code, such as `en`, `zh` or `ja`. Empty or unset lets the model detect it.",
            "examples": [
              "en"
            ]
          },
          "instrumental": {
            "type": "boolean",
            "description": "ACE-Step: generate without vocals whatever `lyrics` says.",
            "default": false,
            "examples": [
              false
            ]
          },
          "bpm": {
            "type": "integer",
            "description": "ACE-Step tempo in beats per minute, 30 to 300. Unset lets the model choose.",
            "examples": [
              92
            ]
          },
          "key_scale": {
            "type": "string",
            "description": "ACE-Step key, such as `C major` or `A minor`. Empty or unset lets the model choose.",
            "examples": [
              "A minor"
            ]
          },
          "time_signature": {
            "type": "string",
            "description": "ACE-Step beats per bar: `2` (2/4), `3` (3/4), `4` (4/4) or `6` (6/8). Empty or unset lets the model choose.",
            "examples": [
              "4"
            ]
          },
          "audio_format": {
            "type": "string",
            "enum": [
              "mp3",
              "flac",
              "wav",
              "wav32",
              "opus",
              "aac"
            ],
            "description": "Output file format: `mp3`, `flac`, `wav`, `wav32` (32-bit float WAV, saved as `.wav`), `opus` or `aac`. Applies to ACE-Step, YuE2 and `demucs`. An unknown format is saved as `flac`.",
            "default": "mp3",
            "examples": [
              "mp3"
            ]
          },
          "repainting_start": {
            "type": "number",
            "description": "`repaint` and `complete`: start of the region to regenerate, in seconds.",
            "default": 0.0,
            "examples": [
              30.0
            ]
          },
          "repainting_end": {
            "type": "number",
            "description": "`repaint` and `complete`: end of the region in seconds; -1 or unset means the end of the track.",
            "default": -1,
            "examples": [
              45.0
            ]
          },
          "source_audio_name": {
            "type": "string",
            "description": "File name of the source audio, stored with `extract`, `demucs` and YuE2 cover history entries.",
            "examples": [
              "demo.wav"
            ]
          },
          "source_audio_hash": {
            "type": "string",
            "description": "`extract` and `demucs`: the hash from `POST /api/v1/generation/audio-hash`, stored in history. An `extract` whose hash matches an earlier extraction is added to that history entry.",
            "examples": [
              "3b7f2c9e0d4a"
            ]
          },
          "demucs_model": {
            "type": "string",
            "enum": [
              "htdemucs",
              "htdemucs_ft",
              "htdemucs_6s"
            ],
            "description": "`demucs` only: `htdemucs` (4 stems), `htdemucs_ft` (4 stems, fine-tuned) or `htdemucs_6s` (6 stems, adds guitar and piano). Every model also returns an instrumental stem.",
            "default": "htdemucs",
            "examples": [
              "htdemucs"
            ]
          },
          "yue2_planning": {
            "type": "string",
            "enum": [
              "full",
              "melody",
              "off"
            ],
            "description": "YuE2 score planning: `full` (melody and chords), `melody` (vocal melody only) or `off` (no score). A cover uses `melody` unless `full` is sent; instrumentals and `yue2_abc` need `melody` or `full`.",
            "default": "full",
            "examples": [
              "full"
            ]
          },
          "yue2_ode_steps": {
            "type": "integer",
            "enum": [
              16,
              32
            ],
            "description": "YuE2 render steps. 16 is faster, 32 is the default.",
            "default": 32,
            "examples": [
              32
            ]
          },
          "yue2_max_seconds": {
            "type": "integer",
            "maximum": 360.0,
            "minimum": 30.0,
            "description": "YuE2 length limit in seconds, 30 to 360. Unset uses the model's own limit.",
            "examples": [
              180
            ]
          },
          "yue2_abc": {
            "type": "string",
            "description": "YuE2 score in ABC notation to render, such as the `score` from a `yue2_stage: plan` run or an entry of an earlier result's `scores`. Required for a YuE2 `cover`: get it from `POST /api/v1/generation/analyze-source` with `engine` `yue2`. Outside a cover only one song is made from it.",
            "examples": [
              "X:1\nT:\nM:4/4\nL:1/16\nQ:1/4=88\nV: Vocal clef=treble name=\"Vocal Melody\" snm=\"Vocal\"\nV: Ins clef=treble name=\"Ins Melody\" snm=\"Inst.\"\nK:C\n% verse\nV: Vocal\n\"C\"E2G2A2G2E2D2C4|\"G\"D2E2G2E2D2C2D4|\"Am\"E2G2A2c2B2A2G4|\"F\"F2E2D2E2G2E2C4|\nV: Ins\nZ4|\n% chorus\nV: Vocal\n\"C\"G2A2c2B2A2G2E4|\"F\"F2A2G2E2D2E2G4|\"G\"A2c2B2A2G2E2D4|\"C\"E2G2A2G2E2D2C4|\nV: Ins\nZ4|\n"
            ]
          },
          "yue2_stage": {
            "type": "string",
            "enum": [
              "plan"
            ],
            "description": "`plan` runs YuE2 planning only: the result carries a draft `score` and no audio. Needs `yue2_planning` `full` or `melody`.",
            "examples": [
              "plan"
            ]
          },
          "yue2_guidance": {
            "type": "number",
            "maximum": 3.0,
            "minimum": 1.0,
            "description": "YuE2 guidance scale, 1.0 to 3.0. Unset keeps the model's own.",
            "examples": [
              1.5
            ]
          },
          "yue2_sampling": {
            "type": "object",
            "description": "YuE2 sampling overrides per stage: `abc` (score planning) and `semantic` (audio tokens), each an object with any of `temperature` (0.1 to 2.0), `top_p` (0.1 to 1.0), `top_k` (1 to 500) and `repetition_penalty` (1.0 to 2.0).",
            "examples": [
              {
                "semantic": {
                  "temperature": 0.9,
                  "top_p": 0.93
                }
              }
            ]
          },
          "repaint_mode": {
            "type": "string",
            "enum": [
              "conservative",
              "balanced",
              "aggressive"
            ],
            "description": "ACE-Step `repaint` only: how much of the source is kept around the region. `conservative` keeps the most, `aggressive` regenerates freely and does not splice the result back into the source, `balanced` sits between as set by `repaint_strength`.",
            "default": "balanced",
            "examples": [
              "balanced"
            ]
          },
          "repaint_strength": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "description": "ACE-Step `repaint` with `repaint_mode` `balanced` only: 0 keeps as much of the source as `conservative`, higher values regenerate more freely. Clamped to 0 to 1.",
            "default": 0.5,
            "examples": [
              0.5
            ]
          },
          "chunk_mask_mode": {
            "type": "string",
            "enum": [
              "auto",
              "explicit"
            ],
            "description": "ACE-Step only, meant for `repaint`: `auto` leaves the model to decide which frames to change; `explicit` gives it a hard mask of the `repainting_start` to `repainting_end` region.",
            "default": "auto",
            "examples": [
              "auto"
            ]
          },
          "thinking": {
            "type": "boolean",
            "description": "ACE-Step `text2music` only: the language model writes audio codes that guide the song. Skipped when `audio_codes` is sent or the `init_llm` setting is off.",
            "default": true,
            "examples": [
              true
            ]
          },
          "use_cot_caption": {
            "type": "boolean",
            "description": "ACE-Step `text2music` only: the language model rewrites `prompt` before the song is made.",
            "default": false,
            "examples": [
              false
            ]
          },
          "use_cot_metas": {
            "type": "boolean",
            "description": "ACE-Step `text2music` only: the language model fills in whichever of `bpm`, `key_scale`, `time_signature`, `audio_duration` and `vocal_language` are unset.",
            "default": true,
            "examples": [
              true
            ]
          },
          "lm_cfg_scale": {
            "type": "number",
            "description": "ACE-Step `text2music` with `thinking` on: guidance for the language model's audio codes; higher follows the caption and lyrics more closely. 1.0 turns it off.",
            "default": 2.0,
            "examples": [
              2.0
            ]
          },
          "sampler_mode": {
            "type": "string",
            "enum": [
              "euler",
              "heun"
            ],
            "description": "ACE-Step only: diffusion solver. `heun` runs the model twice per step, so it is slower and more accurate than `euler`.",
            "default": "euler",
            "examples": [
              "euler"
            ]
          },
          "velocity_norm_threshold": {
            "type": "number",
            "description": "ACE-Step only: caps each step's predicted velocity at this multiple of the latent's norm, to curb distortion. 0 turns it off.",
            "default": 0.0,
            "examples": [
              2.0
            ]
          },
          "velocity_ema_factor": {
            "type": "number",
            "description": "ACE-Step only: blends this share of the previous step's velocity into each step, smoothing the result. 0 turns it off.",
            "default": 0.0,
            "examples": [
              0.1
            ]
          },
          "enable_normalization": {
            "type": "boolean",
            "description": "ACE-Step only: peak-normalise each take to `normalization_db`. `complete` applies it to the added parts before mixing them with the source.",
            "default": true,
            "examples": [
              true
            ]
          },
          "normalization_db": {
            "type": "number",
            "description": "ACE-Step only: peak level in dBFS for `enable_normalization`. Values above 0 turn normalisation off.",
            "default": -1.0,
            "examples": [
              -1.0
            ]
          },
          "fade_in_duration": {
            "type": "number",
            "description": "ACE-Step only: linear fade-in at the start of each take, in seconds; 0 means none. `complete` applies it to the added parts before mixing.",
            "default": 0.0,
            "examples": [
              0.5
            ]
          },
          "fade_out_duration": {
            "type": "number",
            "description": "ACE-Step only: linear fade-out at the end of each take, in seconds; 0 means none. `complete` applies it to the added parts before mixing.",
            "default": 0.0,
            "examples": [
              2.0
            ]
          },
          "retake_seed": {
            "type": "string",
            "description": "ACE-Step only: seed of the second noise that `retake_variance` mixes in, or one per take separated by commas; like `seed`, a single value covers the first take only. Empty, -1 or unset picks at random. Ignored while `retake_variance` is 0.",
            "examples": [
              "1234"
            ]
          },
          "retake_variance": {
            "type": "number",
            "description": "ACE-Step only: how far each take's noise moves from `seed` toward `retake_seed`, 0 to 1. 0 changes nothing; 1 is the same as using `retake_seed` as the seed.",
            "default": 0.0,
            "examples": [
              0.2
            ]
          },
          "audio_codes": {
            "type": "string",
            "description": "ACE-Step only: audio code tokens from an earlier result's `sample_codes`, used instead of the language model's so a take can be remade. A `text2music` run with codes renders as a `cover` of them, and they replace `src_audio_base64` when both are sent.",
            "examples": [
              "<|audio_code_1|><|audio_code_2|>"
            ]
          }
        },
        "additionalProperties": true,
        "type": "object",
        "title": "GenerationStartRequest",
        "description": "Generation parameters, forwarded to AceStepBridge.start_generation.\n\nExtra keys are allowed so a new bridge parameter works over HTTP without\na matching change here; unset keys are dropped so the bridge sees exactly\nwhat the caller sent."
      },
      "GpuConfigResponse": {
        "properties": {
          "tier": {
            "type": "string",
            "title": "Tier",
            "description": "Capability tier derived from the detected GPU."
          },
          "gpu_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Gpu Name",
            "description": "Detected GPU name."
          },
          "gpu_memory_gb": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Gpu Memory Gb",
            "description": "Detected VRAM in GB."
          },
          "max_duration": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Duration",
            "description": "Longest track this hardware can generate, in seconds."
          },
          "max_batch": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Batch",
            "description": "Largest batch this hardware can generate."
          },
          "available_devices": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Available Devices",
            "description": "Selectable devices, always including `auto`."
          },
          "xl_forces_memory_savers": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Xl Forces Memory Savers",
            "description": "True on 12-16 GB GPUs, where XL models always load with INT8 quantization and CPU offload regardless of settings. XL LoRAs are skipped there because LoRAs cannot apply to a quantized model."
          },
          "available_lm_models": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Available Lm Models",
            "description": "Language models this hardware can run."
          },
          "recommended_lm_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Recommended Lm Model",
            "description": "Language model chosen by default for this hardware."
          },
          "recommended_backend": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Recommended Backend",
            "description": "Language model inference backend chosen by default: `pt`, `vllm` or `mlx`."
          },
          "is_turbo": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Turbo",
            "description": "Whether the loaded generation model is a Turbo variant, which needs fewer steps."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "tier"
        ],
        "title": "GpuConfigResponse"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "HealthResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Always `ok` when the server is serving."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "status"
        ],
        "title": "HealthResponse"
      },
      "HistoryEntry": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "Entry identifier, used in the other history routes."
          },
          "timestamp": {
            "type": "number",
            "title": "Timestamp",
            "description": "Unix time the entry was created."
          },
          "task_type": {
            "type": "string",
            "title": "Task Type",
            "description": "What produced it: text2music, cover, repaint, extract, complete, or demucs."
          },
          "samples": {
            "items": {
              "$ref": "#/components/schemas/HistorySample"
            },
            "type": "array",
            "title": "Samples",
            "description": "Generated audio in this entry."
          },
          "prompt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Prompt",
            "description": "Caption used."
          },
          "lyrics": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics",
            "description": "Lyrics used."
          },
          "seed": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Seed",
            "description": "Seed of the run, for reproducing it."
          },
          "generation_info": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Generation Info",
            "description": "One-line summary of how it was generated."
          },
          "settings": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Settings",
            "description": "Parameters the run used. Keys vary by engine and task type."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "id",
          "timestamp",
          "task_type",
          "samples"
        ],
        "title": "HistoryEntry"
      },
      "HistorySample": {
        "properties": {
          "filename": {
            "type": "string",
            "title": "Filename",
            "description": "File name within the history entry."
          },
          "path": {
            "type": "string",
            "title": "Path",
            "description": "Absolute path on the server."
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Origin-relative download URL, valid through a tunnel or on a LAN."
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "description": "User-assigned label."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "filename",
          "path",
          "url"
        ],
        "title": "HistorySample"
      },
      "HubDownloadRequest": {
        "properties": {
          "repo_id": {
            "type": "string",
            "title": "Repo Id",
            "description": "The `repo_id` returned by the most recent `POST /api/v1/loras/hub/lookup` for that repo.",
            "examples": [
              "owner/yue2-style-lora"
            ]
          },
          "path": {
            "type": "string",
            "title": "Path",
            "description": "A file `path` from that lookup's `files` list.",
            "examples": [
              "lora.safetensors"
            ]
          }
        },
        "type": "object",
        "required": [
          "repo_id",
          "path"
        ],
        "title": "HubDownloadRequest"
      },
      "HubFile": {
        "properties": {
          "path": {
            "type": "string",
            "title": "Path",
            "description": "File path inside the repo. Pass it to the download route."
          },
          "size_bytes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Size Bytes",
            "description": "File size, when Hugging Face reports it."
          },
          "engine": {
            "type": "string",
            "title": "Engine",
            "description": "Which model the file suits, read from its tensor names: yue2, acestep or unknown."
          },
          "companions": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Companions",
            "description": "Config files downloaded alongside it."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "path",
          "engine"
        ],
        "title": "HubFile"
      },
      "HubImportRequest": {
        "properties": {
          "source": {
            "type": "string",
            "title": "Source",
            "description": "A Hugging Face model link or an `owner/name` repo id. The repo must be public.",
            "examples": [
              "owner/yue2-style-lora"
            ]
          },
          "engine": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Engine",
            "description": "Import adapters for `acestep` or `yue2`. Any other value, or none, uses the saved engine.",
            "examples": [
              "yue2"
            ]
          }
        },
        "type": "object",
        "required": [
          "source"
        ],
        "title": "HubImportRequest"
      },
      "HubLookupRequest": {
        "properties": {
          "source": {
            "type": "string",
            "title": "Source",
            "description": "A Hugging Face model link or an `owner/name` repo id. The repo must be public.",
            "examples": [
              "https://huggingface.co/owner/yue2-style-lora"
            ]
          }
        },
        "type": "object",
        "required": [
          "source"
        ],
        "title": "HubLookupRequest"
      },
      "HubLookupResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the repo was found and holds LoRA files."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Failure reason when success is false."
          },
          "repo_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Repo Id",
            "description": "The repo id the link resolved to."
          },
          "license": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "License",
            "description": "Licence declared on the repo's model card, if any."
          },
          "files": {
            "items": {
              "$ref": "#/components/schemas/HubFile"
            },
            "type": "array",
            "title": "Files",
            "description": "Safetensors files in the repo, up to 20."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success"
        ],
        "title": "HubLookupResponse"
      },
      "HubStatusResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status",
            "description": "idle, downloading, done, error or cancelled."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Progress or result text to show."
          },
          "percent": {
            "type": "integer",
            "title": "Percent",
            "description": "Download progress, 0 to 100."
          },
          "entry": {
            "type": "string",
            "title": "Entry",
            "description": "Name of the added LoRA once the download is done.",
            "default": ""
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "status",
          "message",
          "percent"
        ],
        "title": "HubStatusResponse"
      },
      "InitError": {
        "properties": {
          "cause": {
            "type": "string",
            "title": "Cause",
            "description": "Machine-readable cause: `vram`, `commit_charge`, `disk_space`, `download`, `checkpoint`, `setup`, or `unknown`."
          },
          "title": {
            "type": "string",
            "title": "Title",
            "description": "One-line summary for display."
          },
          "body": {
            "type": "string",
            "title": "Body",
            "description": "Explanation of what went wrong."
          },
          "steps": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Steps",
            "description": "Ordered steps that fix it."
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model",
            "description": "Present when `cause` is `checkpoint` and the damaged model can be downloaded again: pass it to `POST /api/v1/models/download` with `fresh: true`, then reinitialize."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "cause",
          "title",
          "body",
          "steps"
        ],
        "title": "InitError"
      },
      "InitStatusResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status",
            "description": "One of `idle`, `loading`, `ready`, `error`. Poll until `ready`."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Current step, or the error message."
          },
          "percent": {
            "type": "integer",
            "title": "Percent",
            "description": "Completion percentage, 0-100."
          },
          "detail": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Detail",
            "description": "Full error detail including traceback, when status is `error`."
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/InitError"
              },
              {
                "type": "null"
              }
            ],
            "description": "Named cause and remedy, when status is `error`."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "status",
          "message",
          "percent"
        ],
        "title": "InitStatusResponse"
      },
      "InitializeRequest": {
        "properties": {
          "settings": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Settings",
            "description": "Settings to apply before loading, with the same keys as `PUT /api/v1/settings`. Omit to load with the current settings.",
            "examples": [
              {
                "config_path": "acestep-v15-turbo",
                "quantization": false
              }
            ]
          }
        },
        "type": "object",
        "title": "InitializeRequest"
      },
      "InitializeResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether initialization was accepted. Loading continues in the background."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Confirmation, or why it was refused."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "title": "InitializeResponse"
      },
      "LoraBaseModelRequest": {
        "properties": {
          "model_id": {
            "type": "string",
            "title": "Model Id",
            "description": "The base model the adapter was trained against: an ACE-Step model name such as `acestep-v15-turbo`, or `yue2`. Setting it also enables the adapter.",
            "examples": [
              "acestep-v15-turbo"
            ]
          }
        },
        "type": "object",
        "required": [
          "model_id"
        ],
        "title": "LoraBaseModelRequest"
      },
      "LoraEntry": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name",
            "description": "LoRA name, used in the state and base-model routes."
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "Whether it applies to the next generation."
          },
          "scale": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scale",
            "description": "Blend strength."
          },
          "base_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Base Model",
            "description": "Model this adapter was trained against: an ACE-Step model id, or yue2."
          },
          "engine": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Engine",
            "description": "Engine the adapter belongs to: acestep or yue2."
          },
          "branches": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Branches",
            "description": "For YuE2 adapters, which halves of the model it changes: planning, rendering, or both."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "name",
          "enabled"
        ],
        "title": "LoraEntry"
      },
      "LoraListResponse": {
        "properties": {
          "loras": {
            "items": {
              "$ref": "#/components/schemas/LoraEntry"
            },
            "type": "array",
            "title": "Loras",
            "description": "Adapters found in the LoRA folder."
          },
          "quantized": {
            "type": "boolean",
            "title": "Quantized",
            "description": "Whether the loaded ACE-Step model is quantized. LoRAs cannot apply to a quantized model."
          },
          "active_model": {
            "type": "string",
            "title": "Active Model",
            "description": "ACE-Step model loaded now, or the one selected when none is loaded."
          },
          "yue2_quantized": {
            "type": "boolean",
            "title": "Yue2 Quantized",
            "description": "Whether YuE2 runs in FP8, where YuE2 LoRAs cannot apply."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "loras",
          "quantized",
          "active_model",
          "yue2_quantized"
        ],
        "title": "LoraListResponse"
      },
      "LoraStateRequest": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "Turn the adapter on or off. Turning on an adapter whose base model is unknown leaves it off and returns `needs_base_model: true`.",
            "examples": [
              true
            ]
          },
          "scale": {
            "type": "number",
            "title": "Scale",
            "description": "Blend strength, clamped to 0 to 1.",
            "default": 1.0,
            "examples": [
              0.8
            ]
          }
        },
        "type": "object",
        "required": [
          "enabled"
        ],
        "title": "LoraStateRequest"
      },
      "LoraStateResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "False when the selection could not be applied to the loaded model."
          },
          "message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Message",
            "description": "Why it failed."
          },
          "needs_base_model": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Needs Base Model",
            "description": "True when the adapter's base model could not be detected. The adapter stays disabled until one is set with `PUT /api/v1/loras/{name}/base-model`."
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "description": "The adapter that needs a base model."
          },
          "disabled": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Disabled",
            "description": "Other adapters turned off because they target a different base model."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success"
        ],
        "title": "LoraStateResponse"
      },
      "LyricsResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the language model produced output."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Failure reason when success is false."
          },
          "lyrics": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lyrics",
            "description": "Generated or rewritten lyrics."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success"
        ],
        "title": "LyricsResponse"
      },
      "MigrateRequest": {
        "properties": {
          "destination": {
            "type": "string",
            "title": "Destination",
            "description": "Absolute path to move the data folder to, on the machine running the app. Created if missing.",
            "examples": [
              "D:\\SongCreatorPro"
            ]
          }
        },
        "type": "object",
        "required": [
          "destination"
        ],
        "title": "MigrateRequest"
      },
      "MigrateResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the migration started."
          },
          "source_size": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Size",
            "description": "Size of the data being moved, human-readable."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Why it did not start, such as too little free space at the destination."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success"
        ],
        "title": "MigrateResponse"
      },
      "MigrationProgressResponse": {
        "properties": {
          "phase": {
            "type": "string",
            "title": "Phase",
            "description": "One of `idle`, `copying`, `verifying`, `cleaning_up`, `completed`, `error`."
          },
          "percent": {
            "type": "integer",
            "title": "Percent",
            "description": "Completion percentage, 0-100."
          },
          "current_file": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current File",
            "description": "File being copied."
          },
          "copied": {
            "type": "integer",
            "title": "Copied",
            "description": "Files copied so far."
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Files to copy."
          },
          "error": {
            "type": "string",
            "title": "Error",
            "description": "Why the migration failed; empty otherwise."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "phase",
          "percent",
          "copied",
          "total",
          "error"
        ],
        "title": "MigrationProgressResponse"
      },
      "ModelCatalogResponse": {
        "properties": {
          "dit_models": {
            "items": {
              "$ref": "#/components/schemas/CatalogEntry"
            },
            "type": "array",
            "title": "Dit Models",
            "description": "Generation models. XL variants appear on CUDA/ROCm GPUs with 12 GB or more; below 16 GB they run with INT8 and CPU offload forced on."
          },
          "lm_models": {
            "items": {
              "$ref": "#/components/schemas/CatalogEntry"
            },
            "type": "array",
            "title": "Lm Models",
            "description": "Language models used for lyric and caption assistance."
          },
          "yue2_models": {
            "items": {
              "$ref": "#/components/schemas/CatalogEntry"
            },
            "type": "array",
            "title": "Yue2 Models",
            "description": "YuE2 model and its audio codec. Both are needed for YuE2 generation."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "dit_models",
          "lm_models",
          "yue2_models"
        ],
        "title": "ModelCatalogResponse"
      },
      "ModelDownloadRequest": {
        "properties": {
          "model_name": {
            "type": "string",
            "title": "Model Name",
            "description": "The model to download: an ACE-Step model name, `yue2`, or an add-on: `lyrics_asr` (the lyrics transcriber) or `yue2_cover` (the YuE2 cover tools).",
            "examples": [
              "acestep-v15-sft"
            ]
          },
          "fresh": {
            "type": "boolean",
            "title": "Fresh",
            "description": "Delete the model's folder first and download it from scratch. Use it to repair a model whose files are damaged, when `GET /api/v1/model/status` reports `error.cause` `checkpoint` and names it in `error.model`.",
            "default": false,
            "examples": [
              false
            ]
          }
        },
        "type": "object",
        "required": [
          "model_name"
        ],
        "title": "ModelDownloadRequest"
      },
      "MoveNoteRequest": {
        "properties": {
          "abc": {
            "type": "string",
            "title": "Abc",
            "description": "A YuE2 score in ABC notation.",
            "examples": [
              "X:1\nT:\nM:4/4\nL:1/16\nQ:1/4=88\nV: Vocal clef=treble name=\"Vocal Melody\" snm=\"Vocal\"\nV: Ins clef=treble name=\"Ins Melody\" snm=\"Inst.\"\nK:C\n% verse\nV: Vocal\n\"C\"E2G2A2G2E2D2C4|\"G\"D2E2G2E2D2C2D4|\"Am\"E2G2A2c2B2A2G4|\"F\"F2E2D2E2G2E2C4|\nV: Ins\nZ4|\n% chorus\nV: Vocal\n\"C\"G2A2c2B2A2G2E4|\"F\"F2A2G2E2D2E2G4|\"G\"A2c2B2A2G2E2D4|\"C\"E2G2A2G2E2D2C4|\nV: Ins\nZ4|\n"
            ]
          },
          "start": {
            "type": "integer",
            "title": "Start",
            "description": "Character offset where the note starts, counted in the score with line endings normalised to LF.",
            "examples": [
              155
            ]
          },
          "end": {
            "type": "integer",
            "title": "End",
            "description": "Character offset just past the note's end, counted the same way.",
            "examples": [
              157
            ]
          },
          "steps": {
            "type": "integer",
            "title": "Steps",
            "description": "Staff steps to move the note: negative moves it up, positive down. 0 returns the score unchanged.",
            "examples": [
              -1
            ]
          }
        },
        "type": "object",
        "required": [
          "abc",
          "start",
          "end",
          "steps"
        ],
        "title": "MoveNoteRequest"
      },
      "MoveNoteResponse": {
        "properties": {
          "ok": {
            "type": "boolean",
            "title": "Ok",
            "description": "Whether the note moved."
          },
          "text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Text",
            "description": "The whole score after the move, with line endings normalised to LF."
          },
          "pitch": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pitch",
            "description": "MIDI pitch of the moved note."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Why the note could not be moved."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "ok"
        ],
        "title": "MoveNoteResponse"
      },
      "PathResponse": {
        "properties": {
          "path": {
            "type": "string",
            "title": "Path",
            "description": "Absolute path on the server. The caller opens it themselves."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "path"
        ],
        "title": "PathResponse"
      },
      "PreferenceRequest": {
        "properties": {
          "value": {
            "title": "Value",
            "description": "Any JSON value to store under the key. Omitted or `null` stores null.",
            "examples": [
              "dark"
            ]
          }
        },
        "type": "object",
        "title": "PreferenceRequest"
      },
      "PreferenceResponse": {
        "properties": {
          "key": {
            "type": "string",
            "title": "Key",
            "description": "The preference key that was read."
          },
          "value": {
            "title": "Value",
            "description": "Stored value, or null when unset."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "key"
        ],
        "title": "PreferenceResponse"
      },
      "RenameSampleRequest": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name",
            "description": "New display label for the sample. The file on disk keeps its name.",
            "examples": [
              "Chorus take 2"
            ]
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "RenameSampleRequest"
      },
      "RestartResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the change was applied."
          },
          "needs_restart": {
            "type": "boolean",
            "title": "Needs Restart",
            "description": "Whether a restart is required for it to take effect."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success",
          "needs_restart"
        ],
        "title": "RestartResponse"
      },
      "ScoreMapBarEntry": {
        "properties": {
          "number": {
            "type": "integer",
            "title": "Number",
            "description": "Bar number across the whole song, from 1."
          },
          "start": {
            "type": "number",
            "title": "Start",
            "description": "When the bar starts, in seconds."
          },
          "rest": {
            "type": "boolean",
            "title": "Rest",
            "description": "Whether the vocal bar is a whole-bar rest, which cannot carry a chord."
          },
          "chords": {
            "items": {
              "$ref": "#/components/schemas/ScoreMapChordEntry"
            },
            "type": "array",
            "title": "Chords",
            "description": "Chord symbols written in this bar, in order."
          },
          "carried": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Carried",
            "description": "The chord still sounding from earlier when the bar has none."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "number",
          "start",
          "rest",
          "chords"
        ],
        "title": "ScoreMapBarEntry"
      },
      "ScoreMapChordEntry": {
        "properties": {
          "symbol": {
            "type": "string",
            "title": "Symbol",
            "description": "Chord symbol as written in the score, such as `Dm7`."
          },
          "offset": {
            "type": "number",
            "title": "Offset",
            "description": "Where the chord starts within its bar, in quarter notes."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "symbol",
          "offset"
        ],
        "title": "ScoreMapChordEntry"
      },
      "ScoreMapLyricEntry": {
        "properties": {
          "index": {
            "type": "integer",
            "title": "Index",
            "description": "Position of the lyric block among the lyrics' tagged blocks."
          },
          "label": {
            "type": "string",
            "title": "Label",
            "description": "The block's tag without brackets."
          },
          "first_line": {
            "type": "string",
            "title": "First Line",
            "description": "The block's first non-empty line."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "index",
          "label",
          "first_line"
        ],
        "title": "ScoreMapLyricEntry"
      },
      "ScoreMapRequest": {
        "properties": {
          "abc": {
            "type": "string",
            "title": "Abc",
            "description": "A YuE2 score in ABC notation.",
            "examples": [
              "X:1\nT:\nM:4/4\nL:1/16\nQ:1/4=88\nV: Vocal clef=treble name=\"Vocal Melody\" snm=\"Vocal\"\nV: Ins clef=treble name=\"Ins Melody\" snm=\"Inst.\"\nK:C\n% verse\nV: Vocal\n\"C\"E2G2A2G2E2D2C4|\"G\"D2E2G2E2D2C2D4|\"Am\"E2G2A2c2B2A2G4|\"F\"F2E2D2E2G2E2C4|\nV: Ins\nZ4|\n% chorus\nV: Vocal\n\"C\"G2A2c2B2A2G2E4|\"F\"F2A2G2E2D2E2G4|\"G\"A2c2B2A2G2E2D4|\"C\"E2G2A2G2E2D2C4|\nV: Ins\nZ4|\n"
            ]
          },
          "lyrics": {
            "type": "string",
            "title": "Lyrics",
            "description": "Lyrics with section tags such as `[Verse]`, paired with the score's sections by label and order. May be empty.",
            "default": "",
            "examples": [
              "[Verse]\nNeon fades along the lane\n\n[Chorus]\nLet the day come into view\n"
            ]
          }
        },
        "type": "object",
        "required": [
          "abc"
        ],
        "title": "ScoreMapRequest"
      },
      "ScoreMapResponse": {
        "properties": {
          "ok": {
            "type": "boolean",
            "title": "Ok",
            "description": "Whether the score could be read."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Why the score could not be read."
          },
          "key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key",
            "description": "The score's opening key, such as `Bm`."
          },
          "tempo": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tempo",
            "description": "Quarter-note tempo in BPM."
          },
          "meter": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Meter",
            "description": "The opening time signature, such as `4/4`."
          },
          "seconds": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Seconds",
            "description": "Length of the song at its tempo, in seconds."
          },
          "bars": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bars",
            "description": "Number of bars in the song."
          },
          "has_chords": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Has Chords",
            "description": "Whether the score has any chord symbols."
          },
          "sections": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ScoreMapSectionEntry"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sections",
            "description": "The song's sections in order."
          },
          "unused_lyrics": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Unused Lyrics",
            "description": "Lyric blocks no section is paired with, as `index` and `label`."
          },
          "transpose_options": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Transpose Options",
            "description": "Keys the song can move to, as `semitones` and `key`."
          },
          "key_chords": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Chords",
            "description": "The seven chords built on the key's scale."
          },
          "chord_roots": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Chord Roots",
            "description": "Chord roots offered by the chord picker."
          },
          "chord_qualities": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Chord Qualities",
            "description": "Chord qualities YuE2 supports; an empty string is a major triad."
          },
          "tempo_range": {
            "anyOf": [
              {
                "items": {
                  "type": "integer"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tempo Range",
            "description": "Lowest and highest tempo the map allows."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "ok"
        ],
        "title": "ScoreMapResponse"
      },
      "ScoreMapSectionEntry": {
        "properties": {
          "label": {
            "type": "string",
            "title": "Label",
            "description": "Section name from the score's `% label` comment, or `Song` before the first one."
          },
          "first_bar": {
            "type": "integer",
            "title": "First Bar",
            "description": "Number of the section's first bar."
          },
          "bar_count": {
            "type": "integer",
            "title": "Bar Count",
            "description": "How many bars the section has."
          },
          "start": {
            "type": "number",
            "title": "Start",
            "description": "When the section starts, in seconds."
          },
          "seconds": {
            "type": "number",
            "title": "Seconds",
            "description": "How long the section lasts, in seconds."
          },
          "instrumental": {
            "type": "boolean",
            "title": "Instrumental",
            "description": "Whether every vocal bar is a rest."
          },
          "lyric": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ScoreMapLyricEntry"
              },
              {
                "type": "null"
              }
            ],
            "description": "The lyric block paired with this section."
          },
          "warning": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Warning",
            "description": "Set when a sung section has no matching lyrics."
          },
          "bars": {
            "items": {
              "$ref": "#/components/schemas/ScoreMapBarEntry"
            },
            "type": "array",
            "title": "Bars",
            "description": "The section's bars with their chords."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "label",
          "first_bar",
          "bar_count",
          "start",
          "seconds",
          "instrumental",
          "bars"
        ],
        "title": "ScoreMapSectionEntry"
      },
      "SettingsResponse": {
        "properties": {
          "device": {
            "type": "string",
            "title": "Device",
            "description": "Compute device: `auto`, or one of `available_devices` from `GET /api/v1/system/gpu`."
          },
          "config_path": {
            "type": "string",
            "title": "Config Path",
            "description": "Generation model chosen when the model was last initialised."
          },
          "config_path_custom": {
            "type": "string",
            "title": "Config Path Custom",
            "description": "Model used for `text2music`."
          },
          "config_path_cover": {
            "type": "string",
            "title": "Config Path Cover",
            "description": "Model used for `cover` and `repaint`."
          },
          "config_path_base": {
            "type": "string",
            "title": "Config Path Base",
            "description": "Model used for `extract` and `complete`."
          },
          "lm_model_path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Lm Model Path",
            "description": "Language model used when `init_llm` is true; empty when none is chosen."
          },
          "init_llm": {
            "type": "boolean",
            "title": "Init Llm",
            "description": "Whether generation uses the language model."
          },
          "backend": {
            "type": "string",
            "title": "Backend",
            "description": "Language model inference backend: `pt`, `vllm` or `mlx`."
          },
          "quantization": {
            "type": "boolean",
            "title": "Quantization",
            "description": "Load the generation model with INT8 weight-only quantization."
          },
          "offload_to_cpu": {
            "type": "boolean",
            "title": "Offload To Cpu",
            "description": "Keep models in system RAM while they are not in use, to save VRAM."
          },
          "offload_dit_to_cpu": {
            "type": "boolean",
            "title": "Offload Dit To Cpu",
            "description": "Offload the generation model as well as the language model."
          },
          "compile_model": {
            "type": "boolean",
            "title": "Compile Model",
            "description": "Compile the generation model with torch.compile."
          },
          "use_flash_attention": {
            "type": "boolean",
            "title": "Use Flash Attention",
            "description": "Use flash attention where the GPU supports it."
          },
          "gpu_tier": {
            "type": "string",
            "title": "Gpu Tier",
            "description": "Capability tier the defaults were derived from."
          },
          "yue2_quantization": {
            "type": "string",
            "title": "Yue2 Quantization",
            "description": "YuE2 weight format: `none` or `fp8`."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "device",
          "config_path",
          "config_path_custom",
          "config_path_cover",
          "config_path_base",
          "lm_model_path",
          "init_llm",
          "backend",
          "quantization",
          "offload_to_cpu",
          "offload_dit_to_cpu",
          "compile_model",
          "use_flash_attention",
          "gpu_tier",
          "yue2_quantization"
        ],
        "title": "SettingsResponse"
      },
      "SettingsUpdateRequest": {
        "properties": {
          "settings": {
            "additionalProperties": true,
            "type": "object",
            "title": "Settings",
            "description": "Setting keys and their new values, using the keys returned by `GET /api/v1/settings`. Each key is applied on its own.",
            "examples": [
              {
                "config_path_custom": "acestep-v15-sft",
                "offload_to_cpu": true
              }
            ]
          }
        },
        "type": "object",
        "required": [
          "settings"
        ],
        "title": "SettingsUpdateRequest"
      },
      "SetupOption": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "Backend id to pass to `POST /api/v1/setup/start`: `cuda`, `rocm` or `cpu`."
          },
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Display name."
          },
          "gpu_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Gpu Name",
            "description": "The detected GPU this backend would use, or null for `cpu`."
          },
          "recommended": {
            "type": "boolean",
            "title": "Recommended",
            "description": "True for the one backend setup suggests for this machine."
          },
          "download_size": {
            "type": "string",
            "title": "Download Size",
            "description": "Approximate download size, human-readable."
          },
          "description": {
            "type": "string",
            "title": "Description",
            "description": "What the backend does, or why it is not recommended."
          },
          "available": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Available",
            "description": "Only on `rocm`: false when the AMD GPU was detected but no ROCm build supports it."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "id",
          "name",
          "gpu_name",
          "recommended",
          "download_size",
          "description"
        ],
        "title": "SetupOption"
      },
      "SetupProgressResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status",
            "description": "One of `idle`, `downloading`, `complete`, `error`."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Human-readable progress detail."
          },
          "percent": {
            "type": "integer",
            "title": "Percent",
            "description": "Completion percentage, 0-100."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "status",
          "message",
          "percent"
        ],
        "title": "SetupProgressResponse"
      },
      "SetupResetRequest": {
        "properties": {
          "pending_backend": {
            "type": "string",
            "title": "Pending Backend",
            "description": "Saved with the reset but not used yet: after the restart, choose the backend with `POST /api/v1/setup/start`.",
            "default": "",
            "examples": [
              "cuda"
            ]
          }
        },
        "type": "object",
        "title": "SetupResetRequest"
      },
      "SetupStartRequest": {
        "properties": {
          "backend_id": {
            "type": "string",
            "title": "Backend Id",
            "description": "The backend to install, as an `id` from `GET /api/v1/setup/options`: `cuda`, `rocm` or `cpu`.",
            "examples": [
              "cuda"
            ]
          }
        },
        "type": "object",
        "required": [
          "backend_id"
        ],
        "title": "SetupStartRequest"
      },
      "SetupStatusResponse": {
        "properties": {
          "required": {
            "type": "boolean",
            "title": "Required",
            "description": "True when backend packages are not yet installed."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "required"
        ],
        "title": "SetupStatusResponse"
      },
      "SourceAudioRequest": {
        "properties": {
          "src_audio_base64": {
            "type": "string",
            "title": "Src Audio Base64",
            "description": "Base64-encoded audio file to analyse (raw file bytes, no `data:` prefix).",
            "examples": [
              "UklGRiQAAABXQVZFZm10IBAAAAABAAIAgLsAAADuAgAEABAAZGF0YQAAAAA="
            ]
          },
          "engine": {
            "type": "string",
            "enum": [
              "acestep",
              "yue2"
            ],
            "title": "Engine",
            "description": "`acestep` reports a caption, tempo, key and length for an ACE-Step cover or repaint. `yue2` transcribes the song into the melody score and section-tagged lyrics a YuE2 cover needs; pass the returned `score` as `yue2_abc` and `planning` as `yue2_planning` to `POST /api/v1/generation/start`. `yue2` needs the YuE2 cover tools (`POST /api/v1/models/download` with `yue2_cover`).",
            "default": "acestep",
            "examples": [
              "yue2"
            ]
          },
          "transcribe_lyrics": {
            "type": "boolean",
            "title": "Transcribe Lyrics",
            "description": "Transcribe the sung lyrics. Turn it off to keep lyrics you will write yourself.",
            "default": true,
            "examples": [
              true
            ]
          },
          "keep_chords": {
            "type": "boolean",
            "title": "Keep Chords",
            "description": "`yue2` only: also transcribe the chords into the score, which makes the returned `planning` `full` rather than `melody`.",
            "default": false,
            "examples": [
              false
            ]
          }
        },
        "type": "object",
        "required": [
          "src_audio_base64"
        ],
        "title": "SourceAudioRequest"
      },
      "StartedResponse": {
        "properties": {
          "started": {
            "type": "boolean",
            "title": "Started",
            "description": "Whether the background task was started."
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason",
            "description": "Why it was not started."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "started"
        ],
        "title": "StartedResponse"
      },
      "SuccessResult": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the operation succeeded."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Failure reason when success is false."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "success"
        ],
        "title": "SuccessResult"
      },
      "ValidateAbcRequest": {
        "properties": {
          "abc": {
            "type": "string",
            "title": "Abc",
            "description": "A YuE2 score in ABC notation.",
            "examples": [
              "X:1\nT:\nM:4/4\nL:1/16\nQ:1/4=88\nV: Vocal clef=treble name=\"Vocal Melody\" snm=\"Vocal\"\nV: Ins clef=treble name=\"Ins Melody\" snm=\"Inst.\"\nK:C\n% verse\nV: Vocal\n\"C\"E2G2A2G2E2D2C4|\"G\"D2E2G2E2D2C2D4|\"Am\"E2G2A2c2B2A2G4|\"F\"F2E2D2E2G2E2C4|\nV: Ins\nZ4|\n% chorus\nV: Vocal\n\"C\"G2A2c2B2A2G2E4|\"F\"F2A2G2E2D2E2G4|\"G\"A2c2B2A2G2E2D4|\"C\"E2G2A2G2E2D2C4|\nV: Ins\nZ4|\n"
            ]
          }
        },
        "type": "object",
        "required": [
          "abc"
        ],
        "title": "ValidateAbcRequest"
      },
      "ValidateAbcResponse": {
        "properties": {
          "ok": {
            "type": "boolean",
            "title": "Ok",
            "description": "Whether the score parsed."
          },
          "summary": {
            "type": "string",
            "title": "Summary",
            "description": "One-line description of the parsed score."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Parse error when `ok` is false."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "ok",
          "summary"
        ],
        "title": "ValidateAbcResponse"
      },
      "ValidateFolderResponse": {
        "properties": {
          "ok": {
            "type": "boolean",
            "title": "Ok",
            "description": "Whether the path is usable as a data folder."
          },
          "error": {
            "type": "string",
            "title": "Error",
            "description": "Why it is unusable. Empty when ok is true."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "title": "ValidateFolderResponse"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          },
          "input": {
            "title": "Input"
          },
          "ctx": {
            "type": "object",
            "title": "Context"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      },
      "VersionResponse": {
        "properties": {
          "version": {
            "type": "string",
            "title": "Version",
            "description": "App version from version.txt, or `dev` in a source checkout."
          }
        },
        "additionalProperties": true,
        "type": "object",
        "required": [
          "version"
        ],
        "title": "VersionResponse"
      }
    },
    "securitySchemes": {
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Preferred. Keeps the key out of URLs, logs, and browser history."
      },
      "BearerToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Send the API key as `Authorization: Bearer <key>`."
      },
      "ApiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "api_key",
        "description": "For clients that cannot set headers, such as an `<audio>` element. The key appears in the URL, so it reaches access logs and browser history."
      }
    }
  },
  "tags": [
    {
      "name": "Health",
      "description": "Server health check and app version."
    },
    {
      "name": "System",
      "description": "GPU configuration, available devices, and the active PyTorch backend."
    },
    {
      "name": "Setup",
      "description": "First-run backend installation. Check `GET /api/v1/setup/status`, list options, start, then poll progress. Failures are reported in the body as `success: false`, not as an error status."
    },
    {
      "name": "Settings",
      "description": "App settings and UI preferences."
    },
    {
      "name": "Models",
      "description": "Model catalog and downloads. Models download automatically during generation if missing. Failures are reported in the body as `success: false`, not as an error status."
    },
    {
      "name": "Engines",
      "description": "Generation engines (ACE-Step and YuE2) and the YuE2 score tools: ABC validation, the song map, and score edits. Score failures are reported in the body as `ok: false`, not as an error status."
    },
    {
      "name": "Model",
      "description": "Model lifecycle. **Initialize before generating.** Poll `GET /api/v1/model/status` until ready."
    },
    {
      "name": "Generation",
      "description": "Music generation and stem separation. One at a time; a second start returns 409."
    },
    {
      "name": "Audio",
      "description": "Download generated audio files."
    },
    {
      "name": "History",
      "description": "Generation history. Sample URLs are origin-relative so they work through a tunnel or on a LAN."
    },
    {
      "name": "Lyrics",
      "description": "LLM-backed lyric and caption helpers. Failures are reported in the body as `success: false`, not as an error status."
    },
    {
      "name": "LoRAs",
      "description": "LoRA adapter listing and activation. Failures are reported in the body as `success: false`, not as an error status."
    },
    {
      "name": "Storage",
      "description": "Cache management and the app data folder. Most failures are reported in the body as `success: false`, not as an error status."
    }
  ],
  "security": [
    {
      "ApiKeyHeader": []
    },
    {
      "BearerToken": []
    },
    {
      "ApiKeyQuery": []
    }
  ],
  "servers": [
    {
      "url": "http://127.0.0.1:8200",
      "description": "Song Creator Pro on this computer"
    }
  ]
}
