> ## 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.

# New instrumental

> Generate an instrumental from a prompt or a reference track

`create.new_instrumental` makes a full piece of music with no vocals. You describe the sound in words (a `prompt`) or point at a track whose style to follow (a `reference`). Use it for background music, beds for voiceover, hold music, game and app soundtracks.

For a song with sung lyrics, use [`create.new_song`](/guides/create/new_song). For a short clip at an exact length, use [`create.new_sample`](/guides/create/new_sample).

***

## The request

| Field | Required | What it is |
| - | - | - |
| `prompt` | one of these two | A description of the sound, up to 1,024 characters, e.g. `"synthwave, melancholic, mid-tempo"`. |
| `reference` | one of these two | A track whose style to follow: `{"url": "https://..."}`, a public link to a WAV, MP3 or FLAC file. |
| `n_variations` | no | How many different pieces to make from the same request, from 1 to 3. Defaults to 1. |
| `loudness` | no | Normalise every piece to a target loudness, at no extra cost. Leave it out to get them as produced. See [Loudness](/loudness). |
| `idempotency_key` | yes | A UUID that identifies this job. The [reference client](/client) fills it in for you. |
| `callback_url` | no | An HTTPS address to receive a [webhook](/webhooks) when the work is finished. |

Send `prompt` or `reference`, not both.

Every field, with its exact rules: [submit](/api-reference/create/new_instrumental/submit) and [poll](/api-reference/create/new_instrumental/poll) in the API Reference.

***

## Example

This makes an instrumental in the style of a reference track and saves it. It uses the [reference client](/client); save `soundpiece.py` or `soundpiece.mjs` next to it first.

```python instrumental.py theme={null}
import soundpiece

instrumental = soundpiece.run("create.new_instrumental", {
    "reference": {"url": "https://example.com/audio/reference.mp3"},
})

soundpiece.download(instrumental["outputs"][0]["url"], "instrumental.flac")
print("Saved instrumental.flac")
```

```javascript instrumental.mjs theme={null}
import { run, download } from "./soundpiece.mjs";

const instrumental = await run("create.new_instrumental", {
  reference: { url: "https://example.com/audio/reference.mp3" },
});

await download(instrumental.outputs[0].url, "instrumental.flac");
console.log("Saved instrumental.flac");
```

```bash cURL theme={null}
#!/usr/bin/env bash
# Submit, wait and download by hand. Needs curl, jq and uuidgen.
set -euo pipefail
API=https://api.soundpiece.co/v1
AUTH="Authorization: Bearer $SOUNDPIECE_API_KEY"

# 1. Submit. Sending this exact body again (same idempotency_key) is safe.
body=$(jq -n --arg key "$(uuidgen)" '{
  idempotency_key: $key,
  reference: { url: "https://example.com/audio/reference.mp3" }
}')
response=$(curl --silent --show-error --max-time 30 --request PUT "$API/create.new_instrumental" \
  --header "$AUTH" --header "Content-Type: application/json" --data "$body")
result=$(jq -e .instrumental <<<"$response") || { echo "$response"; exit 1; }
id=$(jq -r .id <<<"$result")

# 2. Wait. Each call returns as soon as the work is finished, or after 20 seconds.
while [ "$(jq -r .status <<<"$result")" = processing ]; do
  response=$(curl --silent --show-error --max-time 30 "$API/create.new_instrumental?id=$id&wait=true" \
    --header "$AUTH")
  result=$(jq -e .instrumental <<<"$response") || { echo "$response"; exit 1; }
done

# 3. Download, or show what went wrong.
if [ "$(jq -r .status <<<"$result")" = failed ]; then
  jq .error <<<"$result"
  exit 1
fi
curl --silent --show-error --fail --output instrumental.flac "$(jq -r '.outputs[0].url' <<<"$result")"
echo "Saved instrumental.flac"
```

***

## The result

`run` returns the finished `instrumental` object, with one entry in `outputs` per variation:

```json theme={null}
{
  "id": "op_01ks2q8n3sgy4c0d6e7f9h2j5k",
  "status": "ready",
  "created_at": "2026-10-10T09:15:02Z",
  "idempotency_key": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b",
  "prompt": null,
  "n_variations": 1,
  "outputs": [
    {
      "url": "https://cdn.soundpiece.co/...signed...",
      "expires_at": "2026-10-10T09:31:40Z",
      "duration": 134.8
    }
  ],
  "error": null
}
```

| Field | What it means |
| - | - |
| `prompt` | The prompt you sent, or `null` when you sent a `reference` (as here). The reference URL is never echoed. |
| `n_variations` | How many pieces you asked for. |
| `loudness` | Present only if you asked for normalisation (not in this example). |
| `outputs[].url` | A signed link to one piece, as a FLAC file (44.1 kHz). It needs no API key. |
| `outputs[].expires_at` | When the link stops working. Poll the operation again for a fresh one. |
| `outputs[].duration` | The piece's length in seconds. There is no length setting; to fit a length, cut the result with [`adapt.auto_cut_down`](/guides/adapt/auto_cut_down). |
| `outputs[].loudness` | Present only if you asked for normalisation: `lufs`, `true_peak_dbtp` and `compressed`, measured on that piece. |

***

## Choosing parameters

* **Prompt or reference?** A prompt is quickest: mix genre, mood, tempo and instruments, separated by commas. A reference is better when you have a track whose feel you want to match. To use a prompt, send it in place of `reference`:

  ```json theme={null}
  {
    "prompt": "synthwave, melancholic, mid-tempo",
    "n_variations": 3,
    "loudness": { "preset": "streaming" }
  }
  ```

* **`n_variations`.** Each variation is a different take on the same request. Ask for two or three when you want to choose; each one costs the same as a single piece.

* **Loudness.** Off unless you include the block. Under a voiceover, consider [`adapt.auto_duck`](/guides/adapt/auto_duck) instead, which balances the music against the voice for you. See the [loudness normalisation guide](/guides/adapt/normalise_loudness#choosing-a-target-by-destination) for which target to pick.

***

## Errors

**When you submit** (the request is refused, nothing is charged):

| Status | `type` | Why |
| - | - | - |
| `422` | `string_too_short` / `string_too_long` | `prompt` is empty or over 1,024 characters. |
| `422` | `missing` | Neither `prompt` nor `reference` was sent. |
| `422` | `extra_forbidden` | Both `prompt` and `reference` were sent (or any field the endpoint doesn't know). |
| `422` | `source_too_large` | The reference's server says the file is over 50 MB. (When it doesn't say, the size is checked during processing instead.) |
| `422` | `idempotency_key_reused` | The key was already used for a different endpoint. |
| `402` | `insufficient_credits` | Your balance is below 3 credits per variation. |

**While processing** (the operation finishes as `failed`, with an `error.code`):

| Code | Why |
| - | - |
| `tos_violation` | The prompt or reference was rejected by our content policy. |
| `source_unreachable`, `source_format_unsupported`, `source_too_short`, `source_too_long`, `source_too_large` | Only with a `reference`: it couldn't be fetched, isn't WAV, MP3 or FLAC audio, or is outside the limits below. |
| `internal_error`, `generation_timeout` | Something went wrong on our side. Resubmit with the same idempotency key. |

**Reference limits for this endpoint:** WAV, MP3 or FLAC, from 1 second to 5 minutes long, and at most 50 MB.

See [Errors](/errors) for the response shapes, and for the errors every endpoint can return (`401`, `403`, `429`).

***

## Cost

**3 credits per variation**, so `n_variations: 3` costs 9. Normalisation costs nothing extra. Resending a request with the same idempotency key is not charged again.


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