API de génération en mode simple
Description du point d'accès
La génération en mode simple sert à transformer une description d'une phrase en un morceau complet. Le service écrit les paroles, la mélodie, l'arrangement et le chant à partir de votre description.
Point d'accès : POST /api/music/create
Facturation : Payant, actuellement 0,6 ¥ par appel par défaut. Chaque appel renvoie généralement 2 morceaux ; le montant réellement facturé suit la configuration tarifaire actuelle du back-office.
Max Mode / Variety : ce point d'accès accepte les paramètres optionnels max_mode et variety (0-4). Avec
max_mode activé, cet appel est facturé au double du prix (0,6 ¥ → 1,2 ¥ par appel) ; variety ne coûte
rien de plus. Leur signification et leur envoi sont décrits dans la section « Paramètres avancés » de la
Présentation de la nouvelle API.
Modèle recommandé : suno-v6
Temps d'attente et timeouts (important) : c'est un point d'accès synchrone — la commande n'est acceptée et transmise à la génération qu'à l'arrivée de la réponse. D'après les mesures, la plupart des requêtes répondent en 1 à 3 secondes, environ 10 % prennent plus de 30 secondes et la plus longue avoisine 230 secondes. Réglez le timeout du client à 300 secondes ou plus ; l'absence de réponse ne signifie pas qu'aucune génération n'a eu lieu, et ne réessayez pas juste après un timeout (cela duplique la commande et refacture). Si la connexion a été coupée, vérifiez plus tard avec
GET /api/music/songs. Voir « Temps d'attente et réglage du timeout » dans la Présentation de la nouvelle API.
Paramètres de la requête
Headers
| Paramètre | Type | Obligatoire | Remarques |
|---|---|---|---|
| Authorization | string | oui | Bearer YOUR_API_KEY |
| Content-Type | string | oui | application/json |
Paramètres du body
| Paramètre | Type | Obligatoire | Par défaut | Remarques |
|---|---|---|---|---|
| description | string | oui | - | Description du morceau, dans n'importe quelle langue ; au maximum 3000 caractères (au-delà, la réponse est 400 et rien n'est facturé) |
| model | string | non | suno-v6 | Nom de modèle côté client : suno-v6, suno-v6-wild ou suno-v6-mini |
| instrumental | boolean | non | false | Si le morceau est purement instrumental |
| wait_completion | boolean | non | false | S'il faut attendre la fin de la génération avant de répondre |
| references | array | non | - | Liste de matériel de référence, pouvant porter des morceaux de référence / voix héritées / images de référence ; au maximum 5 morceaux, 1 voix et 1 image. Voir « Matériel de référence references (facultatif) » ci-dessous |
Exemples de requête
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": "une chanson pop en mandarin entraînante sur l'été au bord de la mer",
"instrumental": false,
"wait_completion": false
}'
Matériel de référence references (facultatif)
references est un tableau qui attache du « matériel de référence » à cette génération. Il est entièrement facultatif (l'omettre se comporte exactement comme avant), et vous pouvez n'attacher qu'un seul type ou n'importe quelle combinaison.
Types d'élément
| type | Champ obligatoire | Champs facultatifs | Maximum | Remarques |
|---|---|---|---|---|
song |
song_id |
style_prompt, lyrics, duration_s |
5 | Morceau de référence ; le song_id vient de l'API de consultation et d'historique des morceaux et le morceau doit déjà être terminé |
voice |
voice_id |
- | 1 | Voix héritée ; le voice_id vient de l'API de clonage vocal et de génération avec voix |
image |
base64 |
- | 1 | Image de référence ; envoyez du base64 sous la forme data:image/jpeg;base64,... |
Règles
- L'ordre des morceaux de référence est leur ordre sémantique : passez-les dans l'ordre voulu (par exemple « mélodie du premier, voix du second »).
style_prompt/lyrics/duration_speuvent tous être omis ; la plateforme les complète à partir des informations du morceau, et ce que vous envoyez l'emporte.- Pour un morceau purement instrumental,
lyricspeut valoir""ou"[Instrumental]". - Les images de référence acceptent
jpeg/png/webp, jusqu'à 10 Mo chacune, envoyées avec le corps en base64. - Lorsque vous attachez plusieurs morceaux de référence, utilisez aussi
accept_mode=async(voir « Mode reçu d'acceptation » ci-dessus) : le service doit d'abord préparer le matériel, l'attente synchrone peut donc être longue.
Exemple : deux morceaux de référence
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 ces idées en un seul morceau",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "song", "song_id": "a90438d2-35fc-4443-88f4-56531e6e5d24" }
]
}'
Exemple : morceau de référence + voix héritée
{
"model": "suno-v6",
"description": "chante ces idées avec cette voix",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "voice", "voice_id": "5813cbe1-36f1-414a-a9a8-4d399dfeb292" }
]
}
Exemple : morceau de référence + image de référence
{
"model": "suno-v6",
"description": "capture l'ambiance de cette image",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "image", "base64": "data:image/jpeg;base64,/9j/4AAQ..." }
]
}
Erreurs de paramètres
Ces cas renvoient HTTP 400, bloqués avant toute facturation, donc sans coût :
| Cas | Message d'erreur |
|---|---|
| Plus de 5 morceaux de référence | references supports at most 5 song references |
| Plus de 1 voix | references supports at most 1 voice reference |
| Plus de 1 image de référence | references supports at most 1 image reference |
type invalide |
references[0].type must be one of song, voice, image |
Morceau sans song_id |
references[0].song_id is required |
| Morceau pas encore terminé | references[0].song_id must be a real completed clip |
| Même morceau envoyé deux fois | references[0].song_id is duplicated |
Le nombre dans
references[0]est l'index de cet élément dans le tableau, ce qui rend l'élément fautif facile à repérer.
Réponse
Un tableau de morceaux, contenant généralement 2 tâches ou morceaux.
[
{
"song_id": "clip_id",
"song_title": "Brise marine d'été",
"status": "pending",
"description": "une chanson pop en mandarin entraînante sur l'été au bord de la mer",
"audio_url": "",
"cover_url": "",
"video_url": "",
"model_version": "suno-v6",
"generation_type": "generate",
"created_at": "2026-05-21T10:00:00Z"
}
]
Mode reçu d'acceptation (facultatif, recommandé pour les clients qui ne doivent pas garder de connexion longue)
Par défaut, ce point d'accès est synchrone : l'arrivée de la réponse est ce qui signifie que la commande a été acceptée, et les attentes mesurées peuvent atteindre environ 230 secondes. Si votre client ne doit pas garder une connexion longue, activez le mode reçu d'acceptation — l'une ou l'autre option fonctionne :
- ajouter
"accept_mode": "async"au corps de la requête - ajouter l'en-tête
X-Accept-Mode: async
Une fois activé, le point d'accès renvoie immédiatement HTTP 202, ce qui signifie seulement « accepté et mis en file de génération », tandis que la génération continue en arrière-plan :
{
"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" }
]
}
}
La phase d'acceptation ne renvoie pas de
song_id. Aucun ID de morceau réel n'existe encore, et nirequest_idnitasks[].indexn'en sont un — ne les enregistrez pas commesong_id. Le vraisong_idapparaît dans la consultation de progression ci-dessous.
Consulter la progression de l'acceptation
Point d'accès : GET /api/music/requests/{request_id} (gratuit, authentifié avec la même clé d'API)
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" }
]
}
}
Ce que signifie chaque valeur de status :
| status | Signification |
|---|---|
queued |
Accepté, pas encore rattaché à des morceaux précis (tasks peut être un tableau vide) |
processing |
Transmis à la génération |
partial |
L'un des deux est déjà terminé |
completed |
Les deux sont terminés, tasks[].song_id est lisible |
failed |
L'envoi a échoué, le montant a été intégralement remboursé, et error_message en donne la raison |
Chaque tâche possède aussi son propre tasks[].status, avec les mêmes valeurs que l'API de consultation des morceaux :
pending (transmise, en génération), processing, completed, failed. Les éléments de tâche peuvent aussi porter title,
duration et un audio_url déjà enregistré ; ce qui manque n'est simplement pas encore généré.
Une fois le vrai song_id obtenu, poursuivez avec l'API de consultation des morceaux ou les points d'accès de téléchargement.
Exemple en Python
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": "une chanson pop entraînante", "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
Compatibilité et remarques
- Sans
accept_mode, le comportement est exactement celui d'avant : attente synchrone, réponse200et tableau de morceaux. Les intégrations existantes n'ont rien à modifier. - Cet interrupteur ne fonctionne aujourd'hui que sur
POST /api/music/createetPOST /api/music/create/custom; les autres points d'accès de génération ne le prennent pas encore en charge. - Envoyez aussi un
Idempotency-Key(votre propre chaîne unique, ≤128 caractères) : la même clé envoyée deux fois n'est acceptée qu'une fois, une répétition renvoie le même reçu et rien n'est facturé deux fois. Cela compte encore plus en mode asynchrone. - Avec
accept_mode=async,wait_completionest ignoré (le reçu revient immédiatement sans attendre les morceaux). - Le montant est toujours prélevé à l'acceptation ; une génération en échec est intégralement remboursée automatiquement.
- Limite du champ texte :
descriptionaccepte au maximum 3000 caractères (comptés en caractères Unicode, un caractère han comptant pour 1). Au-delà, la réponse est directement HTTP400, rien n'entre en génération et rien n'est facturé, et le message d'erreur indique la longueur mesurée, par exempledescription must not exceed 3000 characters; received 4120. Ce point d'accès n'a pas de champs paroles/style ; pour cela, voir « Limite du champ texte » dans l'API de génération en mode personnalisé. Les conventions générales sont dans « Limites des champs texte » de la Présentation de la nouvelle API. - Sans
references, le comportement, le prix et la réponse sont exactement ceux d'avant : les intégrations existantes n'ont rien à modifier. - Lorsque du matériel de référence est joint (surtout plusieurs morceaux), préférez le mode reçu
accept_mode=asyncà une longue attente synchrone ; le temps de préparation dépend de la quantité et de la provenance du matériel.
Étapes suivantes
Si les morceaux ne sont pas terminés à l'arrivée de la réponse, utilisez l'API de consultation des morceaux pour récupérer le résultat final.
Exemple d'intégration Node/Electron
Si vous intégrez la génération standard dans le processus principal d'Electron, un serveur Node.js ou un client de bureau, voici le flux recommandé :
- Appelez
POST /api/music/createpour créer la tâche de génération. - Lisez
song_idouiddans la réponse. - Appelez
POST /api/music/querytoutes les 2 secondes pour vérifier l'état. - Considérez la génération comme terminée dès que
audio_urlapparaît dans le résultat.
Cessez d'utiliser les anciens chemins POST /api/generate ou GET /api/clip?id=... ; ils ne font pas partie de la surface d'intégration publique actuellement recommandée.
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);
Dans un vrai projet, gardez la clé d'API dans une variable d'environnement serveur, les réglages d'un client de bureau ou un stockage sûr — jamais dans du code front-end, jamais commitée dans un dépôt.
Obtenir une clé d'API
Créez une clé d'API dans la console après votre inscription. Chaque génération coûte 0,6 ¥ et renvoie 2 pistes, les téléchargements sont illimités et aucun numéro de téléphone n'est requis.
Obtenir une clé d'API Retour à la présentation