واجهة التوليد بالوضع المبسّط
وصف نقطة النهاية
التوليد بالوضع المبسّط يحوّل وصفاً من جملة واحدة إلى أغنية كاملة. يكتب النظام الكلمات واللحن والتوزيع والغناء انطلاقاً من وصفك.
نقطة النهاية: POST /api/music/create
الفوترة: مدفوع، وحالياً 0.6 يوان افتراضياً لكل طلب. يعيد كل طلب عادةً مقطوعتين؛ والمبلغ المخصوم فعلاً يتبع إعداد الأسعار الحالي في لوحة الإدارة.
Max Mode / Variety: تدعم نقطة النهاية هذه المعاملين الاختياريين max_mode و variety (0-4). عند تشغيل
max_mode يُحاسَب هذا الطلب بضعف السعر (0.6 → 1.2 يوان لكل طلب)، ولا يضيف variety أي تكلفة.
والمعنى وطريقة الإرسال في قسم «المعاملات المتقدمة» من
نظرة عامة على الواجهة الجديدة.
النموذج الموصى به: suno-v6
أوقات الانتظار والمهلات (مهم): هذه نقطة نهاية متزامنة — لا يُقبل الطلب ويُسلَّم إلى التوليد إلا عند وصول الاستجابة. ووفق القياس، تعود معظم الطلبات في 1-3 ثوانٍ، ونحو 10% تتجاوز 30 ثانية، وأطولها نحو 230 ثانية. اضبط مهلة العميل على 300 ثانية أو أكثر؛ وعدم وصول استجابة لا يعني عدم التوليد، ولا تُعد المحاولة فوراً بعد انتهاء المهلة (فذلك يكرر الطلب ويخصم مرة أخرى). وإن انقطع الاتصال فتحقق لاحقاً عبر
GET /api/music/songs. راجع «أوقات الانتظار وإعدادات المهلة» في نظرة عامة على الواجهة الجديدة.
معاملات الطلب
Headers
| المعامل | النوع | مطلوب | ملاحظات |
|---|---|---|---|
| Authorization | string | نعم | Bearer YOUR_API_KEY |
| Content-Type | string | نعم | application/json |
معاملات جسم الطلب
| المعامل | النوع | مطلوب | القيمة الافتراضية | ملاحظات |
|---|---|---|---|---|
| description | string | نعم | - | وصف الأغنية بأي لغة؛ بحد أقصى 3000 حرف (الأطول يعيد 400 ولا يُحاسَب عليه) |
| model | string | لا | suno-v6 | اسم النموذج للعميل: suno-v6 أو suno-v6-wild أو suno-v6-mini |
| instrumental | boolean | لا | false | هل الأغنية موسيقية بلا غناء فقط |
| wait_completion | boolean | لا | false | هل ينتظر انتهاء التوليد قبل الرد |
| references | array | لا | - | قائمة مواد مرجعية: أغانٍ مرجعية / أصوات قديمة / صور مرجعية؛ بحد أقصى 5 أغانٍ وصوت واحد وصورة واحدة. راجع «المواد المرجعية references (اختياري)» أدناه |
أمثلة الطلب
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": "أغنية بوب صينية متفائلة عن الصيف على شاطئ البحر",
"instrumental": false,
"wait_completion": false
}'
المواد المرجعية references (اختياري)
references مصفوفة تُرفق «مواد مرجعية» بهذا التوليد. وهي اختيارية تماماً (إغفالها يجعل السلوك مطابقاً لما سبق تماماً)، ويمكن إرفاق نوع واحد أو أي توليفة.
أنواع العناصر
| type | الحقل المطلوب | الحقول الاختيارية | الحد الأقصى | ملاحظات |
|---|---|---|---|---|
song |
song_id |
style_prompt، lyrics، duration_s |
5 | أغنية مرجعية؛ يُؤخذ song_id من واجهة استعلام الأغاني والسجل، ويجب أن تكون الأغنية قد اكتملت |
voice |
voice_id |
- | 1 | صوت قديم؛ يُؤخذ voice_id من واجهة استنساخ الصوت والتوليد بصوت محدد |
image |
base64 |
- | 1 | صورة مرجعية؛ أرسل محتوى base64 بالشكل data:image/jpeg;base64,... |
القواعد
- ترتيب الأغاني المرجعية هو ترتيبها الدلالي: أرسلها بالترتيب الذي تريده (مثلاً «اللحن من الأولى والغناء من الثانية»).
- يمكن ترك
style_prompt/lyrics/duration_sكلها؛ فالنظام يكملها من معلومات الأغنية، وما ترسله أنت هو المعتمد. - في الأغاني الموسيقية البحتة يمكن أن تكون
lyricsهي""أو"[Instrumental]". - الصور المرجعية تدعم
jpeg/png/webp، بحد 10 ميغابايت للصورة، وتُرسل مع الجسم بصيغة base64. - عند إرفاق عدة أغانٍ مرجعية، استخدم أيضاً
accept_mode=async(انظر «وضع إيصال القبول» أعلاه): إذ يجب على الخدمة تجهيز المواد أولاً، وقد تطول فترة الانتظار المتزامن.
مثال: إرفاق أغنيتين مرجعيتين
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": "اجمع هذه الأفكار في أغنية واحدة",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "song", "song_id": "a90438d2-35fc-4443-88f4-56531e6e5d24" }
]
}'
مثال: أغنية مرجعية + صوت قديم
{
"model": "suno-v6",
"description": "غنِّ هذه الأفكار بهذا الصوت",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "voice", "voice_id": "5813cbe1-36f1-414a-a9a8-4d399dfeb292" }
]
}
مثال: أغنية مرجعية + صورة مرجعية
{
"model": "suno-v6",
"description": "التقط جوّ هذه الصورة",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "image", "base64": "data:image/jpeg;base64,/9j/4AAQ..." }
]
}
أخطاء المعاملات
هذه الحالات تعيد HTTP 400، وتُمنع قبل أي خصم فلا تكلّف شيئاً:
| الحالة | رسالة الخطأ |
|---|---|
| أكثر من 5 أغانٍ مرجعية | references supports at most 5 song references |
| أكثر من صوت واحد | references supports at most 1 voice reference |
| أكثر من صورة مرجعية واحدة | references supports at most 1 image reference |
قيمة type غير صالحة |
references[0].type must be one of song, voice, image |
الأغنية تفتقد song_id |
references[0].song_id is required |
| الأغنية لم تكتمل بعد | references[0].song_id must be a real completed clip |
| تكرار الأغنية نفسها | references[0].song_id is duplicated |
الرقم في
references[0]هو فهرس ذلك العنصر في المصفوفة، مما يسهّل تحديد العنصر الذي به الخطأ.
الاستجابة
مصفوفة أغانٍ، وتحتوي عادةً على مهمتين أو أغنيتين.
[
{
"song_id": "clip_id",
"song_title": "نسيم البحر الصيفي",
"status": "pending",
"description": "أغنية بوب صينية متفائلة عن الصيف على شاطئ البحر",
"audio_url": "",
"cover_url": "",
"video_url": "",
"model_version": "suno-v6",
"generation_type": "generate",
"created_at": "2026-05-21T10:00:00Z"
}
]
وضع إيصال القبول (اختياري، يُوصى به للعملاء الذين لا ينبغي أن يمسكوا اتصالاً طويلاً)
افتراضياً نقطة النهاية متزامنة: وصول الاستجابة هو ما يعني قبول الطلب، وقد تصل مدة الانتظار المقيسة إلى نحو 230 ثانية. وإذا لم يكن عميلك مناسباً لاتصال طويل، فشغّل وضع إيصال القبول — يكفي أحدهما:
- إضافة
"accept_mode": "async"إلى جسم الطلب - إضافة الترويسة
X-Accept-Mode: async
عند تشغيله تُعيد نقطة النهاية HTTP 202 فوراً، وهذا يعني فقط «تم القبول ودخل قائمة التوليد»، ويستمر التوليد في الخلفية:
{
"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" }
]
}
}
مرحلة القبول لا تُعيد
song_id. فلا يوجد بعد معرّف أغنية حقيقي، وليسrequest_idولاtasks[].indexمعرّف أغنية — لا تحفظهما كـsong_id. وسيظهرsong_idالحقيقي في استعلام التقدم أدناه.
استعلام تقدم القبول
نقطة النهاية: GET /api/music/requests/{request_id} (مجاني، ويُصادَق عليه بالمفتاح نفسه)
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" }
]
}
}
معاني قيم status:
| status | المعنى |
|---|---|
queued |
تم القبول، ولم يُربط بأغانٍ محددة بعد (قد تكون tasks مصفوفة فارغة) |
processing |
أُرسل إلى التوليد |
partial |
اكتملت واحدة من الاثنتين |
completed |
اكتملت الاثنتان، وtasks[].song_id قابل للقراءة |
failed |
فشل الإرسال، وقد أُعيد المبلغ كاملاً، ويوضّح error_message السبب |
ولكل مهمة أيضاً tasks[].status خاص بها، بقيم مطابقة لـواجهة استعلام الأغاني:
pending (أُرسلت وتُولَّد)، processing، completed، failed. وقد تحمل عناصر المهمة title
و duration و audio_url مسجَّلاً؛ وما لا يوجد فهو لم يُولَّد بعد.
وبعد الحصول على song_id الحقيقي، تابع عبر واجهة استعلام الأغاني أو نقاط نهاية التنزيل.
مثال بلغة 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": "أغنية بوب متفائلة", "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
التوافق والملاحظات
- بدون
accept_modeيكون السلوك مطابقاً تماماً لما سبق: انتظار متزامن وإرجاع200ومصفوفة الأغاني. ولا يحتاج المستخدمون الحاليون إلى تعديل أي شيفرة. - هذا المفتاح يعمل حالياً على
POST /api/music/createوPOST /api/music/create/customفقط؛ أما بقية نقاط نهاية التوليد فلا تدعمه بعد. - أرسل أيضاً
Idempotency-Key(سلسلة فريدة من اختيارك، ≤128 حرفاً): فالمفتاح نفسه يُقبل مرة واحدة فقط، ويعيد الإرسال الإيصال نفسه دون خصم مزدوج. وفي الوضع غير المتزامن تزداد أهمية ذلك. - عند تشغيل
accept_mode=asyncيُهمَلwait_completion(يعود الإيصال فوراً دون انتظار الأغاني). - لا يزال الخصم يتم مقدماً عند قبول الطلب؛ والتوليد الفاشل يُعاد كاملاً تلقائياً.
- حد الحقل النصي: يقبل
description3000 حرف كحد أقصى (يُحسب بحرف Unicode، والحرف الصيني الواحد يُحسب 1). والنص الأطول يعيد HTTP400مباشرة، ولا يدخل التوليد ولا يُحاسَب عليه، وتذكر رسالة الخطأ الطول المقيس، مثلdescription must not exceed 3000 characters; received 4120. وهذه النقطة لا تحتوي حقول كلمات/أسلوب؛ لتلك راجع «حد الحقل النصي» في واجهة التوليد بالوضع المخصص. أما القواعد العامة فهي في «حدود الحقول النصية» بـنظرة عامة على الواجهة الجديدة. - بدون
referencesيكون السلوك والسعر والاستجابة مطابقة تماماً لما سبق: ولا يحتاج المستخدمون الحاليون إلى تعديل أي شيفرة. - عند إرفاق مواد مرجعية (وخصوصاً عدة أغانٍ)، يُفضَّل وضع الإيصال
accept_mode=asyncبدلاً من انتظار متزامن طويل؛ وزمن تجهيز المواد يعتمد على عددها ومصدرها.
الخطوات التالية
إذا لم تكن الأغاني قد اكتملت عند وصول الاستجابة، فاستخدم واجهة استعلام الأغاني للحصول على النتيجة النهائية.
مثال تكامل في Node/Electron
إذا كنت تدمج التوليد القياسي داخل العملية الرئيسية لـElectron أو خادم Node.js أو عميل سطح مكتب، فهذا هو التدفق الموصى به:
- استدعِ
POST /api/music/createلإنشاء مهمة التوليد. - اقرأ
song_idأوidمن الاستجابة. - استدعِ
POST /api/music/queryكل ثانيتين للتحقق من الحالة. - اعتبر التوليد منتهياً بمجرد ظهور
audio_urlفي النتيجة.
توقف عن استخدام المسارين القديمين POST /api/generate أو GET /api/clip?id=...؛ فهما ليسا جزءاً من سطح التكامل العام الموصى به حالياً.
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);
في المشاريع الحقيقية احفظ مفتاح API في متغيّر بيئة على الخادم أو في إعدادات عميل سطح المكتب أو في مخزن آمن — لا في شيفرة الواجهة الأمامية ولا في المستودع.
احصل على مفتاح API
أنشئ مفتاح API من لوحة التحكم بعد التسجيل. كل عملية توليد تكلف 0.6 يوان وتعيد مقطوعتين، والتنزيلات غير محدودة، ولا حاجة إلى رقم هاتف.
احصل على مفتاح API العودة إلى النظرة العامة