Simple mode generation API

Updated 2026-09-18 · Suno-API team

Endpoint description

Simple mode generation is for turning a one-sentence description into a complete song. The service writes the lyrics, melody, arrangement and vocals from your description.

Endpoint: POST /api/music/create

Billing: Paid, currently ¥0.6 per call by default. Each call usually returns 2 songs; the amount actually charged follows the current back-office price configuration.

Max Mode / Variety: this endpoint supports the optional parameters max_mode and variety (0-4). With max_mode on, this call is billed at 2× the price (¥0.6 → ¥1.2 per call); variety costs nothing extra. What they mean and how to send them is in the "Advanced parameters" section of the New API overview.

Recommended model: suno-v6

Wait times and timeouts (important): this is a synchronous endpoint — the order is only accepted and handed to generation when the response arrives. Measured, most requests return in 1-3 seconds, about 10% take longer than 30 seconds, and the longest is about 230 seconds. Set your client timeout to 300 seconds or more; no response does not mean nothing was generated, and do not retry immediately after a timeout (that duplicates the order and charges again). If the connection dropped, confirm later with GET /api/music/songs. See "Wait times and timeout settings" in the New API overview.

Request parameters

Headers

Parameter Type Required Notes
Authorization string yes Bearer YOUR_API_KEY
Content-Type string yes application/json

Body parameters

Parameter Type Required Default Notes
description string yes - Song description, any language; at most 3000 characters (longer returns 400 and is not charged)
model string no suno-v6 Customer-facing model name: suno-v6, suno-v6-wild or suno-v6-mini
instrumental boolean no false Whether the song is instrumental only
wait_completion boolean no false Whether to wait for generation to finish before responding
references array no - Reference material list, which may carry reference songs / legacy voices / reference images; at most 5 songs, 1 voice and 1 image. See "Reference material references (optional)" below

Request examples

curl -X POST https://www.suno-api.io/api/music/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "suno-v6",
    "description": "an upbeat Mandarin pop song about summer by the sea",
    "instrumental": false,
    "wait_completion": false
  }'

Reference material references (optional)

references is an array that attaches "reference material" to this generation. It is entirely optional (leaving it out behaves exactly as before), and you may attach only one kind or any combination.

Element types

type Required field Optional fields Maximum Notes
song song_id style_prompt, lyrics, duration_s 5 Reference song; song_id comes from the song query and history API and the song must already be completed
voice voice_id - 1 Legacy voice; voice_id comes from the voice clone and generate-with-voice API
image base64 - 1 Reference image; send base64 content in the form data:image/jpeg;base64,...

Rules

Example: two reference songs

curl -X POST https://www.suno-api.io/api/music/create \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "suno-v6",
    "description": "combine these ideas into one song",
    "references": [
      { "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
      { "type": "song", "song_id": "a90438d2-35fc-4443-88f4-56531e6e5d24" }
    ]
  }'

Example: reference song + legacy voice

