complete voice persona
curl --request POST \
--url https://api.mountsea.ai/suno/v2/voicePersona/complete \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"taskId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"verification_audio_url": "https://example.com/verification.wav",
"name": "My Voice",
"description": "<string>",
"is_public": false,
"image_s3_id": "<string>"
}
'import requests
url = "https://api.mountsea.ai/suno/v2/voicePersona/complete"
payload = {
"taskId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"verification_audio_url": "https://example.com/verification.wav",
"name": "My Voice",
"description": "<string>",
"is_public": False,
"image_s3_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
taskId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
verification_audio_url: 'https://example.com/verification.wav',
name: 'My Voice',
description: '<string>',
is_public: false,
image_s3_id: '<string>'
})
};
fetch('https://api.mountsea.ai/suno/v2/voicePersona/complete', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mountsea.ai/suno/v2/voicePersona/complete",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'taskId' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
'verification_audio_url' => 'https://example.com/verification.wav',
'name' => 'My Voice',
'description' => '<string>',
'is_public' => false,
'image_s3_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.mountsea.ai/suno/v2/voicePersona/complete"
payload := strings.NewReader("{\n \"taskId\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n \"verification_audio_url\": \"https://example.com/verification.wav\",\n \"name\": \"My Voice\",\n \"description\": \"<string>\",\n \"is_public\": false,\n \"image_s3_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mountsea.ai/suno/v2/voicePersona/complete")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"taskId\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n \"verification_audio_url\": \"https://example.com/verification.wav\",\n \"name\": \"My Voice\",\n \"description\": \"<string>\",\n \"is_public\": false,\n \"image_s3_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mountsea.ai/suno/v2/voicePersona/complete")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"taskId\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n \"verification_audio_url\": \"https://example.com/verification.wav\",\n \"name\": \"My Voice\",\n \"description\": \"<string>\",\n \"is_public\": false,\n \"image_s3_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"taskId": "15c257ff-43f7-4678-bd41-202ad6b8488b"
}Voice Persona
Voice Persona Complete
Upload verification recording and create voice persona
POST
/
suno
/
v2
/
voicePersona
/
complete
complete voice persona
curl --request POST \
--url https://api.mountsea.ai/suno/v2/voicePersona/complete \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"taskId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"verification_audio_url": "https://example.com/verification.wav",
"name": "My Voice",
"description": "<string>",
"is_public": false,
"image_s3_id": "<string>"
}
'import requests
url = "https://api.mountsea.ai/suno/v2/voicePersona/complete"
payload = {
"taskId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"verification_audio_url": "https://example.com/verification.wav",
"name": "My Voice",
"description": "<string>",
"is_public": False,
"image_s3_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
taskId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
verification_audio_url: 'https://example.com/verification.wav',
name: 'My Voice',
description: '<string>',
is_public: false,
image_s3_id: '<string>'
})
};
fetch('https://api.mountsea.ai/suno/v2/voicePersona/complete', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mountsea.ai/suno/v2/voicePersona/complete",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'taskId' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
'verification_audio_url' => 'https://example.com/verification.wav',
'name' => 'My Voice',
'description' => '<string>',
'is_public' => false,
'image_s3_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.mountsea.ai/suno/v2/voicePersona/complete"
payload := strings.NewReader("{\n \"taskId\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n \"verification_audio_url\": \"https://example.com/verification.wav\",\n \"name\": \"My Voice\",\n \"description\": \"<string>\",\n \"is_public\": false,\n \"image_s3_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mountsea.ai/suno/v2/voicePersona/complete")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"taskId\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n \"verification_audio_url\": \"https://example.com/verification.wav\",\n \"name\": \"My Voice\",\n \"description\": \"<string>\",\n \"is_public\": false,\n \"image_s3_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mountsea.ai/suno/v2/voicePersona/complete")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"taskId\": \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\",\n \"verification_audio_url\": \"https://example.com/verification.wav\",\n \"name\": \"My Voice\",\n \"description\": \"<string>\",\n \"is_public\": false,\n \"image_s3_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"taskId": "15c257ff-43f7-4678-bd41-202ad6b8488b"
}This is Phase 2 of the free Init + Complete Voice Persona flow. Same result as paid Clone Voice. Finish Phase 1: Init first and wait for
awaiting. See the full workflow guide.taskId returned by init. After calling complete, continue polling the same taskId until status becomes success.
You must call this endpoint within 30 seconds of the task reaching
awaiting status. Exceeding this timeout causes the task to fail with VP_USER_TIMEOUT.No intermediate data (
vox_audio_id, phrase_id, etc.) is needed — the system reads them automatically from the init phase. Just pass taskId, verification_audio_url, name, and optional fields.Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json
init 返回的 taskId(同一个任务)
Example:
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
用户朗读验证短语后的录音 URL(WAV/MP3)
Example:
"https://example.com/verification.wav"
Persona 名称
Example:
"My Voice"
Persona 描述
是否公开,默认 false
Example:
false
封面图片(base64 或 null 自动生成)
Response
201 - application/json
task id. Use this id to query task status.
Example:
"15c257ff-43f7-4678-bd41-202ad6b8488b"