> ## Documentation Index
> Fetch the complete documentation index at: https://docs.soundpiece.co/llms.txt
> Use this file to discover all available pages before exploring further.

# adapt.auto_duck (submit)

> Submit an auto-duck request.

Returns immediately with `status: processing`. Use the matching GET to
poll for completion, or supply a `callback_url` to receive a webhook.

Mixes a voice over music, turning the music down while the voice speaks so
the speech stays clear. The voice is levelled, the music placed under it,
ducked while speech is detected, and the mix delivered at the requested
loudness: -14 LUFS by default, with peaks kept at or below -1 dBTP true
peak. `loudness` is optional, and `{}` asks for the defaults; it can also
name a preset, such as `podcast` (-16 LUFS) — see [loudness](/loudness).
The `ready` output reports the loudness measured on the delivered mix.

The output is as long as the longer of the two inputs: the shorter one is
padded with silence at its end, and nothing is cut.

`music` and `voice` must be different sources, else a `422` with
`same_source`; two URLs recognisably serving the same file count as the
same source. Each must be fetchable, decodable audio within the supported
format, length and size limits, else a `source_*` error — validated once it
is fetched and decoded, with the error's `source` naming the input that
failed when it is known (see [errors](/errors)).

**Credits cost:** 1 per request, normalisation included. Insufficient
credits returns `402` — see [errors](/errors).



## OpenAPI

