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

# Complete Workflow

> End-to-end guide: create a task, poll for results, and use the output

# Complete Workflow

This guide walks through the full flow of generating music with sunor: authenticate, create a task, poll until it completes, and use the audio output.

## Prerequisites

* A sunor account with an [API key](/authentication)
* [Credits](/credits) in your account (music costs 10 credits)

***

## Step 1: Create a task

Submit a music generation request:

<Note>
  The example below uses **Suno**'s input shape (`gpt_description_prompt`, `make_instrumental`). **Udio** uses a different shape (`prompt`, `lyrics_type`) — see [/models/udio](/models/udio) before adapting this snippet to `"model": "udio"`.
</Note>

<CodeGroup>
  ```python Python theme={null}
  import requests

  API_KEY = "YOUR_API_KEY"
  BASE_URL = "https://sunor.cc/api/v1"

  response = requests.post(
      f"{BASE_URL}/task",
      headers={
          "Content-Type": "application/json",
          "x-api-key": API_KEY,
      },
      json={
          "model": "suno",
          "task_type": "music",
          "input": {
              "gpt_description_prompt": "A chill lo-fi beat for studying, soft piano and vinyl crackle",
              "make_instrumental": True,
          },
      },
  )

  task = response.json()["data"]
  task_id = task["task_id"]
  print(f"Task created: {task_id} (status: {task['status']})")
  ```

  ```javascript Node.js theme={null}
  const API_KEY = "YOUR_API_KEY";
  const BASE_URL = "https://sunor.cc/api/v1";

  const response = await fetch(`${BASE_URL}/task`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": API_KEY,
    },
    body: JSON.stringify({
      model: "suno",
      task_type: "music",
      input: {
        gpt_description_prompt: "A chill lo-fi beat for studying, soft piano and vinyl crackle",
        make_instrumental: true,
      },
    }),
  });

  const { data: task } = await response.json();
  console.log(`Task created: ${task.task_id} (status: ${task.status})`);
  ```
</CodeGroup>

The response returns a `task_id` with status `"pending"`. Credits are frozen immediately.

***

## Step 2: Poll for results

Tasks take **30 seconds to 5 minutes** to complete. Poll every 5-10 seconds until the status is terminal (`success`, `failure`, or `timeout`).

<CodeGroup>
  ```python Python theme={null}
  import time

  def wait_for_task(api_key, task_id, interval=5):
      """Poll until the task completes. Returns the task data."""
      while True:
          response = requests.get(
              f"{BASE_URL}/task/{task_id}",
              headers={"x-api-key": api_key},
          )
          data = response.json()["data"]
          status = data["status"]
          print(f"  Status: {status}")

          if status in ("success", "failure", "timeout"):
              return data

          time.sleep(interval)

  result = wait_for_task(API_KEY, task_id)
  ```

  ```javascript Node.js theme={null}
  async function waitForTask(apiKey, taskId, interval = 5000) {
    while (true) {
      const response = await fetch(`${BASE_URL}/task/${taskId}`, {
        headers: { "x-api-key": apiKey },
      });
      const { data } = await response.json();
      console.log(`  Status: ${data.status}`);

      if (["success", "failure", "timeout"].includes(data.status)) {
        return data;
      }

      await new Promise((r) => setTimeout(r, interval));
    }
  }

  const result = await waitForTask(API_KEY, task.task_id);
  ```
</CodeGroup>

***

## Step 3: Use the output

On success, the `output.result` contains an array of generated clips:

<CodeGroup>
  ```python Python theme={null}
  if result["status"] == "success":
      clips = result["output"]["result"]
      for clip in clips:
          print(f"Title: {clip['title']}")
          print(f"Audio: {clip['audio_url']}")
          print(f"Cover: {clip['image_url']}")
          print()
  else:
      print(f"Task failed: {result['error']}")
  ```

  ```javascript Node.js theme={null}
  if (result.status === "success") {
    const clips = result.output.result;
    for (const clip of clips) {
      console.log(`Title: ${clip.title}`);
      console.log(`Audio: ${clip.audio_url}`);
      console.log(`Cover: ${clip.image_url}`);
      console.log();
    }
  } else {
    console.log(`Task failed: ${result.error}`);
  }
  ```
