curl --request POST \
--url https://api.apimart.ai/v1/music/generations/download \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
}'
import requests
url = "https://api.apimart.ai/v1/music/generations/download"
payload = {
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"],
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const response = await fetch(
"https://api.apimart.ai/v1/music/generations/download",
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "suno",
task_id: "task_01JGXXXXXXXXXXXX",
audio_index: 1,
formats: ["mp3", "wav"],
}),
},
);
console.log(await response.json());
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": []string{"mp3", "wav"},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest(
http.MethodPost,
"https://api.apimart.ai/v1/music/generations/download",
bytes.NewBuffer(body),
)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
response, _ := http.DefaultClient.Do(req)
defer response.Body.Close()
result, _ := io.ReadAll(response.Body)
fmt.Println(string(result))
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String payload = """
{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apimart.ai/v1/music/generations/download"))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request,
HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/music/generations/download";
$payload = [
"model" => "suno",
"task_id" => "task_01JGXXXXXXXXXXXX",
"audio_index" => 1,
"formats" => ["mp3", "wav"]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer <token>",
"Content-Type: application/json"
]);
echo curl_exec($ch);
curl_close($ch);
?>
require "net/http"
require "json"
uri = URI("https://api.apimart.ai/v1/music/generations/download")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = {
model: "suno",
task_id: "task_01JGXXXXXXXXXXXX",
audio_index: 1,
formats: ["mp3", "wav"]
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/download")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
URLSession.shared.dataTask(with: request) { data, _, error in
if let error = error {
print(error)
return
}
if let data = data {
print(String(data: data, encoding: .utf8) ?? "")
}
}.resume()
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JHXXXXXXXXXXXX"
}
]
}
{
"error": {
"message": "`formats` contains unsupported format `flac`. Supported: mp3 / m4a / wav",
"type": "invalid_request_error",
"code": "invalid_source_reference"
}
}
{
"error": {
"code": 401,
"message": "身份验证失败,请检查您的 API 密钥",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "账户余额不足,请充值后再试",
"type": "payment_required"
}
}
{
"error": {
"code": "model_price_not_configured",
"message": "模型价格未配置",
"type": "permission_error"
}
}
{
"error": {
"code": 429,
"message": "请求过于频繁,请稍后再试",
"type": "rate_limit_error"
}
}
{
"error": {
"code": 500,
"message": "服务器内部错误,请稍后重试",
"type": "server_error"
}
}
Suno
下载音频文件
- 将 Suno 歌曲下载为 MP3、M4A 或 WAV 文件
- 支持一次请求多个格式,返回对应的文件 URL
- 使用源任务 task_id 和 audio_index 指定要下载的歌曲
- 异步提交任务,通过音乐任务查询接口获取结果
POST
/
v1
/
music
/
generations
/
download
curl --request POST \
--url https://api.apimart.ai/v1/music/generations/download \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
}'
import requests
url = "https://api.apimart.ai/v1/music/generations/download"
payload = {
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"],
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const response = await fetch(
"https://api.apimart.ai/v1/music/generations/download",
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "suno",
task_id: "task_01JGXXXXXXXXXXXX",
audio_index: 1,
formats: ["mp3", "wav"],
}),
},
);
console.log(await response.json());
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": []string{"mp3", "wav"},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest(
http.MethodPost,
"https://api.apimart.ai/v1/music/generations/download",
bytes.NewBuffer(body),
)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
response, _ := http.DefaultClient.Do(req)
defer response.Body.Close()
result, _ := io.ReadAll(response.Body)
fmt.Println(string(result))
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String payload = """
{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apimart.ai/v1/music/generations/download"))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request,
HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/music/generations/download";
$payload = [
"model" => "suno",
"task_id" => "task_01JGXXXXXXXXXXXX",
"audio_index" => 1,
"formats" => ["mp3", "wav"]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer <token>",
"Content-Type: application/json"
]);
echo curl_exec($ch);
curl_close($ch);
?>
require "net/http"
require "json"
uri = URI("https://api.apimart.ai/v1/music/generations/download")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = {
model: "suno",
task_id: "task_01JGXXXXXXXXXXXX",
audio_index: 1,
formats: ["mp3", "wav"]
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/download")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
URLSession.shared.dataTask(with: request) { data, _, error in
if let error = error {
print(error)
return
}
if let data = data {
print(String(data: data, encoding: .utf8) ?? "")
}
}.resume()
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JHXXXXXXXXXXXX"
}
]
}
{
"error": {
"message": "`formats` contains unsupported format `flac`. Supported: mp3 / m4a / wav",
"type": "invalid_request_error",
"code": "invalid_source_reference"
}
}
{
"error": {
"code": 401,
"message": "身份验证失败,请检查您的 API 密钥",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "账户余额不足,请充值后再试",
"type": "payment_required"
}
}
{
"error": {
"code": "model_price_not_configured",
"message": "模型价格未配置",
"type": "permission_error"
}
}
{
"error": {
"code": 429,
"message": "请求过于频繁,请稍后再试",
"type": "rate_limit_error"
}
}
{
"error": {
"code": 500,
"message": "服务器内部错误,请稍后重试",
"type": "server_error"
}
}
原
POST /v1/music/generations/wav 接口已弃用。旧接口暂时兼容,等价于调用新接口并传入 formats: ["wav"];新代码请统一使用 POST /v1/music/generations/download。指定源歌曲: 传入生成源音轨时获得的
task_id,并用 audio_index 指定结果 music[] 中的第几首歌曲。audio_index 从 1 开始,默认值为 1。curl --request POST \
--url https://api.apimart.ai/v1/music/generations/download \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
}'
import requests
url = "https://api.apimart.ai/v1/music/generations/download"
payload = {
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"],
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
const response = await fetch(
"https://api.apimart.ai/v1/music/generations/download",
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "suno",
task_id: "task_01JGXXXXXXXXXXXX",
audio_index: 1,
formats: ["mp3", "wav"],
}),
},
);
console.log(await response.json());
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
payload := map[string]interface{}{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": []string{"mp3", "wav"},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest(
http.MethodPost,
"https://api.apimart.ai/v1/music/generations/download",
bytes.NewBuffer(body),
)
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
response, _ := http.DefaultClient.Do(req)
defer response.Body.Close()
result, _ := io.ReadAll(response.Body)
fmt.Println(string(result))
}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
String payload = """
{
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.apimart.ai/v1/music/generations/download"))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request,
HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/music/generations/download";
$payload = [
"model" => "suno",
"task_id" => "task_01JGXXXXXXXXXXXX",
"audio_index" => 1,
"formats" => ["mp3", "wav"]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer <token>",
"Content-Type: application/json"
]);
echo curl_exec($ch);
curl_close($ch);
?>
require "net/http"
require "json"
uri = URI("https://api.apimart.ai/v1/music/generations/download")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = {
model: "suno",
task_id: "task_01JGXXXXXXXXXXXX",
audio_index: 1,
formats: ["mp3", "wav"]
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/music/generations/download")!
let payload: [String: Any] = [
"model": "suno",
"task_id": "task_01JGXXXXXXXXXXXX",
"audio_index": 1,
"formats": ["mp3", "wav"]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer <token>", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
URLSession.shared.dataTask(with: request) { data, _, error in
if let error = error {
print(error)
return
}
if let data = data {
print(String(data: data, encoding: .utf8) ?? "")
}
}.resume()
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JHXXXXXXXXXXXX"
}
]
}
{
"error": {
"message": "`formats` contains unsupported format `flac`. Supported: mp3 / m4a / wav",
"type": "invalid_request_error",
"code": "invalid_source_reference"
}
}
{
"error": {
"code": 401,
"message": "身份验证失败,请检查您的 API 密钥",
"type": "authentication_error"
}
}
{
"error": {
"code": 402,
"message": "账户余额不足,请充值后再试",
"type": "payment_required"
}
}
{
"error": {
"code": "model_price_not_configured",
"message": "模型价格未配置",
"type": "permission_error"
}
}
{
"error": {
"code": 429,
"message": "请求过于频繁,请稍后再试",
"type": "rate_limit_error"
}
}
{
"error": {
"code": 500,
"message": "服务器内部错误,请稍后重试",
"type": "server_error"
}
}
认证
string
必填
所有接口均使用 Bearer Token 认证。访问 API Key 管理页面 获取 API Key。
Authorization: Bearer YOUR_API_KEY
请求参数
string
默认值:"suno"
模型名称。当前填写
suno;省略时默认为 suno。string
必填
生成源歌曲时返回的任务 ID。源任务必须:
- 属于当前账户
- 已完成
- 包含可下载的音轨
integer
默认值:"1"
要下载源任务结果
music[] 中的第几首歌曲。- 从
1开始计数 - 默认:
1 - 不得超过源任务实际包含的歌曲数量
string[]
要下载的文件格式数组,至少包含一项。可选值:
mp3m4awav
string
只下载一种格式时,可使用此字段代替
formats。示例:"format": "mp3"formats 和 format 选择一种写法即可。两者均未提供或格式列表为空时,请求会返回 HTTP 400。提交响应
成功提交后返回下载任务自己的task_id:
{
"code": 200,
"data": [
{
"status": "submitted",
"task_id": "task_01JHXXXXXXXXXXXX"
}
]
}
返回的
data 是数组,请读取 data[0].task_id。它是新建的下载任务 ID,与请求中的源歌曲 task_id 不同。查询下载结果
使用提交响应中的下载任务 ID 查询:GET /v1/music/tasks/{task_id}
completed 或 failed,再每 2 秒轮询一次,最多等待 60 秒。
下载完成
{
"code": 200,
"data": {
"id": "task_01JHXXXXXXXXXXXX",
"status": "completed",
"progress": 100,
"created": 1756800000,
"completed": 1756800003,
"actual_time": 3,
"cost": 0.01,
"credits_cost": 0.1,
"result": {
"music_id": "518c74ee-62ac-4ccd-b3d9-7003acd12ad7",
"files": [
{
"format": "mp3",
"url": "https://assets.apimart.ai/audio/example.mp3"
},
{
"format": "wav",
"url": "https://assets.apimart.ai/audio/example.wav"
}
],
"wavUrl": "https://assets.apimart.ai/audio/example.wav"
}
}
}
result.files[] 获取下载文件:
| 字段 | 类型 | 说明 |
|---|---|---|
format | string | 文件格式:mp3 / m4a / wav |
url | string | 文件下载地址 |
result.wavUrl 仅用于兼容旧 WAV 接口。新代码请统一读取 result.files[]。处理中
{
"code": 200,
"data": {
"id": "task_01JHXXXXXXXXXXXX",
"status": "processing",
"progress": 50,
"created": 1756800000
}
}
result 字段,请继续轮询。
下载失败
{
"code": 200,
"data": {
"id": "task_01JHXXXXXXXXXXXX",
"status": "failed",
"progress": 100,
"cost": 0,
"error": {
"message": "上游返回错误"
}
}
}
cost 为 0。可向用户显示 error.message 并提供重试操作。
文件 URL
下载结果通常使用 APIMart 文件域名。少数转存失败的情况下可能返回上游 CDN 地址,该地址的有效期无法保证。请在获得 URL 后尽快下载并保存文件,不要将临时 URL 作为长期存储地址。
错误处理
提交期参数错误会返回 HTTP 400,不创建任务、不扣费:| 错误信息 | 原因 |
|---|---|
formats is required / must contain at least one | 未提供下载格式 |
unsupported format | 包含 mp3 / m4a / wav 以外的格式 |
task_id is required / invalid task_id format | 源任务 ID 缺失或格式错误 |
source task not found | 源任务不存在或不属于当前账户 |
audio_index N out of range | 歌曲序号超出源任务音轨数量 |
track #N has no music_id | 源任务未完成或对应歌曲没有音频 |
model_price_not_configured 时,表示后台未配置 suno@download 价格,请联系平台支持。
计费与重复下载
下载接口按请求计费:- 一次请求选择多个格式只收取一次费用
- 再次提交同一首歌曲,即使格式相同,也会产生新费用
- 下载另一种格式需要新建任务,也会产生新费用
- 下载失败会自动退款
请保存已返回的文件 URL,并在请求处理中禁用下载按钮,避免重复提交和重复扣费。
从旧接口迁移
| 项目 | 旧接口 | 新接口 |
|---|---|---|
| 请求路径 | /v1/music/generations/wav | /v1/music/generations/download |
| 格式 | 仅 WAV | MP3 / M4A / WAV,可多选 |
| 新增参数 | — | formats 或 format |
| 结果字段 | result.wavUrl | result.files[] |
| 兼容字段 | result.wavUrl | 请求 WAV 时仍可能返回 result.wavUrl |
/generations/download。
Response
integer
响应状态码,成功时为 200