Tunova

Suno API in Python & Node.js

The Suno API flow is the same in any language: submit a generation (you get a job_id back immediately), then poll until it’s done — or pass a callback_url and take a webhook. Generation takes 1–3 minutes, so it’s always async. Here are complete, copy-paste functions with a timeout and proper error handling. No SDK required — though there’s a tiny zero-dep one if you want it.

Python

import os, time, requests  # pip install requests

API = "https://api.tunova.ai"
H = {"X-API-Key": os.environ["TUNOVA_API_KEY"]}

def generate(prompt, model="v5.5", timeout=300):
    r = requests.post(f"{API}/api/generate", headers=H,
                      json={"prompt": prompt, "model": model})
    r.raise_for_status()
    job_id = r.json()["job_id"]                      # 202 + job_id

    deadline = time.time() + timeout
    while time.time() < deadline:
        job = requests.get(f"{API}/api/jobs/{job_id}", headers=H).json()
        if job["status"] == "complete":
            return job["clips"][0]["audio_url"]
        if job["status"] == "failed":
            raise RuntimeError(job["error"])         # tokens auto-refunded
        time.sleep(3)
    raise TimeoutError(job_id)

print(generate("calm rainy-night lofi"))

Node.js / TypeScript

Node 18+ has fetch built in — zero dependencies.

const API = "https://api.tunova.ai";
const H = { "X-API-Key": process.env.TUNOVA_API_KEY, "Content-Type": "application/json" };

async function generate(prompt, model = "v5.5", timeoutMs = 300_000) {
  const res = await fetch(`${API}/api/generate`, {
    method: "POST", headers: H, body: JSON.stringify({ prompt, model }),
  });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  const { job_id } = await res.json();               // 202 + job_id

  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const job = await (await fetch(`${API}/api/jobs/${job_id}`, { headers: H })).json();
    if (job.status === "complete") return job.clips[0].audio_url;
    if (job.status === "failed") throw new Error(job.error); // tokens auto-refunded
    await new Promise((r) => setTimeout(r, 3000));
  }
  throw new Error(`timeout ${job_id}`);
}

console.log(await generate("calm rainy-night lofi"));

Notes

  • Models: pass model = v4.5, v5, or v5.5. Omit it to use the account default.
  • Custom / lyrics mode: POST to /api/custom_generate with prompt= your lyrics, plus optional tags (style) and title.
  • Billed only on success: a failed job auto-refunds the tokens — your except/catch branch is for logging, not for chasing a refund.
  • Idempotency: send an Idempotency-Key header and a retried submit returns the same job instead of charging twice.

Get a key (50 free tokens, no card) and the full reference on the quickstart, or browse the interactive API docs.

Tunova is an independent service, not affiliated with or endorsed by Suno.