【Zalecane】 API profilu głosu
✅ Ten łańcuch zalecamy w nowych integracjach. Zgodnie z realnymi ocenami wielu użytkowników utwory tworzone tą drogą dobrze zachowują oryginalny głos: wokal w gotowym miksie jest bliższy osobie z przesłanej próbki, dlatego obecnie jest to droga, którą rekomendujemy klientom.
Dla porównania: wcześniejsze API klonowania głosu i generowania ze wskazanym głosem nadal działa, ale nawigacja oznacza je jako „niezalecane" i nie jest już zalecane w nowych integracjach.
- Data dokumentu: 2026-09-26
- Zakres: utworzenie własnego głosu → użycie go do coveru wybranego utworu / zaśpiewanie nowego utworu → śledzenie postępu → pobranie gotowego pliku
- Wszystkie interfejsy, pola i odpowiedzi sprawdzono realnymi wywołaniami (punkty oznaczone „zmierzone" zweryfikowano szczegółowo)
Uwaga: ten dokument opisuje tylko interfejsy, które wywołujesz. Przetwarzanie materiałów, planowanie zadań i walidację treści serwer wykonuje automatycznie; klient ich nie implementuje.
0. Start w pięć minut
Cztery kroki wystarczą, aby z jednej próbki wokalu otrzymać dwa gotowe utwory.
① Utwórz głos POST /api/music/voice-profile/create → pobierz voice_id (status=ready)
② Zrób cover POST /api/music/voice-profile/cover → od razu pobierz 2 song_id
③ Śledź POST /api/music/query → odpytuj aż status=completed
④ Pobierz GET /api/music/download?song_id=…&kind=mp3
Minimalny działający przykład (curl):
API_KEY="sk-twoj-klucz"
BASE="https://www.suno-api.io"
# ① Utwórz głos (wyślij próbkę wokalu; zalecane 10 s lub więcej, poniżej 10 MB)
curl -sS -X POST "$BASE/api/music/voice-profile/create" \
-H "Authorization: Bearer $API_KEY" \
-F "file=@./my-voice.mp3" \
-F "title=Mój głos" \
-F "source_kind=upload"
# → {"success":true,"message":"","data":{"voice_id":"vp_2026…","status":"ready", …}}
# ② Zrób cover utworu tym głosem (song_clip_id = clip id utworu do coveru)
curl -sS -X POST "$BASE/api/music/voice-profile/cover" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Create-Ui-Client-Request-Id: cover-$(date +%s)" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"voice_id": "vp_2026…",
"song_clip_id": "5b773e9a-…",
"lyrics": "[Verse 1]\ntekst utworu…",
"style_requirements": "wolny folk, gitara akustyczna",
"audio_weight": 0.85,
"max_mode": false
}'
# → {"code":200,"message":"success","data":{"resolved_scene":"cover","clips":[{…},{…}]}}
# ③ Odpytuj (kilka id naraz, rozdzielone przecinkami)
curl -sS -X POST "$BASE/api/music/query" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"suno-v6","song_ids":"id1,id2"}'
# ④ Po zakończeniu pobierz mp3 (plik jest tylko przy status=completed)
curl -sS -L "$BASE/api/music/download?song_id=id1&kind=mp3" \
-H "Authorization: Bearer $API_KEY" -o song1.mp3
1. Wspólne ustalenia
1.1 Domena i środowisko
| Środowisko | Base URL | Przeznaczenie |
|---|---|---|
| Produkcja | https://www.suno-api.io |
Rzeczywisty ruch klientów |
Wszystkie poniższe ścieżki są względne wobec Base URL; na przykład pełny adres POST /api/music/voice-profile/create to
https://www.suno-api.io/api/music/voice-profile/create.
1.2 Uwierzytelnianie
Wszystkie interfejsy używają tego samego nagłówka żądania, którego wartością jest klucz API utworzony w konsoli:
Authorization: Bearer sk-xxxxxxxx
- Przedrostek
Bearerjest opcjonalny; przedrosteksk-również (Authorization: sk-xxxdziała tak samo). - Brak lub nieprawidłowy klucz → HTTP 401, treść w postaci
{"success":false,"message":"…"}(komunikat zależy od języka żądania). - Każdy klucz widzi i może modyfikować wyłącznie utwory i głosy własnego konta.
1.3 Formaty treści żądania
- Tworzenie głosu: zalecane
multipart/form-data(wysyłanie pliku); obsługiwane jest teżapplication/json(URL lub base64). - Pozostałe interfejsy:
application/json.
1.4 Dwie otoczki odpowiedzi (klient musi znać tylko te dwie)
Interfejsy „zarządzania głosami" (create / create-from-clip / list / detail / delete) używają otoczki biznesowej:
{ "success": true, "message": "", "data": { } }
{ "success": false, "message": "voice_id is required" }
„Cover z głosem" idzie kanałem generowania i używa otoczki generowania: sukces to code/message/data, błąd to obiekt error:
{ "code": 200, "message": "success", "data": { } }
{ "error": { "message": "voice not found: vp_xxx", "type": "bad_response_status_code", "param": "", "code": "bad_response_status_code" } }
Jak rozstrzygać: najpierw kod stanu HTTP, potem success === false, na końcu code !== 200 lub obecność error.
Błąd biznesowy nie gwarantuje HTTP innego niż 200 (interfejsy zarządzania głosami przy błędzie nadal zwracają HTTP 200), więc nie można opierać się wyłącznie na kodzie stanu.
1.5 Idempotencja
Tworzenie głosu (w tym „utwórz z istniejącego audio") jest naprawdę idempotentne: pod tym samym kluczem ponowne wysłanie tego samego client_request_id tworzy tylko jeden głos, a druga próba zwraca wprost pierwszy wynik (success=true, ten sam voice_id). Chodzi o to, że klient sam generuje id (np. UUID) i przy ponowieniu po przekroczeniu czasu używa tej samej wartości.
Wysłanie coveru nie deduplikuje się na poziomie żądania (to płatne generowanie), więc zwróć uwagę na dwie rzeczy:
- Identyfikator wysyłki trafia do nagłówka
X-Create-Ui-Client-Request-Id: <twój id wysyłki>. Jest zapisywany w serwerowym rekordzie zadania, co ułatwia późniejsze dochodzenie; nie zapobiega jednak podwójnemu obciążeniu. - Przekroczenie czasu ≠ porażka: żądanie mogło już zostać przyjęte i generować się. Przed ponowieniem sprawdź przez
GET /api/music/songs?p=1&page_size=20(parametry stronicowania top/page_size; zgodny zapispsteż działa), czy nie pojawił się już nowy utwór zgeneration_type=voice_profile_cover, i ponów to samo żądanie tylko wtedy, gdy go nie ma.
Treści create i create-from-clip też przyjmują pole client_request_id (patrz §3 i §4).
1.6 Przegląd rozliczeń
| Czynność | Interfejs | Cena | Uwagi |
|---|---|---|---|
| Tworzenie głosu (zwykłe) | POST /api/music/voice-profile/create |
Bezpłatne | Wysłanie próbki nie zużywa limitów Suno |
| Tworzenie głosu (z istniejącego audio) | POST /api/music/voice-profile/create-from-clip |
Bezpłatne | Serwer tylko rejestruje odwołanie do materiału; nic nie jest wysyłane ponownie |
| Wzmocnione klonowanie | To samo, enhanced=true |
Według „ceny wzmocnionego przesyłania" (domyślnie 10 ¥ za wywołanie) | Asynchroniczne; przy niepowodzeniu automatyczny zwrot |
| Cover z głosem | POST /api/music/voice-profile/cover |
1,2 ¥ za wywołanie; 2,4 ¥ za wywołanie przy max_mode=true |
Jedno wywołanie zwraca 2 utwory |
| Odpytanie / lista / szczegóły / usunięcie | — | Bezpłatne | |
| Pobieranie (sam bierzesz link bezpośredni) | audio_url z odpowiedzi |
Bezpłatne | Odtwarza wydany adres |
| Pobieranie (konwersja do wav / tekst utworu itp.) | POST /api/music/free2 |
0,2 ¥ za udany utwór | Patrz §8 |
Ceny można w każdej chwili odczytać z publicznego interfejsu, więc nie wpisuj ich na sztywno (patrz §9):
curl -sS https://www.suno-api.io/api/pricing/catalog | jq '.data.catalog.meta'
# {
# "generation_price": "0.6",
# "voice_generation_price": "1.2", ← cena bazowa coveru z głosem
# "max_mode_factor": "2",
# "enhanced_upload_price": "10", ← cena wzmocnionego klonowania
# "voice_auto_verify_price": "5",
# "voice_long_term_clone_price": "5"
# }
Cover działa w modelu pobranie z góry + zwrot przy niepowodzeniu:
- Odrzucone żądanie (błędne parametry, 4xx/5xx platformy, samo niewystarczające saldo) nie jest obciążane — przy wysłaniu z nieistniejącym głosem saldo w pomiarach w ogóle się nie zmieniło (delta = 0);
- Przyjęte zadanie, które ostatecznie zawiedzie (w tym awaria usługi platformy), przechodzi ścieżką zwrotu po stronie serwera i oddaje pobraną z góry kwotę.
1.7 Słownik stanów
status głosu:
| Wartość | Znaczenie | Można użyć do coveru |
|---|---|---|
ready |
Gotowy | ✅ |
processing |
Pojawia się tylko przy wzmocnionym klonowaniu (enhanced=true); w trakcie |
❌ (czekaj na ready) |
failed |
Utworzenie nie udało się; patrz error_message; przy wzmocnionym klonowaniu już zwrócono środki |
❌ |
status utworu (wartość zwracana przez interfejsy odpytujące):
| Wartość | Znaczenie | Można pobrać |
|---|---|---|
submitted / queued / processing |
Generowanie (strumień przedodsłuchu może już istnieć) | ❌ |
completed |
Gotowe | ✅ |
failed |
Nie udało się; opłata została zwrócona | ❌ |
2. Przegląd interfejsów
| # | Metoda | Ścieżka | Rola | Rozliczenie |
|---|---|---|---|---|
| 1 | POST | /api/music/voice-profile/create |
Utworzenie głosu (przesłanie / URL / base64) | Bezpłatne (poza enhanced=true) |
| 2 | POST | /api/music/voice-profile/create-from-clip |
Utworzenie głosu z własnego audio | Bezpłatne |
| 3 | GET | /api/music/voice-profile/list |
Lista głosów | Bezpłatne |
| 4 | GET | /api/music/voice-profile/{voice_id} |
Szczegóły głosu (z postępem wzmocnionego klonowania) | Bezpłatne |
| 5 | POST | /api/music/voice-profile/delete |
Usunięcie głosu | Bezpłatne |
| 6 | POST | /api/music/voice-profile/cover |
Cover tym głosem / zaśpiewanie nowego utworu | 1,2 ¥ (MAX 2,4) |
| 7 | POST | /api/music/query |
Zbiorcze odpytanie stanu utworów | Bezpłatne |
| 8 | GET | /api/music/songs/{song_id} |
Szczegóły jednego utworu | Bezpłatne |
| 9 | GET | /api/music/download |
Pobranie gotowego pliku | Bezpłatne (mp3/link odtwarzania) |
| 10 | POST | /api/music/free2 |
Konwersja do wav / tekst utworu itp. | 0,2 ¥ za udany utwór |
| 11 | POST | /api/music/free2/cached |
Pobranie już zarchiwizowanego adresu | Bezpłatne |
| 12 | GET | /api/music/songs |
Moje utwory, z paginacją | Bezpłatne |
3. Utworzenie głosu
POST /api/music/voice-profile/create
Zarejestruj fragment audio z wokalem jako „głos" i otrzymaj voice_id. Dla platformy głos to po prostu „audio + jego clip w katalogu", dlatego po udanym utworzeniu to źródłowe audio jest zachowywane na stałe (na potrzeby kolejnych coverów).
3.1 Trzy formy wejścia (wybierz jedną)
Forma A: przesłanie pliku multipart (zalecane)
Content-Type: multipart/form-data
file=<dane binarne audio> # wymagane
title=<nazwa głosu> # opcjonalne; puste oznacza nazwę pliku bez rozszerzenia
file_name=<oryginalna nazwa pliku>
source_file_name=<oryginalna nazwa pliku>
source_kind=upload|record # opcjonalne, znacznik źródła (przesłanie / nagranie); domyślnie upload
enhanced=false|true # opcjonalne, true = wzmocnione klonowanie (patrz §3.5)
client_request_id=<klucz idempotencji> # opcjonalne
voice_id=<własne ID> # opcjonalne, rzadko używane
curl -sS -X POST "https://www.suno-api.io/api/music/voice-profile/create" \
-H "Authorization: Bearer $API_KEY" \
-F "file=@./my-voice.mp3;type=audio/mpeg" \
-F "file_name=my-voice.mp3" \
-F "source_file_name=my-voice.mp3" \
-F "title=Mój głos" \
-F "source_kind=upload"
Forma B: JSON + publiczny URL audio
curl -sS -X POST "https://www.suno-api.io/api/music/voice-profile/create" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"file_url": "https://your-cdn.example.com/voice/my-voice.mp3",
"file_name": "my-voice.mp3",
"title": "Mój głos"
}'
- URL musi być publicznie dostępnym bezpośrednim linkiem HTTPS; serwer pobiera go raz i przenosi do naszej pamięci obiektowej.
- Adres można też wpisać w pole
audio_url, efekt jest równoważny (jeśli podasz oba, wygrywafile_url). - Jeśli adres jest już w pamięci obiektowej tej platformy (
*.myqcloud.com/create-ui/voice-source/...), nic nie jest pobierane ponownie: jest rejestrowany bezpośrednio.
Forma C: JSON + base64
{
"file_base64": "data:audio/mpeg;base64,//uQxAAA…",
"file_name": "my-voice.mp3",
"title": "Mój głos"
}
- Obsługiwany jest zarówno przedrostek
data:audio/xxx;base64,, jak i czysty base64. - Rozmiar jest ograniczony (base64 powiększa o 1,33×), więc dla dużych plików użyj formy A.
3.2 Wymagania dotyczące audio
| Punkt | Wymaganie | Uwagi |
|---|---|---|
| Rozmiar | ≤ 10 MB | Powyżej limitu brama obcina treść, co wygląda jak „odrzucone przez Suno"; najpierw skompresuj lub skróć |
| Długość | Minimum 6 s; zalecane 10–60 s | Poniżej 6 s platforma odrzuca: Uploaded audio is too short (currently 2.4 seconds). Minimum duration is 6 seconds. |
| Format | mp3 / wav / m4a / aac / flac / ogg | Rozpoznawany po rozszerzeniu pliku |
| Zawartość | Czysty wokal; unikaj gotowych coverów i oryginałów z podkładem | Audio bardzo podobne do istniejącego nagrania w katalogu jest odrzucane: This audio matches an existing recording in our catalog. (zmierzone) |
3.3 Odpowiedź
{
"success": true,
"message": "",
"data": {
"voice_id": "vp_20260926080618509168500DXXrxe",
"clip_id": "91cc5935-389f-4193-b56b-cc796c15562d",
"song_id": "91cc5935-389f-4193-b56b-cc796c15562d",
"account_id": "acc_1790085275308",
"title": "Mój głos",
"source_file_name": "my-voice.mp3",
"audio_url": "https://suno-api-p-1437223057.cos.ap-guangzhou.myqcloud.com/create-ui/voice-source/2026/09/26/xxx.mp3",
"image_url": "https://cdn2.suno.ai/image_91cc5935-389f-4193-b56b-cc796c15562d.jpeg",
"duration_s": 29.18,
"enhanced": false,
"source_kind": "upload",
"status": "ready",
"client_request_id": "",
"created_at": 1790409978,
"updated_at": 1790409998
}
}
Opis pól (create / list / detail korzystają z tego samego zestawu):
| Pole | Typ | Uwagi |
|---|---|---|
voice_id |
string | ID głosu; używają go późniejsze covery |
clip_id / song_id |
string | clip id tego audio głosu po stronie Suno (oba są takie same); do diagnostyki |
account_id |
string | Konto, które go obsługuje (do diagnostyki; klient nie musi się tym zajmować) |
title |
string | Nazwa głosu |
source_file_name |
string | Oryginalna nazwa pliku |
audio_url |
string | Długoterminowy bezpośredni link do źródłowego audio, przydatny do odsłuchu; zachowywany na stałe |
image_url |
string | Okładka głosu (ta, którą Suno tworzy dla audio wokalnego); gdy okładki nie ma, klucz w ogóle nie występuje |
duration_s |
number | Długość próbki głosu w sekundach |
enhanced |
bool | Czy utworzono wzmocnionym klonowaniem |
source_kind |
string | upload / record / clip (z istniejącego audio) |
status |
string | ready / processing / failed |
error_message |
string | Przyczyna niepowodzenia; występuje tylko przy failed |
task_id |
number | Numer zadania bazowego wzmocnionego klonowania; tylko przy enhanced=true |
pre_consumed_quota |
number | Pobrany z góry limit (tylko przy wzmocnionym klonowaniu) |
created_at / updated_at |
number | Sekundy Unix |
created_at/updated_atto znaczniki czasu w sekundach (10 cyfr), nie w milisekundach.
3.4 Częste błędy
| HTTP | message | Przyczyna i postępowanie |
|---|---|---|
| 200 | one of file_path, file_base64, or file_url is required |
Nie dołączono treści audio |
| 200 | Uploaded audio is too short (currently 2.4 seconds). Minimum duration is 6 seconds. |
Próbka jest za krótka; użyj ≥6 s (zalecane ≥10 s) |
| 200 | This audio matches an existing recording in our catalog. |
Próbka jest bardzo podobna do istniejącego nagrania w katalogu; użyj innego czystego, suchego wokalu |
| 200 | upload succeeded without clip or account identity |
Nietypowa odpowiedź platformy; ponów |
| 200 | audio file exceeds 30 MB limit |
Powyżej limitu serwera (dla klienta trzymaj się 10 MB) |
| 401 | invalid token |
Błędny klucz API |
3.5 Wzmocnione klonowanie (enhanced=true)
Dla przypadków, gdy „sama próbka głosu zawiera chroniony tekst / potrzebne jest wzmocnione przesłanie". Cena jak za wzmocnione przesyłanie (domyślnie 10 ¥ za wywołanie, przy niepowodzeniu automatyczny zwrot):
- Odpowiedź od razu to
status=processing+task_id(na tym etapie bezclip_id), wykonanie jest asynchroniczne; - W trakcie postęp sprawdzasz przez
GET /api/music/voice-profile/{voice_id}; zwracane sąprogress_percent/progress_stage/progress_message; - Po zakończeniu
statuszmienia się naready, aclip_id,audio_url,image_urlsą uzupełniane; - Przy niepowodzeniu
status=failed, aerror_messagebrzmi mniej więcej „wzmocnione przesyłanie nie powiodło się; opłata została automatycznie zwrócona, spróbuj później"; - Wzmocnione klonowanie trwa wyraźnie dłużej niż zwykłe utworzenie (minuty), więc nie czekaj na nie synchronicznym przekroczeniem czasu.
curl -sS -X POST "https://www.suno-api.io/api/music/voice-profile/create" \
-H "Authorization: Bearer $API_KEY" \
-F "file=@./my-voice.mp3" -F "title=Mój głos" -F "enhanced=true"
4. Utworzenie głosu z istniejącego audio
Jeśli nie chcesz ponownie przesyłać: skopiuj wprost do głosu audio, które już przesłałeś lub już wygenerowałeś. Bezpłatnie i idempotentnie.
POST /api/music/voice-profile/create-from-clip
Content-Type: application/json
{
"source_song_id": "97ee62fe-56cd-473f-a2f5-c66ac0766a2e",
"title": "Xu Qing Qiang",
"client_request_id": "vp-clip-1789…"
}
source_song_id: clip id ukończonego audio na twoim koncie (tożsame zsong_idutworu).- Ponowne wysłanie tego samego clipu nie tworzy nowego rekordu: zwracany jest od razu istniejący głos z
reused: true(zmierzone).
Odpowiedź to wszystkie pola z §3.3 plus dwa pola tylko do odczytu:
| Pole | Uwagi |
|---|---|
reused |
true = to audio było już twoim głosem i jest ponownie użyte |
source_type |
Skąd pochodzi audio: generate / custom_generate / voice_generate / upload_source / enhanced_upload |
{
"success": true,
"data": {
"voice_id": "vp_20260926081712557959800Z5gvlt",
"clip_id": "97ee62fe-56cd-473f-a2f5-c66ac0766a2e",
"title": "Xu Qing Qiang",
"status": "ready",
"enhanced": true,
"reused": true,
"source_type": "enhanced_upload"
}
}
Błędy (message w postaci zwróconej; zalecane pokazanie lub lokalizacja):
| message | Znaczenie |
|---|---|
source audio not found |
Clip nie istnieje albo nie należy do ciebie |
source audio is invalid |
To audio jeszcze się generuje / jest produktem pośrednim i nie jest jeszcze użyteczne |
source_song_id is required |
Nie przesłano source_song_id |
5. Lista / szczegóły / usuwanie głosów
5.1 Lista
GET /api/music/voice-profile/list
GET /api/music/voice-profile/list?include_deleted=true
{
"success": true,
"message": "",
"data": {
"items": [ { "voice_id": "vp_…", "title": "Mój głos", "status": "ready", "audio_url": "…", "image_url": "…" } ],
"total": 1
}
}
Pola są dokładnie takie jak w §3.3. Domyślnie usunięte głosy nie są zwracane.
5.2 Szczegóły
GET /api/music/voice-profile/{voice_id}
Zwracany jest pojedynczy obiekt głosu (data to sam obiekt, nie tablica). Gdy trwa wzmocnione klonowanie, dochodzą:
| Pole | Uwagi |
|---|---|
progress_percent |
Liczba całkowita od 0 do 100 |
progress_stage |
Identyfikator etapu, na przykład media_preparing |
progress_message |
Tekst postępu do pokazania użytkownikowi |
5.3 Usuwanie
POST /api/music/voice-profile/delete
Content-Type: application/json
{ "voice_id": "vp_2026…" }
{ "success": true, "message": "", "data": { "voice_id": "vp_2026…", "status": "deleted" } }
- Po usunięciu głos znika z listy i nie można go już użyć do nowych coverów: wysłanie z tym
voice_idzwraca 400 (patrz §6.4). - Utwory już nim wygenerowane nie są w żaden sposób dotknięte; odtwarzanie, pobieranie, kontynuowanie, zamiana i rozdzielanie działają jak wcześniej.
- Usunięcie nieistniejącego głosu lub głosu nienależącego do tego konta zwraca
{"success":false,"message":"voice not found"}.
6. Cover z głosem (kluczowy interfejs)
POST /api/music/voice-profile/cover
Content-Type: application/json
Jedno wysłanie generuje 2 utwory (tak jak zwykłe generowanie).
6.1 Dwa scenariusze
| Scenariusz | Warunek | Uwagi |
|---|---|---|
| A. Cover wybranego utworu | Przesłano song_clip_id |
Śpiewa ten utwór twoim głosem (melodia / rytm / sekcje jak w oryginale; wokal staje się twój) |
| B. Nowy utwór tym głosem | Nie przesłano song_clip_id |
Podajesz tylko głos + tekst (opcjonalnie) + wymagania stylu; model komponuje nową melodię w tym stylu i śpiewa |
resolved_scene w odpowiedzi zwraca cover lub sing, więc możesz potwierdzić, którą drogą poszło.
6.2 Pola żądania
| Pole | Typ | Wymagane | Domyślnie | Uwagi |
|---|---|---|---|---|
model |
string | Tak | — | Nazwa modelu dla klienta, patrz §6.5. Bez niej zwracane jest model is required (HTTP 500) |
voice_id |
string | Jedno z dwóch | — | ID głosu (vp_…); musi być status=ready |
voice_clip_id |
string | Jedno z dwóch | — | Można też podać clip id głosu; gdy oba, wygrywa voice_id |
song_clip_id |
string | Nie | puste | Clip id (song_id) utworu do coveru. Nieprzesłane = scenariusz B |
lyrics |
string | Nie | puste | Pełny tekst utworu, wysyłany znak po znaku, bez przepisywania i obcinania; ≤ 3000 znaków |
cover_requirements |
string | Nie | puste | Wskazówki do coveru w języku naturalnym, na przykład „wyraźniej artykułować". Są doklejane do stałego promptu |
style_requirements |
string | Nie | puste | Wymagania stylu, na przykład „wolny folk, gitara akustyczna" |
title |
string | Nie | puste | Tytuł tych dwóch utworów w obszarze roboczym (wpływa na song_title w późniejszych odpytaniach) |
negative_tags |
string | Nie | puste | Style do wykluczenia, na przykład elektronika, rap; ≤ 1000 znaków |
vocal_gender |
string | Nie | puste | m / f (przyjmuje też male / female); puste = bez znaczenia |
duration |
number | Nie | puste | Żądana długość w sekundach, liczba całkowita od 1 do 480; puste = decyduje platforma. Praktyczne minimum platformy to około 30 s: przy mniejszych wartościach w pomiarach i tak wychodziło około 30 sekund |
audio_weight |
number | Nie | 0,85 | Audio Influence, ułamek dziesiętny od 0 do 1. Wyżej = bliżej próbki głosu |
style_weight |
number | Nie | puste | Wpływ stylu, ułamek dziesiętny od 0 do 1 |
weirdness_constraint |
number | Nie | puste | Kreatywność, ułamek dziesiętny od 0 do 1 (jeśli interfejs używa procentów, podziel przez 100) |
variety |
number | Nie | puste | Różnorodność, liczba całkowita od 0 do 4 (nie procent), tylko w modelach v6 |
max_mode |
boolean | Nie | false |
Max Mode, cena ×2 |
client_request_id |
string | Nie | puste | Identyfikator wysyłki, zapisywany w serwerowym rekordzie zadania na potrzeby diagnostyki (bez deduplikacji) |
Zalecamy przesłanie też nagłówka X-Create-Ui-Client-Request-Id: <ten sam id wysyłki>: tylko on trafia do serwerowego rekordu zadania i służy jako klucz późniejszego dochodzenia (patrz §1.5).
Jednostki: audio_weight / style_weight / weirdness_constraint to ułamki od 0 do 1, variety to liczba całkowita od 0 do 4, a duration jest w sekundach. Pomylenie ich kończy się odrzuceniem albo dziwnym wynikiem.
Tekst utworu jest w scenariuszu B opcjonalny (model sam sobie poradzi), ale zawsze przesyłaj lyrics, gdy ma być zaśpiewana konkretna treść.
6.3 Odpowiedź
{
"code": 200,
"message": "success",
"data": {
"voice_id": "vp_20260926081712557959800Z5gvlt",
"voice_clip_id": "97ee62fe-56cd-473f-a2f5-c66ac0766a2e",
"song_clip_id": "5b773e9a-a035-4134-a4a4-29c9961d3ccb",
"resolved_scene": "cover",
"model": "suno-v6",
"audio_weight": 0.85,
"clips": [
{
"song_id": "0f2a…",
"status": "processing",
"song_title": "",
"model_version": "suno-v6",
"audio_url": "",
"play_url": "https://media.suno-api.io/play/0f2a…?expires=…&signature=…",
"lyrics": "",
"description": "[Zadanie] To jest cover. … (stały blok strukturalny serwera + twoje wymagania coveru / stylu)"
},
{
"song_id": "7c91…",
"status": "processing",
"model_version": "suno-v6",
"audio_url": ""
}
],
"source_updates": []
}
}
Najważniejsze:
- Gotowe utwory rozpoznasz po
clips[].song_id(ten interfejs nie zwraca polaid). - Od razu dostajesz 2 wartości
song_id, przy czymstatusto jeszczeprocessing(oznacza tylko przyjęcie), aaudio_urljest puste; przed pobraniem trzeba odpytywać docompleted.play_urlto strumień przedodsłuchu platformy, może pojawić się już przy wysyłce i wygaśnie. descriptionto prompt, który serwer ostatecznie wysyła (stały blok strukturalny + wpisane przez ciebiecover_requirements/style_requirements); bywa bardzo pomocny przy analizie wyniku.source_updatesto wynik przetwarzania materiałów po stronie serwera; klient może go zignorować.- Przesłany
titletrafia do serwerowego rekordu zadania i pojawia się jakosong_titlew późniejszych odpytaniach; pusteclips[].song_titlew odpowiedzi na wysyłkę jest normalne.
6.4 Błędy
{ "error": { "message": "ten głos nie istnieje lub został usunięty (voice_id=vp_xxx)…", "type": "new_api_error", "param": "", "code": "invalid_request" } }
| HTTP | message | Przyczyna |
|---|---|---|
| 500 | model is required |
W treści brakuje model (pole wymagane przy wyborze kanału) |
| 400 | voice_id is required and must be a ready voice |
Nie przesłano voice_id albo przesłano placeholder / niegotowy głos |
| 400 | ten głos nie istnieje lub został usunięty (voice_id=vp_xxx)… |
Głos został usunięty, nie istnieje lub nie należy do bieżącego konta. Użyj innego dostępnego głosu albo utwórz nowy |
| 400 | ten głos został usunięty (voice_id=vp_xxx)… |
Przy bezpośrednim przekazaniu materiału przez voice_clip_id głos tego materiału został usunięty; postępowanie jak wyżej |
| 400 | voice is not ready yet (status=processing) |
Głos wciąż się tworzy; poczekaj na ready i spróbuj ponownie |
| 400 | song_clip_id must be a real completed clip |
song_clip_id to placeholder / nie jest ukończony |
| 400 | song_clip_id must differ from the voice clip |
Obiektem coveru nie może być sama próbka głosu |
| 400 | audio_weight must be a number between 0 and 1 |
Błędna jednostka suwaka (wysłano procenty) |
| 400 | duration must be an integer between 1 and 480 seconds |
Długość nie jest liczbą całkowitą od 1 do 480 |
| 400 | vocal_gender must be one of m, f, male, female |
Nieprawidłowa wartość płci |
| 400 | variety must be an integer between 0 and 4 / variety is only supported on v6 models |
Nieprawidłowa wartość różnorodności lub model nieobsługiwany |
Niewystarczające saldo zwraca błąd rozliczenia już przy wysyłce i nigdy nie zostawia zadania w połowie.
6.5 Dostępne modele (nazwy dla klienta)
| Nazwa modelu | Uwagi |
|---|---|
suno-v6 |
Domyślny, zalecany |
suno-v6-wild |
Swobodniejszy |
suno-v6-mini |
Lekki |
Używaj nazw modeli dla klienta (tych powyżej). chirp-* to wewnętrzne nazwy platformy i nie należy ich używać bezpośrednio.
7. Śledzenie postępu
7.1 Odpytanie zbiorcze (zalecane)
POST /api/music/query
Content-Type: application/json
{ "model": "suno-v6", "song_ids": "id1,id2" }
song_idsto łańcuch rozdzielony przecinkami (nie tablica).- Odpowiedź to goła tablica (od razu
[...], bez otoczkisuccess/data):
[
{
"song_id": "0f2a…",
"song_title": "Dwa tygrysy",
"status": "completed",
"audio_url": "https://suno-api-hk-1437223057.cos.ap-hongkong.myqcloud.com/assets/0f2a…-mp3.mp3",
"cover_url": "https://cdn2.suno.ai/image_0f2a….jpeg",
"duration": 115.15,
"model_version": "suno-v6",
"generation_type": "voice_profile_cover",
"play_url": "https://media.suno-api.io/play/…?expires=…&signature=…",
"lyrics": "[Verse 1]…",
"prompt": "[Verse 1]…",
"description": "[Zadanie] To jest cover. … (ostateczny prompt serwera)",
"style_tags": "…",
"created_at": "2026-09-25T18:19:09.918Z",
"video_url": ""
}
]
| Pole | Uwagi |
|---|---|
status |
Patrz §1.7; tylko completed liczy się jako gotowe |
audio_url |
Bezpośredni link mp3; wypełniany dopiero od completed |
cover_url |
Adres okładki |
duration |
Rzeczywista długość w sekundach |
generation_type |
Utwory z coveru z głosem to zawsze voice_profile_cover |
play_url |
Podpisany adres przedodsłuchu (wygasa) |
song_title |
Tytuł zadania (przesłany title; bez niego serwer wstawia wartość domyślną) |
lyrics / prompt |
Gotowy tekst / oryginalny tekst |
description |
Ostateczny prompt wysyłany przez serwer (łącznie ze stałym blokiem strukturalnym) |
style_tags |
Ostateczny opis stylu |
created_at |
Łańcuch ISO 8601 (uwaga: inny niż sekundy Unix interfejsu szczegółów) |
Rada dotycząca odpytania: co 5–10 sekund, z łącznym limitem 10–15 minut (najwolniejsze zmierzone „zimne" konto zajęło około 4,5 minuty; bardzo niewiele dłużej). Zakończenia nie oceniaj po pustym audio_url, tylko po status.
Uwaga o zgodności: ten interfejs identyfikuje utwory po
song_id; w kilku wczesnych odpowiedziach pojawiało się poleid, więcrow.song_id || row.idto bezpieczny sposób odczytu.
7.2 Szczegóły jednego utworu
GET /api/music/songs/{song_id}
{
"success": true,
"data": {
"song_id": "0f2a…",
"title": "Dwa tygrysy",
"status": "completed",
"generation_type": "voice_profile_cover",
"model": "suno-v6",
"duration": 115.15,
"audio_url": "https://…/assets/0f2a…-mp3.mp3",
"image_url": "https://cdn2.suno.ai/image_0f2a….jpeg",
"wav_url": "https://www.suno-api.io/api/music/download?song_id=0f2a…&kind=wav",
"video_url": "https://www.suno-api.io/api/music/download?song_id=0f2a…&kind=video",
"created_at": 1790411012,
"completed_at": 1790411500,
"parameters": {
"prompt": "[Verse 1]…",
"style_tags": "…",
"title": "Dwa tygrysy",
"model": "suno-v6",
"generation_type": "voice_profile_cover",
"source_song_id": "5b773e9a-…"
},
"parameter_retention": {
"core_parameters_available": true,
"extended_parameters_available": false,
"sources": ["suno_tasks"],
"unavailable_fields": ["negative_tags", "vocal_gender", "style_weight", "weirdness_constraint"]
}
}
}
- Tutaj
created_at/completed_atto sekundy Unix (inaczej niż łańcuchy ISO w odpytaniu zbiorczym, więc klienci powinni je rozróżniać). wav_url/video_urlto punkty wejścia pobierania tej platformy (względne wobec bieżącej domeny), aGETpobiera plik; są puste, gdy platforma nie wytworzyła takiego materiału.parameter_retentionmówi, do których parametrów wysyłki da się dotrzeć:core_parameters_available=trueoznacza, że parametry kluczowe (tekst / styl / źródło) są dostępne, a przyextended_parameters_available=falsewymienione wyżej parametry rozszerzone nie zostały zachowane (covery z głosem są obecnie w tej kategorii).
7.3 Moje utwory
GET /api/music/songs?p=1&page_size=20
GET /api/music/songs?status=completed&q=słowo kluczowe
Parametry stronicowania: p (numer strony od 1) / page_size (elementy na stronę; zgodny zapis ps). Opcjonalne status i q (słowo kluczowe w tytule). Domyślnie sortowanie po czasie utworzenia malejąco.
{
"success": true,
"data": {
"page": 1,
"page_size": 20,
"total": 42,
"items": [
{
"song_id": "0f2a…",
"title": "Dwa tygrysy",
"status": "completed",
"generation_type": "voice_profile_cover",
"model": "suno-v6",
"duration": 115.15,
"audio_url": "https://…/assets/0f2a…-mp3.mp3",
"image_url": "https://cdn2.suno.ai/image_0f2a….jpeg",
"created_at": 1790411012,
"completed_at": 1790411500
}
]
}
}
Po generation_type=voice_profile_cover odróżnisz „utwory z coveru z głosem" od innych wyników generowania.
8. Pobieranie gotowych utworów
8.1 Wzięcie mp3 wprost (zalecane, bezpłatne)
Każdy z trzech sposobów działa; wybierz jeden:
- Użyć
audio_urlz wyniku odpytania (bezpośredni link do pamięci obiektowej, najprościej). GET /api/music/download?song_id=<id>&kind=mp3→ od razu zwraca strumień bajtów audio (z nazwą pliku już wContent-Disposition).POST /api/music/download-url(aby dostać podpisany adres tymczasowy).
curl -sS -L "https://www.suno-api.io/api/music/download?song_id=0f2a…&kind=mp3" \
-H "Authorization: Bearer $API_KEY" -o song.mp3
Wartości kind: mp3 (odpowiednik song) / playback (odtwarzanie strumieniowe) / wav / video / lyrics / timestamped_lyrics.
timestamped_lyrics (.lrc) jest obecnie dostępne tylko dla części utworów; jeśli się nie uda, wygeneruj plik samodzielnie przez API tekstu ze znacznikami czasu.
Odpowiedź to czysty strumień bajtów pliku, z ustawionym Content-Type i Content-Disposition (nazwa pliku); wav_url / video_url zwracane przez GET /api/music/songs/{song_id} to to samo wejście z kind=wav|video.
8.2 Konwersja do wav / tekst utworu / metadane (płatne)
POST /api/music/free2
Content-Type: application/json
{ "song_ids": ["0f2a…"], "files": ["mp3", "wav", "lyrics"] }
{
"success": true,
"data": {
"songs": [
{ "song_id": "0f2a…", "files": [ { "type": "mp3", "url": "https://…" }, { "type": "wav", "url": "https://…" } ] }
],
"requested_songs": 1,
"succeeded_songs": 1,
"price": 0.2
}
}
filesprzyjmuje:mp3/wav/lyrics/metadata, maksymalnie 10 utworów naraz.- Rozliczenie za udany utwór (0,2 ¥ za sztukę); utwór, który zawiódł w całości, nie jest obciążany, a nieudany format pojawia się tylko w
songs[].errors. - Aby ponownie pobrać już pobrane pliki, użyj najpierw bezpłatnego
POST /api/music/free2/cached(te samesong_ids+files) i pobierz adresy archiwalne; jegosongs[].missing_fileswymienia formaty bez pamięci podręcznej, które trzeba przygotować od nowa.
9. Odpytanie cen
GET /api/pricing/catalog
Publiczny interfejs bez uwierzytelniania. Wszystkie ceny jednostkowe, które klient ma pokazać, są w data.catalog.meta (łańcuchy):
| Klucz | Znaczenie | Bieżąca wartość |
|---|---|---|
generation_price |
Zwykłe generowanie | 0,6 |
voice_generation_price |
Cena bazowa coveru z głosem | 1,2 |
max_mode_factor |
Mnożnik Max Mode | 2 |
enhanced_upload_price |
Wzmocnione klonowanie / wzmocnione przesyłanie | 10 |
voice_auto_verify_price |
Automatyczna weryfikacja głosu | 5 |
voice_long_term_clone_price |
Długoterminowe klonowanie głosu | 5 |
Ceny są zmieniane w back-office, więc czytaj je na bieżąco, a nie wpisuj na sztywno w kliencie. Rzeczywiste obciążenie za cover = voice_generation_price × (przy prawdziwym max_mode jeszcze × max_mode_factor).
10. Limity i ostrzeżenia
- Rozmiar przesłania: ≤ 10 MB (serwer przyjmuje więcej, ale brama wejściowa obcina zbyt duże treści na 10 MiB, co wygląda jak „odrzucone przez Suno"; zablokuj to wcześniej po swojej stronie).
- Długość próbki: minimum 6 s, zalecane 10–60 s; za krótka zostanie odrzucona.
- Zawartość próbki: czysty wokal; unikaj wszystkiego, co jest bardzo podobne do istniejącego nagrania (porównanie z katalogiem to odrzuci).
- Limity tekstu:
lyrics≤ 3000 znaków; dlastyle_requirements/negative_tags/titlezalecane 1000 / 1000 / 100 znaków (wymagania stylu i coveru są doklejane do promptu, trzymaj sumę w granicach 3000 znaków). - Tekst utworu nie jest przepisywany: śpiewane jest to, co przekażesz (znak po znaku), bez lokalnego obcinania.
- Każdy utwór daje 2 ślady; nie zakładaj jednego wyniku.
- Źródłowe audio jest zachowywane na stałe: usunięcie głosu nie czyści jego źródłowego audio; dzięki temu możliwe są kolejne covery, a zgodność pozostaje identyfikowalna.
- Głos musi być gotowy: głos w stanie
processingnie może być użyty do coveru. - Limit czasu żądania: na „zimnym" koncie pierwsze wysłanie w pomiarach zajęło do około 4,5 minuty, ustaw więc limit czasu klienta na ≥ 6 minut. Covery nie deduplikują się na poziomie żądania, więc po przekroczeniu czasu sprawdź, czy nie pojawił się już nowy utwór (§1.5), zanim zdecydujesz o ponowieniu.
- Własność głosu: głosy należą do twórcy; cover przyjmuje tylko głosy gotowe i nieusunięte. Głos nieistniejący, usunięty lub z innego konta zwraca 400:
ten głos nie istnieje lub został usunięty (voice_id=…).
11. Najczęstsze pytania (FAQ)
P1. Czy utworzenie głosu kosztuje? Zwykłe utworzenie i „utworzenie z istniejącego audio" są bezpłatne; płatne są tylko covery (1,2 ¥ / MAX 2,4 ¥) i wzmocnione klonowanie (domyślnie 10 ¥).
P2. Czy mogę użyć jako próbki gotowego utworu z podkładem?
Niezalecane. Wszystko z muzyką lub bardzo podobne do istniejącego nagrania w katalogu platforma odrzuca (This audio matches an existing recording in our catalog.). Użyj nagrania czysto wokalnego, suchego.
P3. Dlaczego audio_url jest puste po wysłaniu coveru?
Wysłanie oznacza tylko przyjęcie, a status to jeszcze processing. Adres do odtwarzania/pobrania pojawia się dopiero po odpytaniu /api/music/query do status=completed.
P4. Czy w scenariuszu B (bez song_clip_id) trzeba przesłać tekst?
Opcjonalnie. Prześlij lyrics, aby zaśpiewać konkretną treść; bez tego model poradzi sobie sam, ale z mniejszą kontrolą.
P5. Czy audio przesłane przez klienta może od razu służyć jako głos?
Tak: przez formę file_url w create albo najpierw wysyłając je jako utwór i wywołując potem create-from-clip.
P6. Czy przy niepowodzeniu pieniądze są zwracane?
Żądanie odrzucone od razu (błędne parametry / błąd platformy) nie jest obciążane, zgodnie z pomiarami; przyjęte, ale ostatecznie nieudane zadanie zwraca pobraną z góry kwotę. Przy ostatecznym niepowodzeniu zadanie zwraca status=failed oraz error_message.
P7. Po usunięciu głosu czy mogę nadal słuchać utworów nim wygenerowanych? Tak. Usunięcie wpływa tylko na to, czy tego głosu można użyć do nowych coverów.
P8. Jak długi utwór mogę objąć coverem naraz?
duration przyjmuje 1–480 sekund; bez podania decyduje platforma na podstawie oryginału / materiału. Uwaga: gotowe ślady platformy mają co najmniej około 30 sekund; przy mniejszej wartości w pomiarach i tak wychodziło 29,96 / 29,76 sekundy.
Załącznik A: pełny przykład (Node.js, z odpytaniem i pobieraniem)
const BASE = "https://www.suno-api.io";
const KEY = process.env.SUNO_API_KEY;
const H = { Authorization: `Bearer ${KEY}` };
// ① Utwórz głos (multipart)
async function createVoice(filePath, title) {
const fd = new FormData();
fd.set("file", new Blob([await (await import("node:fs/promises")).readFile(filePath)], { type: "audio/mpeg" }), "my-voice.mp3");
fd.set("file_name", "my-voice.mp3");
fd.set("source_file_name", "my-voice.mp3");
fd.set("title", title);
fd.set("client_request_id", `vp-create-${Date.now()}`);
const res = await fetch(`${BASE}/api/music/voice-profile/create`, { method: "POST", headers: H, body: fd });
const body = await res.json();
if (!body.success) throw new Error(body.message);
return body.data; // { voice_id, status, audio_url, ... }
}
// ② Cover
async function cover(voiceId, songClipId, lyrics) {
const submissionId = `vp-cover-${Date.now()}`;
const res = await fetch(`${BASE}/api/music/voice-profile/cover`, {
method: "POST",
headers: { ...H, "Content-Type": "application/json", "X-Create-Ui-Client-Request-Id": submissionId },
body: JSON.stringify({
model: "suno-v6",
voice_id: voiceId,
song_clip_id: songClipId || "",
lyrics: lyrics || "",
style_requirements: "wolny folk, gitara akustyczna",
audio_weight: 0.85,
max_mode: false,
client_request_id: submissionId,
}),
});
const body = await res.json();
if (body.error) throw new Error(body.error.message);
return body.data; // { resolved_scene, clips: [{ song_id, status }] }
}
// ③ Odpytuj do zakończenia (co 5 sekund, maksymalnie 15 minut)
async function waitUntilCompleted(songIds) {
const deadline = Date.now() + 15 * 60 * 1000;
while (Date.now() < deadline) {
const res = await fetch(`${BASE}/api/music/query`, {
method: "POST",
headers: { ...H, "Content-Type": "application/json" },
body: JSON.stringify({ model: "suno-v6", song_ids: songIds.join(",") }),
});
const songs = await res.json(); // goła tablica
if (songs.every((s) => s.status === "completed" || s.status === "failed")) return songs;
await new Promise((r) => setTimeout(r, 5000));
}
throw new Error("timeout waiting for cover");
}
// ④ Pobieranie
async function download(songId, outPath) {
const res = await fetch(`${BASE}/api/music/download?song_id=${encodeURIComponent(songId)}&kind=mp3`, { headers: H });
if (!res.ok) throw new Error(`download failed: ${res.status}`);
(await import("node:fs/promises")).writeFile(outPath, Buffer.from(await res.arrayBuffer()));
}
const voice = await createVoice("./my-voice.mp3", "Mój głos");
const result = await cover(voice.voice_id, "5b773e9a-a035-4134-a4a4-29c9961d3ccb", "[Verse 1]\ntekst…");
const ids = result.clips.map((c) => c.song_id);
const songs = await waitUntilCompleted(ids);
for (const [i, s] of songs.entries()) {
if (s.status === "completed") await download(s.song_id, `./out-${i}.mp3`);
}
Załącznik B: historia zmian
| Data | Zmiana |
|---|---|
| 2026-10-15 | Semantyka usuwania podana wprost (§5.3); cover z głosem „usuniętym / bez uprawnień" zwraca teraz 400 przed jakimkolwiek pobraniem z góry, a tabela błędów i FAQ zostały zsynchronizowane (razem z wdrożoną tego dnia blokadą usuwania głosów) |
| 2026-10-13 | Na początku dodano wyjaśnienie „dlaczego zalecamy ten łańcuch": według realnych ocen wielu użytkowników utwory z tego łańcucha znacznie lepiej zachowują oryginalny głos |
| 2026-09-26 | Pierwsza wersja: utworzenie głosu (trzy formy wejścia) / utworzenie z istniejącego audio / lista, szczegóły, usuwanie / cover z głosem (scenariusze A i B) / odpytanie postępu / pobieranie / odczyt cen, ze zmierzonymi dowodami |
Uzyskaj klucz API
Po rejestracji utwórz klucz API w konsoli. Każde generowanie kosztuje 0,6 ¥ i zwraca 2 utwory, pobierania są nieograniczone, a numer telefonu nie jest wymagany.
Pobierz klucz API Powrót do przeglądu