Create Persona from a song
curl --request POST \
--url https://apistable.ai/api/v1/tasks/create_task \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "suno_persona_create",
"input": {
"persona_model": "style_persona",
"audio_id": "YOUR_AUDIO_ID",
"name": "My style"
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: 'suno_persona_create',
input: {persona_model: 'style_persona', audio_id: 'YOUR_AUDIO_ID', name: 'My style'}
})
};
fetch('https://apistable.ai/api/v1/tasks/create_task', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://apistable.ai/api/v1/tasks/create_task"
payload = {
"model": "suno_persona_create",
"input": {
"persona_model": "style_persona",
"audio_id": "YOUR_AUDIO_ID",
"name": "My style"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"code": 200,
"msg": "success",
"data": {
"task_id": "<string>"
}
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}Suno
Create Persona from a song
A style Persona uses an audio ID directly. A Voice Persona uses prepared material and a selected segment.
POST
/
api
/
v1
/
tasks
/
create_task
Create Persona from a song
curl --request POST \
--url https://apistable.ai/api/v1/tasks/create_task \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "suno_persona_create",
"input": {
"persona_model": "style_persona",
"audio_id": "YOUR_AUDIO_ID",
"name": "My style"
}
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: 'suno_persona_create',
input: {persona_model: 'style_persona', audio_id: 'YOUR_AUDIO_ID', name: 'My style'}
})
};
fetch('https://apistable.ai/api/v1/tasks/create_task', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://apistable.ai/api/v1/tasks/create_task"
payload = {
"model": "suno_persona_create",
"input": {
"persona_model": "style_persona",
"audio_id": "YOUR_AUDIO_ID",
"name": "My style"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"code": 200,
"msg": "success",
"data": {
"task_id": "<string>"
}
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}{
"code": 123,
"msg": "<string>",
"data": null
}Operations are enabled individually by server configuration. Disabled operations return 503 without a task. Music credit deduction is currently disabled.
Using this operation
A style Persona uses an audio ID directly. A Voice Persona uses prepared material and a selected segment.-
- Prepare the fields shown in the example below. Replace sample URLs and IDs with resources you can access.
-
- Set model to suno_persona_create and place the parameters inside input. Submit once and save the returned task_id.
-
- Query the saved task or receive its callback. A processing result is not a reason to submit the operation again.
- Keep result.persona_id together with persona_model. Pass both to a generation operation that supports that Persona type.
Create task
Send model and input to the common task endpoint. callback_url is an optional top-level public HTTPS address. All resource IDs are APIstable IDs owned by your account. Music credit deduction is currently disabled.{
"model": "suno_persona_create",
"input": {
"persona_model": "style_persona",
"audio_id": "YOUR_AUDIO_ID",
"name": "My style"
}
}
Acceptance response
HTTP 200 confirms acceptance, not completion. Query GET /api/v1/tasks/{task_id} until data.status is succeeded or failed. Read data.result only after success; a failed task has its error in data.message.{
"code": 200,
"msg": "success",
"data": {
"task_id": "YOUR_TASK_ID"
}
}
Fields: persona_model = style_persona
| Field | Type | Required | Description and limits |
|---|---|---|---|
| persona_model | string | Yes | style_persona or voice_persona; must match the resource’s actual origin. = style_persona |
| audio_id | string | Yes | APIstable song ID belonging to your account. Cover/extend accept this ID only, without a source task_id or external URL. maxLength: 200 |
| source_audio_ids | array | No / conditional | Optional APIstable IDs of original generated songs used as Persona references. Defaults to the source song; uploaded songs are rejected. minItems: 1 |
| image_url | string | No / conditional | Optional public HTTPS cover image: JPEG/PNG/WebP/BMP, up to 10 MiB. |
| name | string | Yes | Voice or Persona display name. maxLength: 100 |
| description | string | No / conditional | Voice or Persona description. maxLength: 1000 |
Fields: persona_model = voice_persona
| Field | Type | Required | Description and limits |
|---|---|---|---|
| persona_model | string | Yes | style_persona or voice_persona; must match the resource’s actual origin. = voice_persona |
| prepared_audio_id | string | Yes | APIstable prepared vocal ID from suno_persona_prepare. maxLength: 200 |
| name | string | Yes | Voice or Persona display name. maxLength: 100 |
| description | string | No / conditional | Voice or Persona description. maxLength: 1000 |
| vocal_start_s | number | Yes | Selected vocal start in seconds, at most two decimal places. Use the original recording for Voice upload and the prepared vocal timeline for song Persona. min: 0 |
| vocal_end_s | number | Yes | Selected vocal end in seconds, at most two decimal places; after start and within the audio. Song Voice Persona requires a 10–30 second range. min: 0 |
| user_input_styles | string | No / conditional | Optional style description for a generated Voice Persona. maxLength: 1000 |
Inputs and limits
The schema lists supported fields, types and basic limits. Also follow Important conditions: cross-field and source-resource checks are not fully represented in JSON Schema. Unknown parameters are rejected. URL fields accept public HTTPS URLs, never file objects.{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"oneOf": [
{
"type": "object",
"properties": {
"persona_model": {
"type": "string",
"const": "style_persona",
"description": "style_persona or voice_persona; must match the resource's actual origin."
},
"audio_id": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "APIstable song ID belonging to your account. Cover/extend accept this ID only, without a source task_id or external URL."
},
"source_audio_ids": {
"minItems": 1,
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "APIstable resource ID; never a supplier ID."
},
"description": "Optional APIstable IDs of original generated songs used as Persona references. Defaults to the source song; uploaded songs are rejected."
},
"image_url": {
"type": "string",
"format": "uri",
"description": "Optional public HTTPS cover image: JPEG/PNG/WebP/BMP, up to 10 MiB."
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "Voice or Persona display name."
},
"description": {
"type": "string",
"maxLength": 1000,
"description": "Voice or Persona description."
}
},
"required": [
"persona_model",
"audio_id",
"name"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"persona_model": {
"type": "string",
"const": "voice_persona",
"description": "style_persona or voice_persona; must match the resource's actual origin."
},
"prepared_audio_id": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "APIstable prepared vocal ID from suno_persona_prepare."
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"description": "Voice or Persona display name."
},
"description": {
"type": "string",
"maxLength": 1000,
"description": "Voice or Persona description."
},
"vocal_start_s": {
"type": "number",
"minimum": 0,
"description": "Selected vocal start in seconds, at most two decimal places. Use the original recording for Voice upload and the prepared vocal timeline for song Persona."
},
"vocal_end_s": {
"type": "number",
"minimum": 0,
"description": "Selected vocal end in seconds, at most two decimal places; after start and within the audio. Song Voice Persona requires a 10–30 second range."
},
"user_input_styles": {
"type": "string",
"maxLength": 1000,
"description": "Optional style description for a generated Voice Persona."
}
},
"required": [
"persona_model",
"prepared_audio_id",
"name",
"vocal_start_s",
"vocal_end_s"
],
"additionalProperties": false
}
]
}
Important conditions
- Style Persona requires audio_id; optional source_audio_ids must contain generated songs. Uploaded audio and its derivatives are rejected. A supplied source_audio_ids list replaces the default single source rather than appending to it. Optional cover: JPEG/PNG/WebP/BMP, at most 10 MiB.
- Voice Persona requires an unexpired prepared_audio_id. Select 10–30 seconds inside the prepared vocal timeline, with start/end at most two decimal places. Use only fields from the selected persona_model branch.
- Uploaded files last 24 hours, generated files 14 days and task details 30 days. Reused files keep their original expiry. Valid Voice/Persona identity mappings are separate from task-log cleanup. Download files you need to retain.
Result schema
The creation response is {code:200,msg:“success”,data:{task_id}}. Poll GET /api/v1/tasks/{task_id}. On success, data.result is an object matching the schema below; it is otherwise null. input remains a JSON string.{
"type": "object",
"required": [
"persona_id",
"persona_model",
"name",
"description"
],
"properties": {
"persona_id": {
"type": "string"
},
"persona_model": {
"enum": [
"style_persona",
"voice_persona"
]
},
"name": {
"type": "string"
},
"description": {
"type": "string"
}
},
"additionalProperties": false
}
Related workflows
Voice: all four steps File uploads CallbacksAuthorizations
Every valid key can submit and query its own account. Revoked keys are rejected.
Body
application/json