</CodeGroup>

### Downloading the audio

Audio URLs point to MP3 files hosted on Suno's CDN. You can download them directly:

<CodeGroup>
  ```python Python theme={null}
  import urllib.request

  clip = clips[0]
  filename = f"{clip['title']}.mp3"
  urllib.request.urlretrieve(clip["audio_url"], filename)
  print(f"Downloaded: {filename}")
  ```

  ```javascript Node.js theme={null}
  import { writeFile } from "fs/promises";

  const clip = clips[0];
  const audio = await fetch(clip.audio_url);
  const buffer = Buffer.from(await audio.arrayBuffer());
  const filename = `${clip.title}.mp3`;
  await writeFile(filename, buffer);
  console.log(`Downloaded: ${filename}`);
  ```
</CodeGroup>

***

## Full example

Putting it all together:

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  API_KEY = "YOUR_API_KEY"
  BASE_URL = "https://sunor.cc/api/v1"

  # 1. Create task
  print("Creating music task...")
  response = requests.post(
      f"{BASE_URL}/task",
      headers={
          "Content-Type": "application/json",
          "x-api-key": API_KEY,
      },
      json={
          "model": "suno",
          "task_type": "music",
          "input": {
              "gpt_description_prompt": "A chill lo-fi beat for studying",
              "make_instrumental": True,
          },
      },
  )
  task_id = response.json()["data"]["task_id"]
  print(f"Task ID: {task_id}")

  # 2. Poll for results
  print("Waiting for completion...")
  while True:
      response = requests.get(
          f"{BASE_URL}/task/{task_id}",
          headers={"x-api-key": API_KEY},
      )
      data = response.json()["data"]

      if data["status"] in ("success", "failure", "timeout"):
          break
      time.sleep(5)

  # 3. Use the output
  if data["status"] == "success":
      for clip in data["output"]["result"]:
          print(f"  {clip['title']}: {clip['audio_url']}")
  else:
      print(f"Failed: {data['error']}")
  ```

  ```javascript Node.js theme={null}
  const API_KEY = "YOUR_API_KEY";
  const BASE_URL = "https://sunor.cc/api/v1";

  // 1. Create task
  console.log("Creating music task...");
  const createRes = await fetch(`${BASE_URL}/task`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": API_KEY,
    },
    body: JSON.stringify({
      model: "suno",
      task_type: "music",
      input: {
        gpt_description_prompt: "A chill lo-fi beat for studying",
        make_instrumental: true,
      },
    }),
  });
  const taskId = (await createRes.json()).data.task_id;
  console.log(`Task ID: ${taskId}`);

  // 2. Poll for results
  console.log("Waiting for completion...");
  let data;
  while (true) {
    const res = await fetch(`${BASE_URL}/task/${taskId}`, {
      headers: { "x-api-key": API_KEY },
    });
    data = (await res.json()).data;

    if (["success", "failure", "timeout"].includes(data.status)) break;
    await new Promise((r) => setTimeout(r, 5000));
  }

  // 3. Use the output
  if (data.status === "success") {
    for (const clip of data.output.result) {
      console.log(`  ${clip.title}: ${clip.audio_url}`);
    }
  } else {
    console.log(`Failed: ${data.error}`);
  }
  ```
</CodeGroup>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Music generation modes" icon="music" href="/models/suno">
    Learn about inspiration, custom, and continuation modes.
  </Card>

  <Card title="Error handling" icon="triangle-exclamation" href="/errors">
    Handle errors and implement retries.
  </Card>

  <Card title="Rate limits" icon="gauge-high" href="/rate-limits">
    Stay within rate limits with smart polling.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/create-task">
    Full endpoint documentation.
  </Card>
</CardGroup>
