---
title: "Generate adaptive soundtrack for a table read artifact."
method: POST
path: "/artifacts/{artifactId}/music"
tags: ["Artifacts"]
---

# Generate adaptive soundtrack for a table read artifact.

`POST /artifacts/{artifactId}/music`

## Request

- Base URL: `https://docs.sleeperhit.studio/api/v1`
- URL: `https://docs.sleeperhit.studio/api/v1/artifacts/{artifactId}/music`
- Auth: HTTP bearer

(Re)generates the per-scene adaptive soundtrack for the read backing this `table_read` artifact, or updates soundtrack direction for the whole screenplay, one scene, or one entry/line when directive fields are provided. No new revision — the artifact id and share URLs stay stable, like a voice recast. Optionally tune how much of the read carries soundtrack via `musicCoveragePercent` (a fraction 0..1 or a whole percent 0..100; clamped into [0,1]). For directive edits, send `{ scope?, mode?, sceneIndex?, entryIndex?, prompt?, summary?, enabled?, weight? }`, e.g. "make scene 2 heavier bass", "mute the cold open", or `mode: "replace"` to overwrite a stale palette when switching scoring styles. To change one scene's music direction field by field, send `{ sceneIndex, direction: { endTransition?, mix?, ducking?, bpm?, density?, brightness?, guidance?, temperature?, topK?, scale?, seed?, instruments?, summary?, enabled? } }`: the same save as the Table Read page's scene console, which drops the scene's rendered bed so the next render plays the new direction. GET returns each scene's direction as `music.sceneDirections`. Full regeneration is async + queued: returns `{ status: "generating" }`. Directive edits return `{ status: "ready" }`. Poll GET /artifacts/{artifactId}/music until `music.status` is `ready`.  Requires `Idempotency-Key`. Scope: `artifact:publish`.

## Headers

- `Idempotency-Key` string, required

## Request body

- MusicGenerateRequest: Soundtrack tuning. Omit the body entirely to (re)generate scene music (defined-clip scripts render durable per-scene beds; realtime scripts regenerate adaptive directions). Provide `musicMode` to switch modes, `sceneIndex` + `clip` to edit one defined clip, `regenerateScenes` to re-render specific clips, or `scope`/`sceneIndex`/`entryIndex` with directive fields for realtime soundtrack direction.
  - `musicMode` 'defined_clips': Switch the script-level music mode. `defined_clips` (the only mode) plays durable per-scene music clips and auto-queues a baseline coverage pass.
  - `clip` object: Defined-clip edit for the scene at `sceneIndex`. Editing `prompt` or `vocals` marks the clip pending (re-render via `regenerateScenes`); `disabled`/`volume`/`playMode` keep a ready clip playable. Vocals are an explicit opt-in — clips render instrumental otherwise.
    - `prompt` string: Music prompt for this scene — instrumentation, texture, tempo.
    - `vocals` boolean: Allow vocals in this scene's clip. Defaults false; only set true when the writer explicitly asks for vocals.
    - `disabled` boolean: Mute this scene's clip without deleting the prompt/audio.
    - `volume` number: Playback volume override (default 0.25).
    - `fadeInMs` integer: Music fade-in for this clip, ms (default ~1500). 0 disables the fade-in.
    - `fadeOutMs` integer: Music fade-out for this clip, ms (default ~2500). 0 disables the fade-out.
    - `playMode` 'once' | 'loop': Playback mode. `once` (default) plays the natural ~30-40s bed a single time; `loop` repeats it to fill the whole scene.
    - `soundUrl` string, uri: Banked/library audio URL on files.sleeperhit.studio. Supplying it adopts the clip as ready without rendering new music.
    - `durationMs` number: Measured duration of banked `soundUrl` audio in milliseconds, used for play-once placement and fades.
    - `anchor` 'start' | 'end': For play-once clips in longer scenes, align the clip to the scene start (default) or scene end (outro themes).
    - `postRollMs` integer: Music-only tail after the final spoken line, in milliseconds. A positive value automatically selects play-once and end anchoring; render extension applies only to the final scene.
  - `regenerateScenes` integer[]: Zero-based scene indexes whose defined clips should re-render with their current prompts.
  - `soundtrackEnabled` boolean: The read's "Scene Soundtrack Active" master switch. `false` silences every scene's music everywhere (live playback, the MP3 and the MP4); banked clips and coverage are kept. Used alone. Free — it never waits on the project gate.
  - `musicCoveragePercent` number: Soundscape coverage: how much of the read carries music. Accepts a fraction (0..1) or a whole percent (0..100); clamped into [0,1]. The same setting as the in-app coverage slider: it keeps the key scenes (opening, finale, the most intense) and silences the rest, saves the percent, and queues clips for kept scenes that have none. 0 silences every scene; banked clips are kept.
  - `scope` 'screenplay' | 'scene' | 'entry': Directive scope. Defaults to `scene` when `sceneIndex` is supplied, `entry` when `entryIndex` is supplied, otherwise `screenplay`.
  - `mode` 'merge' | 'replace': Directive mode. Defaults to `merge`, which appends to the existing weighted prompt palette. Use `replace` to overwrite the targeted palette, e.g. when switching the whole read to a new scoring style.
  - `sceneIndex` integer: Zero-based scene index to update. Required for `scope: "scene"`; optional context for entry-level updates.
  - `entryIndex` integer: Zero-based parsed script entry index for line/beat-level soundtrack steering. Required for `scope: "entry"`.
  - `prompt` string: Optional adaptive soundtrack prompt, e.g. "a single piano tone, held, then released" or "heavier bass pulse, tense low strings".
  - `summary` string: Optional plain-language soundtrack summary.
  - `enabled` boolean: Optional soundtrack toggle. `false` mutes soundtrack for this scope; `true` turns it back on.
  - `weight` number: Optional prompt weight; defaults to 1 and is clamped by the API.
  - `direction` SceneMusicDirectionUpdate: A scene's music direction, field by field: fields left out are kept, `instruments` replaces the palette. Saving drops the scene's rendered bed so the next render plays the new direction. Bounds: bpm 60–180, mix 0–1, ducking 0.1–1, topK 1–100, at most 5 instruments.
    - `enabled` boolean: The scene's music on or off.
    - `endTransition` 'fadeOut' | 'cut': `fadeOut` eases the music out at the scene's end; `cut` stops it hard.
    - `summary` string
    - `instruments` object[]
      - `text` string, required: An instrument, timbre or atmosphere, e.g. "Cello", "Ominous Drone".
      - `weight` number, required
    - `mix` number
    - `ducking` number
    - `bpm` number
    - `density` number
    - `brightness` number
    - `guidance` number
    - `temperature` number
    - `topK` integer
    - `scale` 'SCALE_UNSPECIFIED' | 'C_MAJOR_A_MINOR' | 'D_FLAT_MAJOR_B_FLAT_MINOR' | 'D_MAJOR_B_MINOR' | 'E_FLAT_MAJOR_C_MINOR' | 'E_MAJOR_D_FLAT_MINOR' | 'F_MAJOR_D_MINOR' | 'G_FLAT_MAJOR_E_FLAT_MINOR' | 'G_MAJOR_E_MINOR' | 'A_FLAT_MAJOR_F_MINOR' | 'A_MAJOR_G_FLAT_MINOR' | 'B_FLAT_MAJOR_G_MINOR' | 'B_MAJOR_A_FLAT_MINOR'
    - `seed` integer

