Suno Studio Project Integration Guide
POST https://api.fishapi.cloud/suno/projects is the Beta API for managing multitrack projects. Use action to distinguish between creating, saving, generating candidates, committing candidates, and exporting.
POST /suno/projects
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Idempotency-Key: <a new UUID for each write operation>
Except for retrieve, every operation requires Idempotency-Key. The same key with the same request only returns the original result; the same key with a different request returns 409. When a paid generation encounters a network timeout or an uncertain submission result, first query using the original task ID or the same idempotency key; do not directly resend with a different key.
¶ Identifiers and Time Units
| Name | Where to Obtain It | Where to Use It |
|---|---|---|
id |
data.id in the create response |
All subsequent requests for the current project |
version_id |
data.version_id from the most recent retrieve, save, add_track, commit_candidate, or remove_track |
Modification, candidate generation, and export; the latest version must be used |
audio_id / source_audio_id |
response.data.candidate.audio_id upon upload completion, or an existing completed audio ID |
Referencing the original audio when using add_track, generating, or replacing |
render_audio_id |
response.data.audio_id upon render completion |
Project mix reference for generate_track |
operation_id |
response.data.operation_id upon generate_track or replace_section completion |
commit_candidate; it is usually the same as the generation task's task_id, but the return value should be read |
candidate_id |
response.data.candidates[].id upon generation completion |
Selecting a candidate to commit |
track_id |
data.state.tracks[].id in the project |
Committing a candidate or deleting a track |
task_id |
Asynchronous operation submission response | Query the final status using /suno/tasks; it is not a project ID |
start_seconds / end_seconds are seconds within the source audio; start_beats / end_beats are beats on the project timeline. state.timing.bps is beats per second, with a default of 2. For example, a 41-second clip starting at beat 0 has a default endpoint of beat 82. The seconds range for generate_track is used to specify the generation reference and does not guarantee that a candidate will only have the length of that range.
¶ Operation Flow
| Order | action |
Purpose | Return Method |
|---|---|---|---|
| 1 | create |
Create an empty project | Synchronous project data |
| 2 | retrieve |
Read the latest version and complete state |
Synchronous project data |
| 3 | save |
Save for the first time or save the modified overall state |
Synchronous project data |
| 4 | upload |
Create an asset from an HTTPS audio URL | Asynchronous task |
| 5 | add_track |
Place asset audio into the project | Asynchronous task, updates version |
| 6 | save |
To receive new track candidates, first save an empty target track | Synchronous project data, updates version |
| 7 | render |
Export currently audible tracks and obtain the mix reference audio_id |
Asynchronous task |
| 8 | generate_track or replace_section |
Generate new track candidates or partial replacement candidates respectively | Asynchronous task, does not modify the project yet |
| 9 | commit_candidate |
Select and commit a candidate | Asynchronous task, updates version after success |
| Optional | remove_track |
Delete the specified track | Synchronous project data, updates version |
If only performing a partial replacement, an existing usable source audio is sufficient, and render is not required first; if the source audio is already in the project, upload and add_track can also be skipped. render_audio_id is only the required reference for generate_track.
When an asynchronous operation is submitted, it first returns { "task_id": "...", "trace_id": "..." }, which does not indicate successful generation. Poll:
POST /suno/tasks
Content-Type: application/json
{"action":"retrieve","id":"the task_id returned in the previous step"}
A task is considered successful only when the task record has finished_at and its response.success is true; when response.success=false, read response.error. Although save may include task_id, it completes synchronously within this API. upload, render, generate_track, and replace_section do not modify the project version; after save, add_track, commit_candidate, and remove_track succeed, the new version_id should be obtained.
¶ Request Conventions
| Parameter | Type and Applicable Scope | Description |
|---|---|---|
action |
Required string | Fixed to one of the operation names listed on this page; each request executes only one operation. |
id |
Required string except for create |
Project ID, from create.data.id. |
version_id |
Required string when modifying, generating candidates, or exporting; may be omitted for the first save of an empty project |
Use the latest version; old versions will be rejected. retrieve does not require it. |
Idempotency-Key |
Required request header except for retrieve, 1–128 characters |
Use a new key for each new operation; the same key and request returns the original result without regenerating or charging again. |
async |
Optional boolean for upload, add_track, generate_track, replace_section, commit_candidate, and render |
These operations are always asynchronous; false also will not make generation synchronous. |
callback_url |
Optional URL for asynchronous operations | Receives final status notifications; when omitted, query /suno/tasks by task_id. response.success must still be checked. |
The following examples demonstrate the passing of IDs and versions between operations. Responses only list fields related to the current step; during integration, replace the example IDs with response values from the current application.
¶ Creating and Retrieving Projects
| Operation | Parameter | Type and Description |
|---|---|---|
create |
title |
Required string, 1–200 characters; title of the new project. |
retrieve |
No operation-specific parameters | Use the project id to read the current version and complete state; no idempotency key is required. |
¶ Create Project: create
Request:
{
"action": "create",
"title": "Suno Projects Documentation Verification 2026-10-09"
}
Response:
{
"success": true,
"trace_id": "42408a82-988b-4127-ba68-9b89348a7c56",
"data": {
"id": "af0e104a-2a4c-40e0-9c70-7614566824a6",
"title": "Suno Projects Documentation Verification 2026-10-09",
"state": {
"tracks": [],
"timing": {
"bps": 2
}
}
}
}
¶ Retrieve Project: retrieve
Request:```json { "action": "retrieve", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6" }
Response:
{ "success": true, "trace_id": "a335ceac-5cb7-4b1c-9773-77b9d5c84bd7", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "title": "Suno Projects Documentation Verification 2026-10-09", "state": { "tracks": [], "timing": { "bps": 2 } } } }
## Save Project State
| Parameter | Type and Description |
|---|---|
| `state` | Required object. Submit the **complete project state**, not a partial patch; base it on the `data.state` returned by the most recent retrieve or modify operation, retaining unknown fields. |
| `title` | Optional string; when omitted, use `state.title`; if that is also absent, use the default title. |
| `version_id` | May be omitted when first saving a newly created empty project; afterward, the latest version must be used. |
`state.timing.bps` must be a positive number, defaulting to 2. `state.tracks` is the track array; `clipId` of existing audio clips references the audio ID, and `startBeats`, `endBeats`, and `readStartBeats` use project beat units. The safest editing method is to retrieve the complete `state`, modify only the target track or clip, and then `save` it as a whole. A newly added empty target track must have at least a unique `id`, `type:"audio"`, and `clips:[]`; see the example in “Generate New Tracks” for the complete empty track structure. Do not directly use beat points from audio analysis results as project timeline coordinates.
### First Save: `save`
A new project has no `version_id`; omit it for the first save:
{ "action": "save", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "title": "Suno Projects Documentation Verification 2026-10-09", "state": { "tracks": [], "timing": { "bps": 2 } } }
Response:
{ "success": true, "task_id": "ab172b47-4d89-404b-a10e-71f67c36ccba", "trace_id": "fc7b2e43-7a7a-4276-8671-27008a1153ea", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "8f0c62fb-304f-420e-9707-426e8b64b5e3", "state": { "timing": { "bps": 2 }, "tracks": [] } } }
## Upload Audio and Add Tracks
| Operation | Parameter | Type and Description |
|---|---|---|
| `upload` | `audio_url` | Required HTTPS URL, pointing to audio that is publicly accessible and that you have the right to use. The `candidate.audio_id` in the terminal state can be used to add a track. |
| `add_track` | `audio_id` | Required string; the audio ID of completed material, not a URL. |
| `add_track` | `name`, `color` | Optional strings; the track name defaults to the audio title, the recommended color is `#RRGGBB`, and the default is `#7251F7`. |
| `add_track` | `title` | Optional string; also modifies the project title, and is usually omitted. |
| `add_track` | `start_beats`, `end_beats` | Optional non-negative numbers; the endpoint must be greater than the starting point; by default, it starts from beat 0, and the endpoint is calculated based on the audio duration and `timing.bps`. |
| `add_track` | `gain` | Optional non-negative number, defaulting to 1; the volume coefficient for clips and tracks. |
### Upload Material: `upload`
{ "action": "upload", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "8f0c62fb-304f-420e-9707-426e8b64b5e3", "audio_url": "https://cdn.acedata.cloud/suno_demo.mp3", "async": true }
Acknowledgment Response:
{ "task_id": "3fe60d9c-cada-4aab-b1f4-8c0b28247243", "trace_id": "4a54cb56-befb-45da-8001-2a20cdb67d18" }
Task Terminal State:
{ "success": true, "task_id": "3fe60d9c-cada-4aab-b1f4-8c0b28247243", "trace_id": "4a54cb56-befb-45da-8001-2a20cdb67d18", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "candidate": { "audio_id": "b21be571-bfe4-47c1-b59c-2abc55c6f9c3", "title": "suno_demo", "duration": 41, "audio_url": "https://cdn.acedata2.cloud/suno/b21be571-bfe4-47c1-b59c-2abc55c6f9c3.m4a" } } }
### Add Source Track: `add_track`
{ "action": "add_track", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "8f0c62fb-304f-420e-9707-426e8b64b5e3", "audio_id": "b21be571-bfe4-47c1-b59c-2abc55c6f9c3", "name": "Source demo", "start_beats": 0 }
Acknowledgment Response:
{ "task_id": "03f0f74f-c3ed-4d03-896b-74b2a366838b", "trace_id": "3442a5b2-7b16-4225-b8af-24eb872d0e07" }
Task Terminal State:
{ "success": true, "task_id": "03f0f74f-c3ed-4d03-896b-74b2a366838b", "trace_id": "3442a5b2-7b16-4225-b8af-24eb872d0e07", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "cf8a6aa5-0f6d-4da3-844e-cc156aa1b731", "track": { "id": "b7ee9e97-f517-44d7-af4c-e9dad71498c9", "name": "Source demo", "clips": [ { "clipId": "b21be571-bfe4-47c1-b59c-2abc55c6f9c3", "startBeats": 0, "endBeats": 82 } ] } } }
## Generate New Tracks
Candidates are bound to the project version at the time of generation. First save an empty track to receive candidates, then export the current mix as a generation reference; after generation is complete, select a candidate and submit it to that empty track.
### Reserve Target Track: `save`
The candidates from `generate_track` are bound to the current project version. On the **complete** `state` returned in the terminal state of the previous `add_track`, add the following empty track to `state.tracks`, then save it with `save`; retain all other existing fields as they are:
{ "id": "bdec15b5-ce96-43fa-b681-26298e013b06", "type": "audio", "name": "Generated piano", "clips": [], "takeLanes": [], "mute": false, "solo": false, "amplitude": 1, "instrument": { "type": "song" }, "color": "#7251F7" }
Save response:
{ "success": true, "task_id": "783f8d49-cc59-4a65-9f9d-ca00e7d7b8a9", "trace_id": "0a9c8f13-7e4f-4915-8a40-010ce4ac61dc", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "cb0a82c9-aa5b-48cc-9395-0528675fc18d" } }
### Export reference mix: `render`
| Parameter | Type and description |
|---|---|
| `title` | Required string; exported audio title. |
| `lyrics`, `tags` | Optional strings; lyrics default to `[Instrumental]`, and `tags` are style descriptions. |
| `start_beats`, `end_beats` | Optional non-negative numbers, with the endpoint required to be greater than the start point; when omitted, covers all audible clips. Muted clips are not included; when there are solo tracks, only solo tracks are selected. |
After success, obtain `render_audio_id` from the task terminal state `response.data.audio_id`.
{ "action": "render", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "cb0a82c9-aa5b-48cc-9395-0528675fc18d", "title": "Suno Projects Docs Source Mix", "lyrics": "[Instrumental]", "async": true }
Acceptance response:
{ "task_id": "adc559fa-4a87-4a53-9336-28d4302a151b", "trace_id": "165fde93-f34b-4b0b-a7cd-0fba7d7ac154" }
Task terminal state:
{ "success": true, "task_id": "adc559fa-4a87-4a53-9336-28d4302a151b", "trace_id": "165fde93-f34b-4b0b-a7cd-0fba7d7ac154", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "cb0a82c9-aa5b-48cc-9395-0528675fc18d", "render_id": "41038732-4dc4-40bf-b00d-2728d99bc26e", "audio_id": "41038732-4dc4-40bf-b00d-2728d99bc26e", "duration": 41, "audio_url": "https://cdn.acedata2.cloud/suno/41038732-4dc4-40bf-b00d-2728d99bc26e.m4a" } }
### Generate candidates: `generate_track`
Each submission is fixed at 2 candidates.
| Parameter | Type and description |
|---|---|
| `source_audio_id` | Required; ID of the completed source audio. First add the source audio to the project, then the candidate position can be determined subsequently. |
| `render_audio_id` | Required; `response.data.audio_id` from the above `render` terminal state, not the audio URL. |
| `model` | Required; options include `chirp-v3-5`, `chirp-v4`, `chirp-v4-5`, `chirp-v4-5-plus`, `chirp-v5`, `chirp-v5-5`, `chirp-v6`, `chirp-v6-wild`, `chirp-v6-mini`. Whether specific combinations are available is subject to the task terminal state. |
| `start_seconds`, `end_seconds` | Required numbers, `0 ≤ start_seconds < end_seconds`; a seconds interval within the source audio, not project beats, and does not guarantee output duration. |
| `stem_control_tags` | Required string; description of the added part, such as `add Piano`, `add Drums`, `add Bass`, not a fixed enumeration. |
| `instrumental`, `vocal_gender` | Optional; instrumental defaults to `true`, vocal preference can be `f`, `m`, `unspecified`, defaulting to `unspecified`. |
| `title`, `tags`, `negative_tags`, `prompt` | Optional strings; respectively the candidate title, desired style, styles to avoid, and text or lyric prompt for the new part. |
{ "action": "generate_track", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "cb0a82c9-aa5b-48cc-9395-0528675fc18d", "source_audio_id": "b21be571-bfe4-47c1-b59c-2abc55c6f9c3", "render_audio_id": "41038732-4dc4-40bf-b00d-2728d99bc26e", "model": "chirp-v5", "start_seconds": 12, "end_seconds": 20, "stem_control_tags": "add Piano", "title": "Documentation Piano Take", "tags": "gentle piano, instrumental", "async": true }
Acceptance response:
{ "task_id": "66a7356f-3b2a-4472-bdfd-f7b973380644", "trace_id": "81a4cf70-d9f6-48b3-a889-b68e74d6307f" }
Task terminal state:
{ "success": true, "task_id": "66a7356f-3b2a-4472-bdfd-f7b973380644", "trace_id": "81a4cf70-d9f6-48b3-a889-b68e74d6307f", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "cb0a82c9-aa5b-48cc-9395-0528675fc18d", "operation_id": "66a7356f-3b2a-4472-bdfd-f7b973380644", "candidates": [ { "id": "1a4788a8-6f04-47d7-9698-4199b585b9a8", "title": "Documentation Piano Take", "state": "complete", "duration": 41.76, "audio_url": "https://cdn.acedata2.cloud/suno/20f8ffe5063111b1eb866336242e2c0b2b9b7103a8dc0c0c19106cbf50843f86.mp3" }, { "id": "18d6e0a4-2d73-43c3-92e9-be87cf11e139", "title": "Documentation Piano Take", "state": "complete", "duration": 40.96, "audio_url": "https://cdn.acedata2.cloud/suno/c1c50a016333e3a037f18f651c0a88061880b3069aee7c6a258d6c9cdc041a6b.mp3" } ] } }
The 12–20 seconds in the request are the source audio reference interval, while the candidate audio is approximately 41 seconds; `start_seconds`/`end_seconds` are not guarantees of output duration.
### Adopt candidate: `commit_candidate`
| Parameter | Type and description |
|---|---|
| `operation_id` | Required; the generation task terminal-state `data.operation_id`. |
| `candidate_id` | Required; the selected `data.candidates[].id`. |
| `track_id` | Required; the ID of the empty track saved before generation, `state.tracks[].id`. |
| `start_beats`, `end_beats` | Optional for new-track candidates; specifies the project beat range and cannot overlap with existing clips on the target track. When omitted, the source clip start point is used and the endpoint is calculated based on the candidate duration. |
| `name`, `gain` | Optional for new-track candidates; the clip name and non-negative volume coefficient, with `gain` defaulting to 1. |
Generation only produces candidates; it **does not automatically place them into the project**. `commit_candidate` checks that the candidate still belongs to the current version. A partial-replacement candidate can be automatically committed only when its actual duration can be reliably matched to the complete source audio or the selected interval; when it does not match, the original project is retained and an error is returned, and it cannot be forcibly stitched together by manually guessing beat counts.
{ "action": "commit_candidate", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "cb0a82c9-aa5b-48cc-9395-0528675fc18d", "operation_id": "66a7356f-3b2a-4472-bdfd-f7b973380644", "candidate_id": "1a4788a8-6f04-47d7-9698-4199b585b9a8", "track_id": "bdec15b5-ce96-43fa-b681-26298e013b06", "async": true }
Acceptance response:
{ "task_id": "3291bd86-d524-4720-9b6e-655efa600e3d", "trace_id": "1bfee6c0-e936-4147-8a75-a903173d13d6" }
Task terminal state:
{ "success": true, "task_id": "3291bd86-d524-4720-9b6e-655efa600e3d", "trace_id": "1bfee6c0-e936-4147-8a75-a903173d13d6", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "1ff01ada-e26b-444e-a618-a91f76754360", "committed_candidate_id": "1a4788a8-6f04-47d7-9698-4199b585b9a8", "state": { "tracks": [ { "id": "b7ee9e97-f517-44d7-af4c-e9dad71498c9", "clips": [ { "clipId": "b21be571-bfe4-47c1-b59c-2abc55c6f9c3", "startBeats": 0, "endBeats": 82 } ] }, { "id": "bdec15b5-ce96-43fa-b681-26298e013b06", "clips": [ { "clipId": "1a4788a8-6f04-47d7-9698-4199b585b9a8", "startBeats": 0, "endBeats": 83.52 } ] } ] } } }
### Export after committing
After committing a new-track candidate, exporting the full song containing that candidate was rejected. The request and terminal state:
{ "action": "render", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "1ff01ada-e26b-444e-a618-a91f76754360", "title": "Suno Projects Docs Mix With Piano", "lyrics": "[Instrumental]", "async": true }
Acceptance response:
{ "task_id": "12fe503c-017e-46db-9d99-8cfb861ad4fc", "trace_id": "2f376c45-a081-4c2a-b6a5-658401fe8dc0" }
Task terminal state:
{ "success": false, "task_id": "12fe503c-017e-46db-9d99-8cfb861ad4fc", "trace_id": "2f376c45-a081-4c2a-b6a5-658401fe8dc0", "error": { "code": "studio_audio_unavailable", "message": "A referenced audio is not available for project rendering. Keep the original project and use a supported audio." } }
A candidate audio link being accessible does not mean that a project containing it can necessarily be exported. When receiving `studio_audio_unavailable`, retain the original project and check the availability of the referenced audio.
## Replace an existing clip
`replace_section` can directly use existing source audio, without needing to export a mix first. Generation only returns candidates; when committing, select the original track containing the unique source clip.
| Parameter | Type and description |
|---|---|
| `source_audio_id` | Required; the completed source audio ID to be replaced. |
| `model` | Required; use one of the public models listed under “Generate candidates”; model and operation availability are subject to the task terminal state. |
| `start_seconds`, `end_seconds` | Required numbers, `0 ≤ start_seconds < end_seconds ≤ source audio duration`; the seconds interval within the source audio. |
| `prompt`, `replacement_lyrics` | Optional strings; the former is the original lyrics or context, and the latter is the new lyrics for the replacement interval. |
| `title`, `tags`, `negative_tags` | Optional strings; the candidate title, desired style, and styles to avoid. |
| `fixed` | Optional Boolean, defaulting to `false`; when set to `true`, the interval must be shorter than 26 seconds, and the model may not support it. |
### Generate replacement candidate: `replace_section`
{ "action": "replace_section", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "1ff01ada-e26b-444e-a618-a91f76754360", "source_audio_id": "b21be571-bfe4-47c1-b59c-2abc55c6f9c3", "model": "chirp-v5", "title": "Documentation Verse Edit", "tags": "dreamy Chinese pop", "prompt": "[Verse 1]\n晨光洒在海边\n浪花笑得灿烂\n你和我在沙滩\n钟表停止转动\n冰淇淋在融化\n手牵手去散步\n[Chorus]\n风儿轻轻吹过\n心跳不停鼓\n夏天夏天\n时间停在这一天\n笑声回荡\n微蓝天空在身旁", "replacement_lyrics": "我们走在海边\n微风吹过晴天", "start_seconds": 12, "end_seconds": 20, "async": true }
Acceptance response:
{ "task_id": "e742a2d5-35f1-4a43-b351-c6aa5a744c4c", "trace_id": "9f9c0bec-963d-417f-aaf2-0b7f89e0dcbc" }
Task final state:
{ "success": true, "task_id": "e742a2d5-35f1-4a43-b351-c6aa5a744c4c", "trace_id": "9f9c0bec-963d-417f-aaf2-0b7f89e0dcbc", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "1ff01ada-e26b-444e-a618-a91f76754360", "operation_id": "e742a2d5-35f1-4a43-b351-c6aa5a744c4c", "candidates": [ { "id": "c486e799-5f89-4db0-b414-3b666e0db2b3", "title": "Documentation Verse Edit", "state": "complete", "duration": 36, "audio_url": "https://cdn.acedata2.cloud/suno/287a448c0e6099b5e66901f363607bcfcf38d06312c344b03a3486bbb4fe037b.mp3" }, { "id": "f0b66dff-9f8e-45f2-b441-c94e2ecd3a11", "title": "Documentation Verse Edit", "state": "complete", "duration": 36, "audio_url": "https://cdn.acedata2.cloud/suno/172227abd70f2201081a8f58e4c3b401f1e75fd0b29c03aa95abdb6689bfd0a5.mp3" } ] } }
### Candidate duration mismatch
When submitting a partial replacement candidate, `track_id` should point to the original track containing the unique source segment, and `start_beats` and `end_beats` should be omitted. The API will update the project only when the candidate duration can reliably match the complete source audio or the selected range.
After selecting an 8-second range, both candidates are 36 seconds, which equals neither the original audio's 41 seconds nor the selected 8 seconds. Submitting one of the candidates returns:
{ "action": "commit_candidate", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "1ff01ada-e26b-444e-a618-a91f76754360", "operation_id": "e742a2d5-35f1-4a43-b351-c6aa5a744c4c", "candidate_id": "c486e799-5f89-4db0-b414-3b666e0db2b3", "track_id": "b7ee9e97-f517-44d7-af4c-e9dad71498c9", "async": true }
Acceptance response:
{ "task_id": "2261a2a6-d7fb-42ac-ae58-41005cfc8173", "trace_id": "25c6e92d-e0b9-4f9b-ba35-434635ec7bb3" }
Task final state:
{ "success": false, "task_id": "2261a2a6-d7fb-42ac-ae58-41005cfc8173", "trace_id": "25c6e92d-e0b9-4f9b-ba35-434635ec7bb3", "error": { "code": "bad_request", "message": "Candidate duration does not match the source or selected section. Keep the original track and inspect the candidate before editing." } }
Therefore, the original track was not modified. When encountering this error, retain the candidates for auditioning and manual processing; do not treat them as having been successfully inserted into the project, and do not automatically resubmit paid generation.
## Delete track
`remove_track` requires the current `version_id` and `state.tracks[].id`; after success, use the returned new version. Below, the candidate track that cannot be used for full-song export is deleted, and the project state is read back.
{ "action": "remove_track", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "1ff01ada-e26b-444e-a618-a91f76754360", "track_id": "bdec15b5-ce96-43fa-b681-26298e013b06" }
Response:
{ "success": true, "trace_id": "5df2f4b4-6f09-4006-93bd-ad44f4ccb8c1", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "c3f650a9-1c49-4e80-88ef-27deb9b16ce8", "removed_track_id": "bdec15b5-ce96-43fa-b681-26298e013b06", "state": { "tracks": [ { "id": "b7ee9e97-f517-44d7-af4c-e9dad71498c9" } ] } } }
Read the project again:
{ "success": true, "trace_id": "c7613f9b-6484-47b1-83ff-f8a0c1529d8e", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "c3f650a9-1c49-4e80-88ef-27deb9b16ce8", "state": { "tracks": [ { "id": "b7ee9e97-f517-44d7-af4c-e9dad71498c9" } ] } } }
### Export after deletion
After deleting the candidate track, the original source track remains, and exporting again with the latest version succeeds:
{ "action": "render", "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "c3f650a9-1c49-4e80-88ef-27deb9b16ce8", "title": "Suno Projects Docs Mix After Remove", "async": true }
Acceptance response:
{ "task_id": "41c8bcb2-eb98-4da7-8081-7755bcc7be8d", "trace_id": "6480a230-7553-4dd1-a8e2-9131dab418a9" }
Task final state:
{ "success": true, "task_id": "41c8bcb2-eb98-4da7-8081-7755bcc7be8d", "trace_id": "6480a230-7553-4dd1-a8e2-9131dab418a9", "data": { "id": "af0e104a-2a4c-40e0-9c70-7614566824a6", "version_id": "c3f650a9-1c49-4e80-88ef-27deb9b16ce8", "render_id": "75aaaa5f-e633-4006-9200-98d03f3542af", "audio_id": "75aaaa5f-e633-4006-9200-98d03f3542af", "duration": 41, "audio_url": "https://cdn.acedata2.cloud/suno/75aaaa5f-e633-4006-9200-98d03f3542af.m4a" } }
The successfully exported `audio_url` can be used for downloading or playback. An accessible audio link does not prove that other candidates are also eligible for project export.
## Errors and Recovery
| Result | Meaning | Next Step |
|---|---|---|
| `project_version_conflict` / `project_candidate_stale` (409) | The project version has changed, or the candidate does not belong to the current version. | `retrieve` the latest project and re-plan the modifications; do not replay old candidates. |
| `bad_request` / `studio_state_invalid` / `studio_model_unsupported` (usually 400) | The parameters, track state, candidate duration, or model does not match the operation. | Check the task terminal-state error and correct the input; retain the original project when candidates cannot be safely stitched together. |
| `studio_audio_unavailable` / `studio_access_denied` / `content_rejected` (403) | The referenced audio is unavailable for this project operation, access is denied, or content review rejected it. | Check the audio source and the task `trace_id`; do not equate an already generated candidate with the exportability of the entire track. |
| `too_many_requests` (429) | The request is rate-limited. | Query the original task first, then decide whether to initiate a new operation with a new idempotency key. |
| `studio_unavailable` / `studio_model_unavailable` (503) | Project processing or the selected model is temporarily unavailable. | Retain the original task result; explicitly retry later, and do not automatically switch models. |
| `studio_processing_failed` / timeout (500/504) | Processing failed or the terminal state is uncertain. | Query by `task_id` or the original idempotency key to avoid duplicate charged generation. |
Projects and candidates are bound to the application and execution environment that created them; do not assume cross-application reuse or automatic failover. Persist the successfully exported final audio URL, and retain the `trace_id` for troubleshooting.