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

# Suno Music

> Generate songs from a description or your own lyrics with Suno V6. $0.075 per request, $0.15 in Max mode.

`suno-music` generates songs with Suno V6. Describe the song and let the model write it, or send your own lyrics and style tags. The request runs as an asynchronous task, and a finished task can return several tracks. Every track can be the source of a later edit, such as an extension, a cover, or a stem split.

| Property | Value |
| - | - |
| Model ID | `suno-music` |
| Endpoint | `POST /v1/music/generations` (asynchronous task) |
| Group | Suno > Create |
| Input | Text: a song description, or lyrics with style tags |
| Result | Tracks in `result.tracks` with `audio_url` |
| Versions | `v6` (default), `v6-wild`, `v6-mini`, or your own model from `suno-custom-model` |
| Price | \$0.075 per request (7.5 credits); \$0.15 with `max_mode: true` |

Confirm live rates on the [SnapGen models page](https://snapgen.org/models). Failed tasks are not charged.

## Two ways to write a song

<Tabs>
  <Tab title="Description mode">
    Leave `custom` out (or `false`) and describe the song in `prompt`, up to
    3,000 characters. The model writes the lyrics, style, and title.

    ```bash theme={null}
    curl https://api.snapgen.org/v1/music/generations \
      -H "Authorization: Bearer $SNAPGEN_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "suno-music",
        "prompt": "A late-night city lo-fi song with soft piano and rain"
      }'
    ```
  </Tab>

  <Tab title="Custom mode">
    Send `custom: true` with your lyrics in `prompt` (up to 5,000
    characters), the sound in `style`, and a `title`. Custom mode also unlocks
    `max_mode`, a target `duration`, and a Persona.

    ```bash theme={null}
    curl https://api.snapgen.org/v1/music/generations \
      -H "Authorization: Bearer $SNAPGEN_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "suno-music",
        "custom": true,
        "title": "Night Drive",
        "style": "synthwave, female vocal",
        "prompt": "[Verse]\nCity lights are calling me home\n[Chorus]\nWe keep on driving through the night",
        "duration": 120
      }'
    ```

    For an instrumental, send `custom: true` and `instrumental: true`; lyrics
    are then optional.
  </Tab>
</Tabs>

<ParamField body="model" type="string" required>
  Set to `suno-music`.
</ParamField>

<ParamField body="custom" type="boolean" default="false">
  `false` (default) is description mode: `prompt` describes the song. `true` is custom mode: `prompt` holds the lyrics, and `title`, `style`, `negative_tags`, `auto_lyrics`, and `persona_task_id` apply.
</ParamField>

<ParamField body="instrumental" type="boolean" default="false">
  `true` makes an instrumental with no vocals. In custom mode, `prompt` is then optional.
</ParamField>

<ParamField body="version" type="string" default="v6">
  Suno model version: `v6`, `v6-wild`, or `v6-mini`. Omit it when you send `custom_model_task_id`.
</ParamField>

<ParamField body="custom_model_task_id" type="string">
  The `id` of a succeeded [`suno-custom-model`](/api-manual/audio/suno-custom-model) task. Generates with that custom model instead of a public `version`, so don't send `version` or `persona_task_id`.
</ParamField>

<ParamField body="prompt" type="string">
  Description mode: what the song should sound like, up to 3,000 characters. Custom mode: the lyrics, up to 5,000 characters. Required, except for a custom-mode instrumental.
</ParamField>

<ParamField body="title" type="string">
  Track title, up to 80 characters. Applies in custom mode.
</ParamField>

<ParamField body="style" type="string">
  Style tags for custom mode, up to 1,000 characters, for example `synthwave, female vocal`.
</ParamField>

<ParamField body="negative_tags" type="string">
  Styles to avoid, up to 1,000 characters. Applies in custom mode.
</ParamField>

<ParamField body="auto_lyrics" type="boolean">
  `true` rewrites the lyrics you send creatively. Applies in custom mode.
</ParamField>

<ParamField body="persona_task_id" type="string">
  The `id` of a succeeded [`suno-persona`](/api-manual/audio/suno-persona) task. The song is sung with that Persona. Applies in custom mode. Can't be combined with `custom_model_task_id`.
</ParamField>

<ParamField body="vocal_gender" type="string">
  `male` or `female` vocals.
</ParamField>

<ParamField body="style_weight" type="number">
  Style weight, from 0 to 1.
</ParamField>

<ParamField body="weirdness" type="number">
  Creativity, from 0 to 1. Higher values are more experimental.
</ParamField>

<ParamField body="audio_weight" type="number">
  Audio weight, from 0 to 1.
</ParamField>

<ParamField body="variety" type="string">
  Style variation: `off`, `normal`, `high`, `extra`, or `max`. It doesn't turn on Max mode or change the price.
</ParamField>

<ParamField body="max_mode" type="boolean" default="false">
  `true` turns on Suno Max mode and bills twice the request price. Requires `custom: true`.
</ParamField>

<ParamField body="audio_format" type="string">
  Output format: `mp3`, `m4a`, or `wav`. The provider picks one if you omit it.
</ParamField>

<ParamField body="duration" type="integer">
  Target length in seconds, from 10 to 360. The finished track can be shorter or longer. Requires `custom: true`.
</ParamField>

<ParamField body="webhook" type="string">
  Optional public `https` URL that receives one signed event when the task finishes. See [Task webhooks](/api-reference/webhooks).
</ParamField>

<ParamField body="webhook_secret" type="string">
  Required with `webhook`: 16 to 256 characters, used to sign the delivery.
</ParamField>

## Request rules

The gateway checks these before it reserves any balance:

* Without `custom: true`, `prompt` is a description of up to 3,000 characters and is required.
* With `custom: true`, `prompt` holds lyrics of up to 5,000 characters and is required unless `instrumental` is `true`.
* `max_mode` and `duration` require `custom: true`.
* Send either `version` or `custom_model_task_id`, not both.
* `persona_task_id` can't be combined with `custom_model_task_id`.

## Wait for the result

The response is HTTP `202` with a task object and a `Location: /v1/tasks/{id}`
header. Poll [`GET /v1/tasks/{id}`](/api-reference/task-status) every 10 to 20
seconds until `status` is `succeeded` or `failed`, or pass `webhook` to be
notified.

<CodeGroup>
  ```python Python theme={null}
  import json
  import os
  import time
  from urllib.request import Request, urlopen

  API = "https://api.snapgen.org/v1"
  AUTH = {"Authorization": f"Bearer {os.environ['SNAPGEN_API_KEY']}"}

  submit = Request(
      f"{API}/music/generations",
      data=json.dumps({
          "model": "suno-music",
          "prompt": "A late-night city lo-fi song with soft piano and rain",
      }).encode(),
      headers={**AUTH, "Content-Type": "application/json"},
  )
  with urlopen(submit) as response:
      task = json.load(response)

  while task["status"] in ("queued", "processing"):
      time.sleep(15)
      with urlopen(Request(f"{API}/tasks/{task['id']}", headers=AUTH)) as response:
          task = json.load(response)

  if task["status"] != "succeeded":
      raise RuntimeError(task["error"])
  for track in task["result"]["tracks"]:
      print(track["index"], track.get("title"), track.get("audio_url"))
  ```

  ```javascript Node.js theme={null}
  const API = "https://api.snapgen.org/v1";
  const auth = { Authorization: `Bearer ${process.env.SNAPGEN_API_KEY}` };

  const submitted = await fetch(`${API}/music/generations`, {
    method: "POST",
    headers: { ...auth, "Content-Type": "application/json" },
    body: JSON.stringify({
      model: "suno-music",
      prompt: "A late-night city lo-fi song with soft piano and rain",
    }),
  });
  if (!submitted.ok) throw new Error(await submitted.text());
  let task = await submitted.json();

  while (task.status === "queued" || task.status === "processing") {
    await new Promise((resolve) => setTimeout(resolve, 15_000));
    task = await (await fetch(`${API}/tasks/${task.id}`, { headers: auth })).json();
  }
  if (task.status !== "succeeded") throw new Error(JSON.stringify(task.error));
  for (const track of task.result.tracks) {
    console.log(track.index, track.title, track.audio_url);
  }
  ```
</CodeGroup>

## Result

`result.tracks[]` lists every track in its original order, each with its
`index` and `audio_url`, plus `title`, `image_url`, `duration_seconds`,
`lyrics`, and `tags` when the provider returns them. `result.urls` lists the
audio URLs. Keep the task `id` and the track `index`: they're how later
operations find the track.

```json theme={null}
{
  "urls": [
    "https://cdn.example.com/music/rain-lofi-1.mp3",
    "https://cdn.example.com/music/rain-lofi-2.mp3"
  ],
  "tracks": [
    {
      "index": 1,
      "id": "clip_8f3a2c",
      "title": "Rain on the Window",
      "audio_url": "https://cdn.example.com/music/rain-lofi-1.mp3",
      "image_url": "https://cdn.example.com/music/rain-lofi-1.jpg",
      "duration_seconds": 146.2,
      "tags": "lo-fi, soft piano, rain"
    },
    {
      "index": 2,
      "id": "clip_9b4d1e",
      "title": "Rain on the Window",
      "audio_url": "https://cdn.example.com/music/rain-lofi-2.mp3",
      "image_url": "https://cdn.example.com/music/rain-lofi-2.jpg",
      "duration_seconds": 152.8,
      "tags": "lo-fi, soft piano, rain"
    }
  ]
}
```

## Next steps

Pass this task's `id` as `source_task_id`, and a track `index` as
`source_index`, to any Suno edit model:

<CardGroup cols={2}>
  <Card title="Extend a track" icon="forward" href="/api-manual/audio/suno-extend">
    Continue the song from a chosen second, then join the parts with
    `suno-concat`.
  </Card>

  <Card title="Cover in a new style" icon="shuffle" href="/api-manual/audio/suno-cover">
    Re-record the song in another genre or mood.
  </Card>

  <Card title="Split stems" icon="layer-group" href="/api-manual/audio/suno-stems-all">
    Separate vocals, drums, bass, and other stems.
  </Card>

  <Card title="Export files" icon="download" href="/api-manual/audio/suno-download">
    Get MP3, M4A, or WAV files of a track.
  </Card>
</CardGroup>

<Note>
  Result URLs are kept for about 72 hours. Download the files you want to
  keep. See [Music generation tasks](/api-reference/music-generations) for
  task references, webhooks, and errors.
</Note>