## Response `200`

Adaptive soundtrack generation dispatched or scene soundtrack direction updated.

- MusicGenerateResponse: Acknowledgement that adaptive soundtrack (re)generation has been dispatched, or that one scene direction was updated.
  - `artifactId` string, required
  - `status` 'generating' | 'ready' | 'ok', required
  - `musicMode` 'defined_clips': Present when the music mode was switched.
  - `soundtrackEnabled` boolean: Present when the scene soundtrack master switch was set: its value now.
  - `sceneIndexes` integer[]: Present when specific defined clips were queued to re-render.
  - `clip` object: Present when one scene's defined clip was edited — the updated clip record.
  - `coveragePercent` number, nullable: The clamped coverage percent applied (null when none was supplied and none was previously set).
  - `totalScenes` integer: Number of scenes the read was decomposed into.
  - `scope` 'screenplay' | 'scene' | 'entry': Present when a soundtrack directive update was applied.
  - `sceneIndex` integer: Present when a scene-level or resolved entry-level soundtrack update was applied.
  - `entryIndex` integer: Present when an entry-level soundtrack update was applied.
  - `directive` object: Hidden soundtrack directive that was stored for future adaptive-scene regeneration.
  - `adaptiveSceneDirection` object: Present when a concrete scene direction was updated. This is the live theater adaptive scene direction.
  - `sceneDirection` SceneMusicDirection: One scene's music direction.
    - `sceneIndex` integer, required
    - `heading` string, required
    - `enabled` boolean, required: The scene's music is on.
    - `endTransition` 'fadeOut' | 'cut', required: How the music ends at the scene's boundary: `fadeOut` eases it out, `cut` stops it hard.
    - `summary` string, nullable, required: One line on the music's mood.
    - `instruments` object[], required
      - `text` string, required
      - `weight` number, required
    - `mix` number, nullable, required: Music level.
    - `ducking` number, nullable, required: How much of its level the music keeps under dialogue: 1 = no dip, lower dips deeper (say it in percent and dB, e.g. 48% of its level = -6 dB).
    - `bpm` number, nullable, required
    - `density` number, nullable, required
    - `brightness` number, nullable, required
    - `guidance` number, nullable, required
    - `temperature` number, nullable, required
    - `topK` number, nullable, required
    - `scale` string, nullable, required
    - `seed` number, nullable, required

## Other responses

- `401`: Missing, malformed, revoked, or expired API key.
- `403`: API key is valid but lacks the scope, is blocked by IP allowlist, or the account is disabled.
- `404`: The story artifact does not exist or is owned by another account.
- `409`: The artifact is not in a state where this operation is valid yet (e.g. requesting an MP4 render before the share link exists).
- `429`: Rate limit for this API key + IP + route family was exceeded.
- `500`: The API failed unexpectedly. Safe to retry with the same Idempotency-Key.

---

[API](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api.md) · [All operations](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sleeperhit/apis/sleeper-hit-studio-story-api/revisions/4534f5d25540?raw)
