Upload source audio API
Endpoint description
Upload source audio turns a local or remote audio file into a source clip that later capabilities — cover, extend, replace-section, separation and so on — can use.
Endpoint: POST /api/music/upload-source
Billing: Free. This endpoint only uploads source audio; it does not start a generation task.
Recommended usage: this is step 1 of the "two-step cover". Upload the audio with this endpoint first (free, and you can retry whenever it fails) and keep the returned
clip_id; once you have confirmed that the upload succeeded (statusin a completed state), call the cover from a source clip API to start the cover — that request body is only a few hundred bytes, so it cannot be truncated in transit because the audio is too large. Compared with the one-shot upload-then-cover API, this split is more robust when the audio is large, the network is unstable, or the same material will be reused several times (extend / replace-section / separation).
Advice for large file uploads
| Situation | Recommended approach |
|---|---|
| The audio is already public (it has an https direct link) | Use file_url: the request body is only a few hundred bytes, the most robust option |
| Temporary signed URL (ByteDance and others) | Use file_url only while the URL is publicly reachable and still valid; otherwise use multipart or upload immediately |
| A local file (Node / Python / desktop) | Use a multipart upload (-F "file=@source.mp3") and do not set Content-Type manually |
| Only JSON + base64 is possible | Note that Content-Length must be the byte count (Buffer.byteLength), otherwise the request body may be truncated |
After the upload finishes, always confirm that status in the response is already a completed state and save the clip_id before moving on to step 2;
a failed upload is not charged and creates no generation task, so simply retry.
Check file_url before uploading
Our server downloads
file_urlitself; your browser does not. A URL that opens in your browser is not necessarily reachable from our production servers.
For local files, use multipart upload with the file field. Do not use file_url for ByteDance or other temporary signed URLs unless the URL is publicly reachable and is still valid when the upload request is sent.
Run this from a public server before sending the upload request:
curl -L --max-time 30 -D - -o /dev/null "https://example.com/source.mp3"
A GET request must end with HTTP 200, return an audio MIME type and contain non-empty data. Login pages, HTML responses, and HTTP 401, 403, 404 or 410 cannot be used by the server.
file_url download failed: HTTP 404 usually means the signed URL expired, the file was removed, or URL parameters were truncated.
This upload is free. If the file_url download fails, no clip_id, song task or generation call is created and no fee is charged, so no refund is required.
Request parameters
Headers
For JSON requests:
| Parameter | Type | Required | Notes |
|---|---|---|---|
| Authorization | string | yes | Bearer YOUR_API_KEY |
| Content-Type | string | yes | application/json |
Do not set Content-Type manually for multipart requests; the client generates it automatically.
Body parameters
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
| model | string | no | suno-v6 | Customer-facing model name: suno-v6, suno-v6-wild or suno-v6-mini |
| file_url | string | no | - | Remote audio URL |
| file_base64 | string | no | - | Base64 audio |
| file | file (multipart) | no | - | Audio file to upload; the field name must be file |
| file_name | string | no | - | File name |
| upload_type | string | no | file_upload | Upload type |
JSON request example
curl -X POST https://www.suno-api.io/api/music/upload-source \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"file_url": "https://example.com/source.mp3",
"file_name": "source.mp3",
"upload_type": "file_upload"
}'
multipart request example
curl -X POST https://www.suno-api.io/api/music/upload-source \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@source.mp3" \
-F "file_name=source.mp3" \
-F "upload_type=file_upload" \
-F "model=suno-v6"
import requests
with open("source.mp3", "rb") as audio:
response = requests.post(
"https://www.suno-api.io/api/music/upload-source",
headers={"Authorization": "Bearer YOUR_API_KEY"},
data={
"file_name": "source.mp3",
"upload_type": "file_upload",
"model": "suno-v6",
},
files={"file": ("source.mp3", audio, "audio/mpeg")},
timeout=300,
)
response.raise_for_status()
print(response.json())
Response
{
"clip_id": "uploaded_clip_id",
"status": "complete",
"title": "source.mp3",
"image_url": "https://...",
"audio_url": "https://...",
"display_tags": "pop, vocal",
"inferred_description": "uploaded source audio",
"clip_metadata": {}
}
Get an API key
Create an API key in the console after signing up. ¥0.6 per run returns 2 tracks, downloads are unlimited, and no phone number is required.
Get API key Back to overview