````yaml /openapi.json put /v1/adapt.auto_duck
openapi: 3.1.0
info:
  title: Soundpiece API
  description: >

    # Soundpiece API


    The Soundpiece API gives you programmatic access to Soundpiece's audio

    generation, separation, and adaptation capabilities. Generate songs from

    lyrics, separate stems from a mix, cut audio to length — anything you can do

    in the Soundpiece app, you can do over HTTP.


    This is an **RPC-style API**, similar in shape to Slack's or Stripe's APIs.

    Each endpoint is a named action like `create.new_song` or

    `adapt.separate_stems`. There are no resource hierarchies to learn — pick
    the

    action you want and call it.


    ## Getting started


    1. Get your API key from your account dashboard. Each key comes with a
    webhook
       signing secret — save both, they're shown once.
    2. Authenticate with `Authorization: Bearer <your-api-key>`.

    3. Submit work with a `PUT` to the action endpoint. You'll get back a
    response
       with `status: processing`.
    4. Poll the same endpoint with `GET` and `?wait=true` to wait up to 20
    seconds
       for the result, or use webhooks to be notified when work is done.

    ### Example: generate a song


    ```http

    PUT /v1/create.new_song

    Authorization: Bearer <your-api-key>

    Content-Type: application/json


    {
      "idempotency_key": "3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b",
      "lyrics": "I've been driving all night, my hands wet on the wheel",
      "prompt": "Synthwave, melancholic, mid-tempo"
    }

    ```


    You'll get back:


    ```json

    {
      "song": {
        "id": "op_01m3vcs7e0f8rsq32d5sqhmetw",
        "status": "processing",
        "created_at": "2026-10-01T09:30:00Z",
        "idempotency_key": "3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b",
        "lyrics": "I've been driving all night, my hands wet on the wheel",
        "prompt": "Synthwave, melancholic, mid-tempo",
        "n_variations": 1,
        "outputs": null,
        "error": null
      }
    }

    ```


    Poll with `GET
    /v1/create.new_song?id=op_01m3vcs7e0f8rsq32d5sqhmetw&wait=true` until
    `status` is

    `ready` (`outputs` populated) or `failed` (`error` populated).


    ## Method shapes


    Each method is either a *command* (writes state) or a *query* (reads state).


    | Kind | Verb | Body | Notes |

    |---|---|---|---|

    | Command (idempotent) | `PUT` | JSON | Used to submit work. Include an
    `idempotency_key` to retry safely. |

    | Query | `GET` | none | Used to poll for operation state. |


    Responses are JSON unless otherwise noted.


    ## Authentication


    All endpoints require an API key passed as a Bearer token:


    ```http

    Authorization: Bearer <your-api-key>

    ```


    Keys start with the prefix `spk_` — the prefix is part of the key, so use
    the

    value exactly as the dashboard shows it. Keep keys secret — anyone with your

    key can use your account.


    You can manage keys in your account dashboard: create new ones, list
    existing

    ones, revoke compromised ones. **The key value and webhook signing secret
    are

    shown once at creation** — save them somewhere safe.


    ## Idempotency


    Every `PUT` request takes an `idempotency_key` field — a UUID you choose. If

    you send the same request twice with the same key, we return the original

    response without doing the work again. This is the safe way to retry over an

    unreliable network.


    The key is also echoed back in every response and webhook delivery, so you

    can correlate work end-to-end on your side without keeping a
    request-id-to-state

    map.


    ## Operation status lifecycle


    Every operation moves through three statuses:


    - **`processing`** — submitted; we're working on it. `output`/`outputs` and
      `error` are both `null`.
    - **`ready`** — done. The `output` (or `outputs`) field is populated.

    - **`failed`** — something went wrong. The `error` field is populated with a
      `code` and `message`.

    `output`/`outputs` and `error` are mutually exclusive — exactly one or the

    other is populated when the operation terminates.


    ## Polling vs webhooks


    Two ways to find out when an operation is done:


    **Polling** — call the same endpoint with `GET` and an `id`. Add
    `?wait=true`

    to long-poll for up to 20 seconds. Repeat if you get back `processing`.


    **Webhooks** — supply a `callback_url` in the original `PUT` request. We

    `POST` the final response to that URL when the operation reaches `ready` or

    `failed`. See the *Webhooks* section below for signature verification.


    **Polling is canonical.** Webhooks are a best-effort latency optimisation;
    if

    you didn't receive one within a reasonable window, fall back to polling.

    Don't rely on webhook receipt as proof of operation state.


    ## Downloads


    When an operation is `ready`, each output carries a signed URL you can use
    to

    download the audio as a FLAC file (44.1 kHz). These URLs are time-limited;

    check the `expires_at` field on each output. If a URL has expired, call the

    matching `get` endpoint again — we'll generate a fresh one.


    Don't cache the URL itself; it's signed against a short window. Do cache the

    audio you downloaded if you need to reuse it.


    ## Webhooks


    If you supply a `callback_url` in a `PUT` request, we'll `POST` the final

    response to that URL when the operation reaches `ready` or `failed`. The

    payload is the same body you'd get from polling, e.g.:


    ```json

    {
      "song": { "...the same DTO you'd get from polling..." }
    }

    ```


    We sign every webhook so you can verify it came from us. Each delivery

    includes these headers (following the [Standard
    Webhooks](https://www.standardwebhooks.com/)

    spec):


    - `webhook-id` — a stable id for this event. Retries reuse the same id, so
      consumers can dedupe.
    - `webhook-timestamp` — Unix seconds when we first attempted delivery.

    - `webhook-signature` — `v1,<base64(HMAC-SHA256(secret,
    "<id>.<timestamp>.<body>"))>`.
      Multiple signatures are space-separated during secret rotation.
    - `webhook-type` — what happened: the endpoint name plus `.ready` or
      `.failed`, e.g. `create.new_song.ready`. Lets you route an event without
      parsing its body. It is not covered by the signature (which is over the
      id, timestamp and body), so treat it as a routing hint and trust the
      verified body.

    Verify by computing the HMAC with your signing secret and comparing in

    constant time. Reject the request if the signature doesn't match, or if the

    timestamp is more than 5 minutes from the current time.


    We retry failed deliveries with exponential backoff. `5xx` responses and

    connection errors get retried; `4xx` responses (other than `429`) fail

    immediately — fix your endpoint and we'll deliver the next one.


    ## Errors


    When an operation itself fails (e.g. your prompt was rejected by our content

    policy), the response has `status: "failed"` with a populated `error`:


    ```json

    {
      "code": "tos_violation",
      "message": "The request was rejected by our content policy."
    }

    ```


    HTTP-level errors (`4xx` / `5xx`) return a JSON body with a `detail` field —

    either a string message, or a list of `{loc, msg, type}` entries pinpointing

    which field of the request body failed validation. `5xx` responses on `PUT`

    endpoints are safely retryable — the same `idempotency_key` will land at

    most once.


    ## Versioning


    We avoid breaking changes to request and response shapes. New fields will

    appear on responses additively; deprecated fields will be marked as such
    with

    notice before removal. If an unavoidable breaking change is ever needed, it

    will be on a versioned URL path so existing clients keep working.
  version: 0.1.0
servers:
  - url: https://api.soundpiece.co
    description: Production
security:
  - Bearer: []
tags:
  - name: Create
    description: >

      Generate new audio from a prompt, reference track, or lyrics.


      Each endpoint follows the same pattern: `PUT` to submit work, `GET` to
      poll.

      The `PUT` returns immediately with `status: processing`; the `GET` returns
      the

      same DTO with updated status until it reaches `ready` or `failed`.


      Generation can take anywhere from a few seconds to a minute or so
      depending

      on length and current capacity. Use `?wait=true` on the `GET` to long-poll

      for up to 20 seconds, or supply a `callback_url` on the `PUT` to be
      notified.
  - name: Adapt
    description: >

      Transform existing audio — separate stems, cut to a target duration,
      normalise

      to a target loudness (in LUFS, or by a named preset such as `podcast`),
      mix a

      voice over music with the music turned down while the voice speaks.


      These endpoints take their audio inputs as URLs (see the `AudioSource`
      schema)

      and produce a derived output. The same async-status pattern as `create.*`

      applies.
paths:
  /v1/adapt.auto_duck:
    put:
      tags:
        - Adapt
      summary: adapt.auto_duck (submit)
      description: >-
        Submit an auto-duck request.


        Returns immediately with `status: processing`. Use the matching GET to

        poll for completion, or supply a `callback_url` to receive a webhook.


        Mixes a voice over music, turning the music down while the voice speaks
        so

        the speech stays clear. The voice is levelled, the music placed under
        it,

        ducked while speech is detected, and the mix delivered at the requested

        loudness: -14 LUFS by default, with peaks kept at or below -1 dBTP true

        peak. `loudness` is optional, and `{}` asks for the defaults; it can
        also

        name a preset, such as `podcast` (-16 LUFS) — see [loudness](/loudness).

        The `ready` output reports the loudness measured on the delivered mix.


        The output is as long as the longer of the two inputs: the shorter one
        is

        padded with silence at its end, and nothing is cut.


        `music` and `voice` must be different sources, else a `422` with

        `same_source`; two URLs recognisably serving the same file count as the

        same source. Each must be fetchable, decodable audio within the
        supported

        format, length and size limits, else a `source_*` error — validated once
        it

        is fetched and decoded, with the error's `source` naming the input that

        failed when it is known (see [errors](/errors)).


        **Credits cost:** 1 per request, normalisation included. Insufficient

        credits returns `402` — see [errors](/errors).
      operationId: adapt.auto_duck
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AdaptAutoDuckRequest'
            examples:
              Defaults:
                value:
                  idempotency_key: 3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b
                  music:
                    url: https://example.com/audio/music.mp3
                  voice:
                    url: https://example.com/audio/voiceover.mp3
              Podcast preset:
                value:
                  idempotency_key: 3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b
                  music:
                    url: https://example.com/audio/music.mp3
                  voice:
                    url: https://example.com/audio/voiceover.mp3
                  loudness:
                    preset: podcast
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdaptAutoDuckResponse'
              examples:
                Just submitted:
                  value:
                    ducked_audio:
                      id: op_01m3vcs7e0f8rsq32d5sqhmetw
                      status: processing
                      created_at: '2026-10-01T09:30:00Z'
                      idempotency_key: 3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b
                      loudness:
                        target_lufs: -14
                        allow_compression: true
                      output: null
                      error: null
                Ready:
                  value:
                    ducked_audio:
                      id: op_01m3vcs7e0f8rsq32d5sqhmetw
                      status: ready
                      created_at: '2026-10-01T09:30:00Z'
                      idempotency_key: 3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b
                      loudness:
                        target_lufs: -14
                        allow_compression: true
                      output:
                        url: >-
                          https://example.com/downloads/ducked.flac?expires=1790847972&signature=9f3c2a7e5b1d4c8a
                        expires_at: '2026-10-01T09:46:12Z'
                        duration: 62.4
                        loudness:
                          lufs: -14
                          true_peak_dbtp: -1.3
                          compressed: false
                      error: null
                Failed:
                  value:
                    ducked_audio:
                      id: op_01m3vcs7e0f8rsq32d5sqhmetw
                      status: failed
                      created_at: '2026-10-01T09:30:00Z'
                      idempotency_key: 3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b
                      loudness:
                        target_lufs: -14
                        allow_compression: true
                      output: null
                      error:
                        code: source_too_short
                        message: >-
                          The source audio is shorter than this operation
                          allows.
                        source: voice
        '401':
          description: The API key is missing or isn't valid.
          content:
            application/json:
              example:
                detail: not_authenticated
              schema:
                $ref: '#/components/schemas/NotAuthenticated'
        '402':
          description: >-
            The account doesn't have enough credits for this request. Nothing
            was submitted.
          content:
            application/json:
              example:
                detail:
                  type: insufficient_credits
                  msg: You have insufficient credits to perform this action.
              schema:
                $ref: '#/components/schemas/InsufficientCredits'
        '403':
          description: >-
            The API key is valid, but this account doesn't currently have API
            access: for example, the plan that included it has ended. A
            correctly set-up account never gets this, so don't retry: contact
            support.
          content:
            application/json:
              example:
                detail: not_authorized
              schema:
                $ref: '#/components/schemas/NotAuthorized'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
              example:
                detail:
                  - loc:
                      - body
                      - idempotency_key
                    msg: Field required
                    type: missing
        '429':
          description: >-
            Too many requests. Retry after the number of seconds in
            `Retry-After`.
          headers:
            Retry-After:
              description: How many seconds to wait before retrying.
              schema:
                type: integer
          content:
            application/json:
              example:
                detail: Rate limit exceeded; retry in 17 seconds
              schema:
                $ref: '#/components/schemas/RateLimited'
      x-codeSamples:
        - lang: bash
          source: >-
            # A complete program that also waits for the result and downloads
            it:

            # https://docs.soundpiece.co/guides/adapt/auto_duck


            # One key per job: keep it, and send the same key if you retry.

            IDEMPOTENCY_KEY=$(uuidgen)


            curl --request PUT \
              --url https://api.soundpiece.co/v1/adapt.auto_duck \
              --header 'Authorization: Bearer <token>' \
              --header 'Content-Type: application/json' \
              --data @- <<EOF
            {
              "idempotency_key": "$IDEMPOTENCY_KEY",
              "music": {
                "url": "https://example.com/audio/music.mp3"
              },
              "voice": {
                "url": "https://example.com/audio/voiceover.mp3"
              }
            }

            EOF
        - lang: python
          source: >-
            # A complete program that also waits for the result and downloads
            it:

            # https://docs.soundpiece.co/guides/adapt/auto_duck


            import uuid


            import requests


            url = "https://api.soundpiece.co/v1/adapt.auto_duck"


            # One key per job: keep it, and send the same key if you retry.

            idempotency_key = str(uuid.uuid4())


            payload = {
                "idempotency_key": idempotency_key,
                "music": {
                    "url": "https://example.com/audio/music.mp3",
                },
                "voice": {
                    "url": "https://example.com/audio/voiceover.mp3",
                },
            }

            headers = {"Authorization": "Bearer <token>"}


            response = requests.put(url, json=payload, headers=headers,
            timeout=30)


            print(response.json())
        - lang: javascript
          source: >-
            // A complete program that also waits for the result and downloads
            it:

            // https://docs.soundpiece.co/guides/adapt/auto_duck


            import { randomUUID } from "node:crypto";


            // One key per job: keep it, and send the same key if you retry.

            const idempotencyKey = randomUUID();


            const response = await
            fetch("https://api.soundpiece.co/v1/adapt.auto_duck", {
              method: "PUT",
              headers: {Authorization: "Bearer <token>", "Content-Type": "application/json"},
              body: JSON.stringify({
                idempotency_key: idempotencyKey,
                music: {
                  url: "https://example.com/audio/music.mp3",
                },
                voice: {
                  url: "https://example.com/audio/voiceover.mp3",
                },
              }),
            });


            console.log(await response.json());
components:
  schemas:
    AdaptAutoDuckRequest:
      properties:
        idempotency_key:
          type: string
          format: uuid
          title: Idempotency Key
          description: >-
            A unique UUID you choose. Send the same key to retry safely; we'll
            return the original response without doing the work again.
          examples:
            - 3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b
        callback_url:
          anyOf:
            - type: string
              maxLength: 2048
              minLength: 1
              format: uri
            - type: 'null'
          title: Callback Url
          description: >-
            Optional HTTPS URL we'll POST the final response to when the
            operation reaches `ready` or `failed`. Polling remains the canonical
            source of truth; webhooks are a best-effort latency optimisation.
          examples:
            - https://example.com/webhooks/soundpiece
        music:
          $ref: '#/components/schemas/AudioSource'
          description: >-
            The music to mix the voice over. It is turned down while the voice
            speaks. Must be a different source from `voice`.
          examples:
            - url: https://example.com/audio/music.mp3
        voice:
          $ref: '#/components/schemas/AudioSource'
          description: >-
            The speech to mix over the music. While it is speaking, the music is
            turned down so the voice stays clear.
          examples:
            - url: https://example.com/audio/voiceover.mp3
        loudness:
          oneOf:
            - $ref: '#/components/schemas/LoudnessTarget'
            - $ref: '#/components/schemas/LoudnessPreset'
          title: Loudness
          description: >-
            The loudness to deliver the mix at, given either as `target_lufs` or
            as a named `preset` (`streaming`, `podcast` or `broadcast`), not
            both. Optional: omit it, or send `{}`, for the defaults (-14 LUFS,
            compression allowed). The mix is always delivered normalised, at no
            extra cost. See [loudness](/loudness).
      additionalProperties: false
      type: object
      required:
        - idempotency_key
        - music
        - voice
      title: AdaptAutoDuckRequest
    AdaptAutoDuckResponse:
      properties:
        ducked_audio:
          $ref: '#/components/schemas/DuckedAudio'
      type: object
      required:
        - ducked_audio
      title: AdaptAutoDuckResponse
    NotAuthenticated:
      properties:
        detail:
          type: string
          const: not_authenticated
          title: Detail
          description: >-
            Always `not_authenticated`, whatever the reason, so a key can't be
            probed. Check the `Authorization: Bearer <your-api-key>` header.
      type: object
      required:
        - detail
      title: NotAuthenticated
      description: The API key is missing, malformed, revoked or unknown.
    InsufficientCredits:
      properties:
        detail:
          $ref: '#/components/schemas/InsufficientCreditsDetail'
      type: object
      required:
        - detail
      title: InsufficientCredits
      description: |-
        The account doesn't have enough credits for this request. Nothing was
        submitted and nothing was charged: top up, then retry with the same
        `idempotency_key`.
    NotAuthorized:
      properties:
        detail:
          type: string
          const: not_authorized
          title: Detail
          description: 'Always `not_authorized`. Retrying won''t help: contact support.'
      type: object
      required:
        - detail
      title: NotAuthorized
      description: |-
        The API key is valid, but its account doesn't currently have API access.
        A correctly set-up account never gets this.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    RateLimited:
      properties:
        detail:
          type: string
          title: Detail
          description: Human-readable message.
      type: object
      required:
        - detail
      title: RateLimited
      description: |-
        Too many requests in a short time. Wait for the number of seconds in the
        `Retry-After` header, then retry; a `PUT` retried with the same
        `idempotency_key` never creates the work twice.
    AudioSource:
      properties:
        url:
          type: string
          maxLength: 2048
          minLength: 1
          format: uri
          title: Url
          description: A publicly-accessible HTTPS URL returning audio (wav, mp3, or flac).
      additionalProperties: false
      type: object
      required:
        - url
      title: AudioSource
    LoudnessTarget:
      properties:
        target_lufs:
          type: number
          maximum: -6
          minimum: -30
          title: Target Lufs
          description: >-
            Target integrated loudness in LUFS (EBU R128), between -30 and -6.
            Defaults to -14, the level most streaming services play music back
            at. Peaks are always kept at or below -1 dBTP true peak; that
            ceiling is fixed.
          default: -14
        allow_compression:
          type: boolean
          title: Allow Compression
          description: >-
            What to do when the audio can't reach `target_lufs` by a change of
            level alone without its peaks going over the -1 dBTP ceiling —
            typically very dynamic audio, with loud peaks relative to its
            average level. `true` (the default) gently compresses the dynamics
            to land close to the target. `false` changes the level only,
            stopping at the ceiling: the dynamics are untouched, but the result
            is quieter than the target. Makes no difference for audio that can
            reach the target by a change of level alone.
          default: true
      additionalProperties: false
      type: object
      title: Target
      description: |-
        A target loudness to normalise audio to. Every field has a default, so
        `{}` asks for the defaults: -14 LUFS, compression allowed.
    LoudnessPreset:
      properties:
        preset:
          type: string
          enum:
            - streaming
            - podcast
            - broadcast
          title: Preset
          description: >-
            The destination to normalise for, each standing for a fixed target
            integrated loudness: `streaming` is -14 LUFS, the level most
            streaming services play music back at; `podcast` is -16 LUFS, the
            level podcast platforms recommend; `broadcast` is -23 LUFS, the EBU
            R128 broadcast standard. A preset's value is fixed and never
            changes. Peaks are always kept at or below -1 dBTP true peak.
        allow_compression:
          type: boolean
          title: Allow Compression
          description: >-
            What to do when the audio can't reach `target_lufs` by a change of
            level alone without its peaks going over the -1 dBTP ceiling —
            typically very dynamic audio, with loud peaks relative to its
            average level. `true` (the default) gently compresses the dynamics
            to land close to the target. `false` changes the level only,
            stopping at the ceiling: the dynamics are untouched, but the result
            is quieter than the target. Makes no difference for audio that can
            reach the target by a change of level alone.
          default: true
      additionalProperties: false
      type: object
      required:
        - preset
      title: Preset
      description: >-
        A named loudness preset: a fixed target loudness for a common
        destination,

        asked for by name instead of by number.
    DuckedAudio:
      properties:
        id:
          type: string
          pattern: ^op_[0-9a-z]{26}$
          title: Id
          description: >-
            A unique identifier for an operation, prefixed `op_`. Returned from
            any `PUT` endpoint; pass it to the matching `GET` to poll, or use it
            to correlate webhook deliveries with your records.
          examples:
            - op_01m3vcs7e0f8rsq32d5sqhmetw
        status:
          type: string
          enum:
            - processing
            - ready
            - failed
          title: Status
          description: >-
            Current state of the operation. `processing` means work is in
            flight; `ready` means the result is available (the
            `output`/`outputs` field is populated); `failed` means something
            went wrong (the `error` field is populated).
        created_at:
          type: string
          format: date-time
          title: Created At
          description: When this operation was created (ISO-8601, UTC).
        idempotency_key:
          type: string
          format: uuid
          title: Idempotency Key
          description: >-
            A unique UUID you choose. Send the same key to retry safely; we'll
            return the original response without doing the work again.
          examples:
            - 3f2b8c1e-9d4a-4e7b-b6c5-1a2d3e4f5a6b
        loudness:
          $ref: '#/components/schemas/LoudnessSettings'
          description: >-
            The loudness the mix is delivered at, with any omitted fields filled
            in with their defaults, and the preset's name when one was used.
        output:
          anyOf:
            - $ref: '#/components/schemas/AudioOutput'
            - type: 'null'
          description: Populated when `status` is `ready`.
        error:
          anyOf:
            - $ref: '#/components/schemas/DuckedAudioError'
            - type: 'null'
          description: >-
            Populated when `status` is `failed`. The `code` is a stable
            machine-readable identifier; `message` is a human-readable
            description.
      type: object
      required:
        - id
        - status
        - created_at
        - idempotency_key
        - loudness
      title: DuckedAudio
    InsufficientCreditsDetail:
      properties:
        type:
          type: string
          const: insufficient_credits
          title: Type
          description: 'Stable machine-readable code: safe to branch on.'
        msg:
          type: string
          title: Msg
          description: Human-readable message.
      type: object
      required:
        - type
        - msg
      title: InsufficientCreditsDetail
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    LoudnessSettings:
      properties:
        target_lufs:
          type: number
          title: Target Lufs
          description: >-
            The target integrated loudness in LUFS: the `target_lufs` requested,
            the value of the `preset` requested, or the default of -14.
        allow_compression:
          type: boolean
          title: Allow Compression
          description: >-
            Whether the dynamics may be compressed to reach the target, as
            requested.
        preset:
          type: string
          enum:
            - streaming
            - podcast
            - broadcast
          title: Preset
          description: >-
            Present only when the request named a preset: which one.
            `target_lufs` is then that preset's value.
      type: object
      required:
        - target_lufs
        - allow_compression
      title: LoudnessSettings
      description: >-
        The loudness audio is normalised to, as the operation records it: the

        target in LUFS whichever way it was asked for, and the preset's name
        when

        one was used.
    AudioOutput:
      properties:
        url:
          type: string
          maxLength: 2083
          minLength: 1
          format: uri
          title: Url
          description: >-
            A signed URL to download the audio as a FLAC file (44.1 kHz).
            Time-limited; see `expires_at`. Don't cache the URL itself.
        expires_at:
          type: string
          format: date-time
          title: Expires At
          description: >-
            When the URL stops working (ISO-8601, UTC). Call the matching `get`
            endpoint again to receive a fresh URL.
        duration:
          type: number
          title: Duration
          description: Duration in seconds.
        loudness:
          $ref: '#/components/schemas/OutputLoudness'
          title: Loudness
          description: >-
            Present only when loudness normalisation was requested: what was
            measured on this output. Measured rather than assumed, so it can
            differ from the target when the audio couldn't reach it (see
            `allow_compression`).
      type: object
      required:
        - url
        - expires_at
        - duration
      title: AudioOutput
    DuckedAudioError:
      properties:
        code:
          anyOf:
            - type: string
              enum:
                - internal_error
                - generation_timeout
            - type: string
              enum:
                - source_unreachable
                - source_format_unsupported
                - source_too_short
                - source_too_long
                - source_too_large
          title: Code
          description: >-
            Stable machine-readable error code — safe to branch on. This
            endpoint can only return the codes listed here.
        message:
          type: string
          title: Message
          description: Human-readable error message.
        source:
          type: string
          enum:
            - music
            - voice
          title: Source
          description: >-
            Present when the failing input is known: which of the two inputs a
            `source_*` error concerns, `music` or `voice`. Absent for other
            errors, and for a source error that could not be attributed to one
            input.
      type: object
      required:
        - code
        - message
      title: DuckedAudioError
      description: >-
        Error for `auto_duck` — the source-transform set, plus, when it is
        known,

        which of the two inputs a `source_*` failure concerns. No content-policy

        path, so no `tos_violation`.
    OutputLoudness:
      properties:
        lufs:
          type: number
          title: Lufs
          description: Integrated loudness measured on the delivered audio, in LUFS.
        true_peak_dbtp:
          type: number
          title: True Peak Dbtp
          description: True peak measured on the delivered audio, in dBTP.
        compressed:
          type: boolean
          title: Compressed
          description: >-
            Whether reaching the target meant altering the audio's dynamics.
            `false` means only its level changed.
      type: object
      required:
        - lufs
        - true_peak_dbtp
        - compressed
      title: OutputLoudness
      description: What was measured on a normalised output.
  securitySchemes:
    Bearer:
      type: http
      scheme: bearer

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.