---
title: "Manage line-level sound-effect cues for a table read artifact."
method: POST
path: "/artifacts/{artifactId}/sfx"
tags: ["Artifacts"]
---

# Manage line-level sound-effect cues for a table read artifact.

`POST /artifacts/{artifactId}/sfx`

## Request

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

Mutates timed sound-effect cues on the live read backing a `table_read` artifact. Use `{ op: "add", entryIndex, label, prompt, volume?, triggerOffset?, offsetMs?, generatedDurationS?, enabled? }` to add a cue. Use `{ op: "update", id, ...fields }` to retime, rename, mute, or regenerate a cue. Use `{ op: "remove", id }` to remove a cue. Adding a cue, or updating one with `regenerate: true`, generates its audio: while the project's gate is closed it is refused with 409 `project_precondition_failed` before anything is generated or saved. A retime, rename, mute or removal generates nothing and stays open. This does not create a new artifact revision and does not change share URLs.  Scope: `artifact:publish`. Idempotency-Key is required.

## Headers

- `Idempotency-Key` string, required

## Request body

- SfxManageRequest: Add, update, or remove a timed sound-effect cue on the read backing a `table_read` artifact. `op` defaults to `add`; `update` and `remove` target an existing cue by `id`. Mutating cues does not create a new artifact revision or change share URLs.
  - `op` 'add' | 'update' | 'remove'
  - `entryIndex` integer: Dialogue entry index for add or update operations.
  - `label` string
  - `prompt` string
  - `volume` number
  - `triggerOffset` 'before' | 'with' | 'after'
  - `offsetMs` integer: Millisecond timing nudge relative to the cue trigger.
  - `generatedDurationS` number: Generated cue duration in seconds.
  - `enabled` boolean: false mutes/excludes the cue without deleting it.
  - `regenerate` boolean: For update operations, regenerate cue audio from the revised prompt.
  - `id` string: Cue id for update or remove operations.

## Response `200`

SFX mutation result.

- SfxMutationResponse: Result of adding, updating, or removing a sound-effect cue.
  - `artifactId` string
  - `cue` SfxCue: Timed sound-effect cue on the read backing a table-read artifact.
    - `id` string, required
    - `label` string, required
    - `entryIndex` integer, required
    - `prompt` string, nullable: Sound-effect generation prompt when available.
    - `soundUrl` string, uri, nullable, required
    - `volume` number, nullable
    - `triggerOffset` 'before' | 'with' | 'after': Where the cue fires relative to the target line.
    - `offsetMs` integer: Millisecond timing nudge relative to the trigger placement.
    - `generatedDurationS` number, nullable
    - `isDisabled` boolean: True when the cue is muted/excluded from playback and finalized renders.
    - `enabled` boolean: False when the cue is muted/excluded from playback and finalized renders.
    - `isDraft` boolean, required: True when sound generation has not produced a reusable sound URL yet.
    - `overLine` object, nullable: List only. Set when the cue lands on a spoken line loud enough to cover the words (placed by the read's recording timing when it has one, else a `with` cue over its own line): whose line, how far under the voice its loudest moment sits, and the `suggestedVolume` that keeps the words heard (set it with op: update). Null otherwise, and for an unmeasured, muted or draft cue.
      - `state` 'covers_line', required
      - `entryIndex` integer, required: The spoken line it lands on.
      - `speaker` string, required: That line's character; NARRATOR for narration.
      - `underVoiceDb` number, required: dB its loudest moment sits under the voice (negative: over it).
      - `suggestedVolume` number, required: The volume that puts it back under the words.
      - `sentence` string, required: The plain sentence every surface shows.
  - `removed` boolean
  - `id` string
  - `label` string

## Other responses

- `400`: Request payload failed validation. The error message names the offending field.
- `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)