{
  "model": "suno-v6",
  "description": "sing these ideas with this voice",
  "references": [
    { "type": "song",  "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
    { "type": "voice", "voice_id": "5813cbe1-36f1-414a-a9a8-4d399dfeb292" }
  ]
}

Example: reference song + reference image

{
  "model": "suno-v6",
  "description": "capture the mood of this image",
  "references": [
    { "type": "song",  "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
    { "type": "image", "base64": "data:image/jpeg;base64,/9j/4AAQ..." }
  ]
}

Parameter errors

These cases return HTTP 400, blocked before any billing, so they cost nothing:

Case Error message
More than 5 reference songs references supports at most 5 song references
More than 1 voice references supports at most 1 voice reference
More than 1 reference image references supports at most 1 image reference
Invalid type references[0].type must be one of song, voice, image
Song missing song_id references[0].song_id is required
Song not finished yet references[0].song_id must be a real completed clip
The same song passed twice references[0].song_id is duplicated

The number in references[0] is that element's index in the array, so the failing item is easy to locate.

Response

An array of songs, usually holding 2 tasks or songs.

[
  {
    "song_id": "clip_id",
    "song_title": "Summer Sea Breeze",
    "status": "pending",
    "description": "an upbeat Mandarin pop song about summer by the sea",
    "audio_url": "",
    "cover_url": "",
    "video_url": "",
    "model_version": "suno-v6",
    "generation_type": "generate",
    "created_at": "2026-05-21T10:00:00Z"
  }
]

Accept-receipt mode (optional, recommended for clients that should not hold long connections)

By default this endpoint is synchronous: the response arriving is what means the order was accepted, and measured waits can reach about 230 seconds. If your client should not hold a long connection, turn on accept-receipt mode — either one works:

With it on, the endpoint returns HTTP 202 immediately, meaning only "accepted and queued for generation", while generation continues in the background:

{
  "success": true,
  "data": {
    "request_id": "ac_20260920092714315816800d76fv3nq",
    "status": "queued",
    "accepted_at": 1789896434,
    "pre_consumed_quota": 300000,
    "tasks": [
      { "index": 0, "status": "queued" },
      { "index": 1, "status": "queued" }
    ]
  }
}

The accept stage does not return a song_id. No real song ID exists yet, and neither request_id nor tasks[].index is a song ID — do not save them as song_id. The real song_id appears in the progress query below.

Query the accept progress

Endpoint: GET /api/music/requests/{request_id} (free, authenticated with the same API key)

curl "https://www.suno-api.io/api/music/requests/ac_20260920092714315816800d76fv3nq" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "success": true,
  "data": {
    "request_id": "ac_20260920092714315816800d76fv3nq",
    "status": "processing",
    "tasks": [
      { "index": 0, "status": "processing", "song_id": "f3fa09f5-3d55-4953-826c-0d23f043ec57" },
      { "index": 1, "status": "processing", "song_id": "5fcafe3e-3fae-4d64-8f66-c01bc027b0c3" }
    ]
  }
}

What each status value means:

status Meaning
queued Accepted, not yet tied to specific songs (tasks may be an empty array)
processing Submitted for generation
partial One of the two has completed
completed Both completed, tasks[].song_id is readable
failed Submission failed, the charge has been fully refunded, and error_message gives the reason

Each task also has its own tasks[].status, with the same values as the song query API: pending (submitted, generating), processing, completed, failed. Task items may also carry title, duration and an already registered audio_url; anything missing simply means it is not generated yet.

Once you have the real song_id, continue with the song query API or the download endpoints.

Python example

import time
import requests

BASE = "https://www.suno-api.io"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json"}

accepted = requests.post(
    f"{BASE}/api/music/create",
    headers={**HEADERS, "Idempotency-Key": "your-own-unique-key"},
    json={"description": "an upbeat pop song", "model": "suno-v6", "accept_mode": "async"},
    timeout=300,
).json()["data"]

request_id = accepted["request_id"]
while True:
    time.sleep(5)
    progress = requests.get(
        f"{BASE}/api/music/requests/{request_id}", headers=HEADERS, timeout=60
    ).json()["data"]
    if progress["status"] in ("completed", "failed"):
        print(progress)
        break

Compatibility and notes

Next steps

If the songs are not finished when the response arrives, use the song query API to fetch the final result.

Node/Electron integration example

If you are integrating standard generation inside an Electron main process, a Node.js server or a desktop client, this is the recommended flow:

  1. Call POST /api/music/create to create the generation task.
  2. Read song_id or id from the response.
  3. Call POST /api/music/query every 2 seconds to check the status.
  4. Treat generation as finished once audio_url appears in the query result.

Stop using the old paths POST /api/generate or GET /api/clip?id=...; those are not part of the currently recommended public integration surface.

const http = require('http');
const https = require('https');

const BASE_URL = 'https://www.suno-api.io';
const MODEL = 'suno-v6';
const POLL_INTERVAL_MS = 2000;
const MAX_POLL_ATTEMPTS = 60;

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

function requestJson(urlString, apiKey, body) {
  const url = new URL(urlString);
  const transport = url.protocol === 'https:' ? https : http;
  const payload = JSON.stringify(body);

  return new Promise((resolve, reject) => {
    const req = transport.request(
      {
        method: 'POST',
        hostname: url.hostname,
        port: url.port || undefined,
        path: `${url.pathname}${url.search}`,
        headers: {
          Authorization: `Bearer ${apiKey}`,
          'Content-Type': 'application/json',
          'Content-Length': Buffer.byteLength(payload),
        },
      },
      (res) => {
        let raw = '';

        res.setEncoding('utf8');
        res.on('data', (chunk) => {
          raw += chunk;
        });
        res.on('end', () => {
          const data = raw ? JSON.parse(raw) : {};

          if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
            reject(new Error(`Suno API request failed: HTTP ${res.statusCode} ${raw}`));
            return;
          }

          resolve(data);
        });
      }
    );

    req.on('error', reject);
    req.write(payload);
    req.end();
  });
}

function getPayload(response) {
  return response && response.data !== undefined ? response.data : response;
}

function toSongList(payload) {
  if (Array.isArray(payload)) return payload;
  if (Array.isArray(payload?.songs)) return payload.songs;
  if (Array.isArray(payload?.clips)) return payload.clips;
  return payload ? [payload] : [];
}

function collectSongIds(createResponse) {
  return toSongList(getPayload(createResponse))
    .map((song) => song.song_id || song.id)
    .filter(Boolean);
}

async function generateSunoSong({ apiKey, description, instrumental = false }) {
  const createResponse = await requestJson(`${BASE_URL}/api/music/create`, apiKey, {
    description,
    model: MODEL,
    instrumental,
    wait_completion: false,
  });

  const songIds = collectSongIds(createResponse);
  if (songIds.length === 0) {
    throw new Error(`Suno API did not return song ids: ${JSON.stringify(createResponse)}`);
  }

  for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt += 1) {
    await sleep(POLL_INTERVAL_MS);

    const queryResponse = await requestJson(`${BASE_URL}/api/music/query`, apiKey, {
      song_ids: songIds,
      model: MODEL,
    });

    const songs = toSongList(getPayload(queryResponse));
    const completed = songs.find((song) => song.audio_url);

    if (completed) {
      return {
        audioUrl: completed.audio_url,
        title: completed.song_title || completed.title || 'Suno Song',
        duration: completed.duration,
      };
    }

    const allFailed = songs.length > 0 && songs.every((song) =>
      ['failed', 'error', 'rejected'].includes(String(song.status || '').toLowerCase())
    );

    if (allFailed) {
      throw new Error(`Suno generation failed: ${JSON.stringify(songs)}`);
    }
  }

  throw new Error('Suno generation timed out after 120 seconds. Please query again later.');
}

// Usage:
// generateSunoSong({
//   apiKey: process.env.SUNO_API_KEY,
//   description: 'A bright pop song about the ocean in summer',
// }).then(console.log).catch(console.error);

In real projects keep the API key in a server environment variable, a desktop client setting or secure storage — never in front-end code and never committed to a repository.

NextCustom mode generation API

Get an API key

Create an API key in the console after signing up. ¥0.6 per run returns 2 tracks, downloads are unlimited, and no phone number is required.

Get API key Back to overview