# Seedance / Seedream / Upscaler / Seed Audio / 可灵·海螺·Vidu / Zhenzhen / Suno / Midjourney API(api.seedance.nz) > 异步任务型接口:提交任务 → 轮询结果 → 拿到媒体直链。 > Seedance 视频按 Token;HappyHorse / Wan / 超分等按秒或金额;**可灵 / 海螺 / Vidu 为按次计费**;**Zhenzhen 扩展 / Suno / Midjourney 按上游消耗结算**。多退少补,失败全额退款。 > 本文件为 AI 友好的 Markdown 版完整 API 文档,可直接投喂给 Cursor、Claude Code、Codex 等 AI 编程工具。 > 人类可读的网页版:https://api.seedance.nz/docs/ ## 基本信息 - Base URL: `https://api.seedance.nz` - 鉴权:所有接口都要求请求头 `Authorization: Bearer `(在 https://api.seedance.nz/keys 「API 令牌」页面创建,形如 `sk-xxxx`) - 接口一览: - `POST /v1/videos` — 提交视频生成任务(异步) - `POST /v2/video_generation` — MiniMax-H3,MiniMax V2 请求格式;480P/768P/1080P及驱动音频扩展,完整说明见本文件 MiniMax-H3 专节 - `GET /v2/query/video_generation/{task_id}` — MiniMax-H3 单任务,成功视频在 task.content.url - `GET /v2/query/video_generation` — MiniMax-H3 最近7天任务列表 - `DELETE /v2/video_generation/{task_id}` — MiniMax-H3 删除终态记录/尝试取消 - `GET /v1/videos/{task_id}` — 查询视频任务(OpenAI Video 风格响应) - `POST /v1/videos`(model=`zhenzhen-upscaler`)— **视频超分**(独立分类,见下方专节) - `POST /v1/image/generations` — 提交图片生成任务(异步) - `GET /v1/image/generations/{task_id}` — 查询图片任务(通用 TaskDto 响应) - 图片模型(包括 `zhenzhen-image-g-v2.5-lowprice`)必须使用上述异步路径;它与 OpenAI 的 `POST /v1/images/generations` 不兼容。请提交后轮询任务,不要调用 OpenAI 的复数图片路径。 - `POST /v1/audio/generations` — 提交音频生成任务(异步;不是 `/v1/audio/speech`) - `GET /v1/audio/generations/{task_id}` — 查询音频任务(通用 TaskDto 响应) - `POST /v1/chat/completions` — **文本对话(同步/流式)**,模型 `deepseek/deepseek-v4.1-flash`、`deepseek/deepseek-v4-flash-vision-exp`、`glm/glm-5.3-flash`、`glm-5.3`、`qwen/qwen3.8-omni-flash`、`qwen/qwen3.8-flash-next`、`qwen/qwen3.8-max`、`zhenzhen/gk-4.6`、`zhenzhen/g6-astra`、`zhenzhen/g6-sol`、`zhenzhen/g6-luna`、`zhenzhen/g5.6-sol`、`zhenzhen/g5.6-terra`、`zhenzhen/g5.6-luna`、`zhenzhen/g5.5`、`zhenzhen/gm-3.8-flash`、`zhenzhen/gm-4-argon`、`zhenzhen-op-5.5`、`kimi-k3`(OpenAI Chat Completions 兼容) - `POST /v1/audio/transcriptions` — **语音转写(同步)**,模型 `whisper-1`(multipart;不经 bridge) - `POST /v1/music/generations[/:action]` — **Suno 音乐**提交(异步;SKU=`suno-*`) - `GET /v1/music/tasks/{task_id}` — **Suno 音乐**查询(透传 `music[]`) - `POST /v1/midjourney/generations[/:action]` — **Midjourney**提交(异步;SKU=`midjourney-*`) - `GET /v1/midjourney/tasks/{task_id}` — **Midjourney**查询(MJ 风格 + cost) - `POST /v1/files/upload` — 上传参考素材,换取 24 小时有效的公网直链(免费) - `GET /api/usage/wallet/` — **查询账户钱包余额**(Bearer sk;非令牌额度) - 旧版视频端点 `POST /v1/video/generations` + `GET /v1/video/generations/{task_id}` 仅为兼容保留;动效视频模型 `zhenzhen/motion-video`、`zhenzhen/motion-video-pro` 使用该端点,普通视频请用 `/v1/videos`;MiniMax-H3 的 MiniMax V2 客户端使用 `/v2/video_generation`。 ### 异步任务实际扣费 所有异步生成任务在进入终态并完成最终结算后,查询接口都会返回公开的 `usage` 对象: ```json { "usage": { "amount": 8.75, "currency": "CNY" } } ``` - `amount` 必须与本次任务最终实际从用户余额扣除的钱完全一致,单位由 `currency` 指明;它不是提交任务时的预扣金额。 - 任务失败并已退款时,`amount` 为 `0`。 - 只有任务进入终态并完成多退少补后,`usage` 才代表最终实扣。 不同查询协议中的读取位置: | 查询接口 | 读取位置 | | --- | --- | | 通用图片、视频、音频、3D 任务查询 | `data.usage` | | `GET /v1/music/tasks/{task_id}` | `data.usage` | | `GET /v1/midjourney/tasks/{task_id}` | `usage` | | `GET /v1/videos/{task_id}` | `usage` | | `GET /v2/query/video_generation/{task_id}` | `task.usage` | ### 查询钱包余额 用 API Key 查询**账户钱包余额**(控制台钱包,不是令牌 remain_quota): ```bash curl https://api.seedance.nz/api/usage/wallet/ \ -H "Authorization: Bearer sk-xxxx" ``` 响应示例: ```json { "code": true, "message": "ok", "data": { "object": "wallet_balance", "quota": 1500000, "used_quota": 250000, "total_available": 1500000, "amount": 3.0, "used_amount": 0.5, "display_type": "CNY", "username": "demo", "group": "default" } } ``` - 路径:`GET /api/usage/wallet/` - 鉴权:`Authorization: Bearer sk-xxxx`(TokenAuthReadOnly;过期/耗尽令牌也可查询,封禁用户除外) - `amount`:展示货币余额(本站通常为 CNY);`quota` / `total_available`:内部额度单位 - 勿与 `GET /api/usage/token/`(令牌剩余额度)混淆 ### 文本对话(DeepSeek / Qwen / GLM / GK / GPT-6 Astra / Kimi) 同步 OpenAI Chat Completions 兼容接口: ```bash curl -X POST https://api.seedance.nz/v1/chat/completions \ -H "Authorization: Bearer sk-xxxx" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen/qwen3.8-max", "stream": false, "max_tokens": 256, "messages": [{"role":"user","content":"你好"}] }' ``` - 路径:`POST /v1/chat/completions`(同步;可选 `stream=true`) - DeepSeek V4.1 Flash:`deepseek/deepseek-v4.1-flash`;262,144 tokens 上下文,支持图片输入、工具调用、推理、流式输出、上下文缓存和结构化输出。价格以控制台为准。 - DeepSeek Vision 实验版:`deepseek/deepseek-v4-flash-vision-exp`;1,048,576 tokens 上下文,支持图片输入、工具调用、流式输出和结构化输出。实验版能力和价格可能调整,以控制台为准。 - 国内版模型:`glm/glm-5.3-flash`、`glm-5.3`、`qwen/qwen3.8-flash-next`;保留完整模型名(含斜杠)。GLM/Qwen 两款 Flash 模型为 262,144 tokens 上下文,GLM-5.3 为 1,048,576 tokens。 - GLM-5.3:纯文本输入、始终开启推理;工具选择仅支持 `auto`,不支持结构化输出。GLM/Qwen 两款 Flash 模型支持视觉、工具调用、推理和结构化输出。 - 输入、输出、缓存价格以控制台定价页为准。`max_tokens` 包含推理消耗;最终回答读取 `choices[0].message.content`,SSE 读取 `choices[].delta.content`。 - 模型:`qwen/qwen3.8-max`(Qwen 3.8 Max,1M 上下文;支持工具调用、推理、Web Search 与结构化输出) - 模型:`zhenzhen/gk-4.6`(GK 4.6 海外版,500K 上下文;支持视觉输入、工具调用、推理与流式输出) - 模型:`zhenzhen/g6-astra`(GPT-6 Astra 节省版,1,050,000 tokens 上下文;支持视觉输入、工具调用、推理与流式输出) - 模型:`zhenzhen/g6-sol`、`zhenzhen/g6-luna`(GPT-6 节省版,1,050,000 tokens 上下文;支持视觉输入、工具调用、推理与流式输出) - 模型:`kimi-k3`(Kimi K3,约 1M 上下文;默认启用推理) - 计费:按 Token 用量结算(输入/输出倍率以控制台定价页为准);失败不计费 - GK 4.6 阶梯价:输入上下文 `<200K` tokens 时,输入/输出/缓存读取为 ¥14/¥42/¥3.5 每 1M tokens;`>=200K` 时为 ¥28/¥84/¥7;最终按海外上游实际账单换算结算 - GPT-6 Astra 阶梯价:输入上下文 `<=272K` tokens 时,输入/输出/缓存读取/缓存写入为 ¥28.82/¥144.12/¥2.88/¥36.03 每 1M tokens;`>272K` 时为 ¥57.65/¥216.18/¥5.76/¥72.06;最终按海外上游实际美元账单换算结算 - GPT-6 Sol / Luna 阶梯参考价(人民币每 1M tokens,输入 / 输出 / 缓存读 / 缓存写): - `zhenzhen/g6-sol`:≤272K ¥5.7647 / ¥28.8235 / ¥0.5765 / ¥7.2059;>272K ¥11.5294 / ¥43.2353 / ¥1.1529 / ¥14.4118 - `zhenzhen/g6-luna`:≤272K ¥0.2882 / ¥1.4412 / ¥0.0288 / ¥0.3603;>272K ¥0.5765 / ¥2.1618 / ¥0.0576 / ¥0.7206 - 两款最终按海外上游实际美元账单换算结算;控制台定价为准 - 与异步图/视频、`/v1/audio/*` 不是同一路径 ### Claude Opus 5.5 海外版 - 模型:`zhenzhen-op-5.5`,上游映射 `anthropic/claude-opus-5.5`;1,000,000 tokens 上下文,支持文本/图片输入、工具调用、推理、结构化输出和流式输出。 - 价格(人民币每 1M tokens 参考值):输入 ¥32.9412、输出 ¥164.7059、缓存读取 ¥3.2941、5 分钟缓存写入 ¥41.1765、1 小时缓存写入 ¥65.8824。 - 通过 `POST /v1/chat/completions` 调用;最终按海外上游实际美元账单换算结算,具体以控制台定价为准。租户别名遵循分隔符规则,例如 `pickabc-op-5.5`。 ### 语音转写(whisper-1) 同步接口,不轮询: ```bash curl -X POST https://api.seedance.nz/v1/audio/transcriptions \ -H "Authorization: Bearer sk-xxxx" \ -F "file=@/path/to/audio.mp3" \ -F "model=whisper-1" \ -F "response_format=json" ``` - 支持格式:mp3 / wav / flac / m4a / mp4 / ogg / opus / aac / aiff(**不支持 webm**) - `response_format`:`json`(默认)/ `verbose_json` / `srt` / `text` / `vtt` - 计费:按音频时长,1 分钟 = 1000 tokens - 与异步 Seed Audio(`/v1/audio/generations`)不是同一路径 ## 在 Claude Code / Codex 中使用(MCP) - 指南:https://api.seedance.nz/docs/guide-agent-assistants.html - 接入页:登录后在 https://api.seedance.nz/console/agent-connect 创建 AI 助手凭证(独立预算、单次上限、超额先询问,可随时撤销)。 - MCP 地址:`https://api.seedance.nz/mcp`(Streamable HTTP),请求头 `Authorization: Bearer `。AI 助手凭证只能用于 MCP,不能直接调用 `/v1/*`。 - 工具:`get_account`、`list_models`、`get_model_schema`、`estimate_cost`、`generate_image`、`generate_video`、`generate_audio`、`get_task`、`list_tasks`、`create_upload`、`import_media_url`。 - 推荐流程:`get_account` → `list_models` → `get_model_schema` → `estimate_cost` → 用户确认 → `generate_*` → `get_task`(`wait_seconds` 最大 50)。 ## 典型调用流程 ### 视频 1. 如有本地参考素材,先调 `POST /v1/files/upload` 换取 URL。 2. 调 `POST /v1/videos` 提交,记录返回的 `id`。 3. 每 3~5 秒调 `GET /v1/videos/{id}`,直到 `status` 为 `completed` 或 `failed`。 4. 成功时从 `metadata.url` 取视频直链并立即下载转存。 ### 视频超分(Zhenzhen Upscaler) 1. 如有本地 MP4,先调 `POST /v1/files/upload` 换取 URL。 2. 调 `POST /v1/videos`,`model=zhenzhen-upscaler`,在 `metadata.content` 传一条 `video_url`,`metadata.resolution` 指定目标分辨率。 3. 轮询同普通视频任务;成功后下载结果视频并转存。 ### 图片 1. 图生图如需参考图,先上传换 URL。 2. 调 `POST /v1/image/generations` 提交,记录 `task_id` / `id`。 3. 每 3~5 秒调 `GET /v1/image/generations/{id}`,直到 `data.status` 为 `SUCCESS` 或 `FAILURE`。 4. 成功时从 `data.result_url`(或 `data.data.content.image_url`)取图片直链并立即下载转存。 ### 音频 1. 如需参考音频/图片,先上传换 URL。 2. 调 `POST /v1/audio/generations` 提交,记录 `task_id` / `id`。 3. 每 3~5 秒调 `GET /v1/audio/generations/{id}`,直到 `data.status` 为 `SUCCESS` 或 `FAILURE`。 4. 成功时从 `data.result_url`(或 `data.data.content.audio_url`)取音频直链并立即下载转存。 --- ## POST /v1/videos — 提交视频生成任务 Content-Type: `application/json` ### 请求体字段 | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `model` | string | 是 | 模型名,见下方「模型列表」。后缀决定任务类型:`-t2v` 文生视频 / `-i2v` 图生视频 / `-multi` 多模态视频 | | `prompt` | string | `-t2v`/`-multi` 必填,`-i2v` 可选 | 文本提示词,最长 20480 字符。多模态场景可用 `@Image 1`、`@Video 1` 指代第几个参考素材 | | `images` | string[] | `-i2v` 必填 | 参考图片 URL 数组,仅 `-i2v` 使用。1 张 = 首帧图;2 张时第 2 张为尾帧图。也可用单数字段 `image`(单个 URL 字符串)代替 | | `seconds` | string | 否 | 视频时长(秒),字符串类型。`"4"` ~ `"15"` 的整数,或 `"-1"`(模型智能选择时长)。默认 `"5"` | | `metadata` | object | 否 | 生成参数集合,见下表 | ### metadata 对象字段(均可选) | 字段 | 类型 | 说明 | | --- | --- | --- | | `resolution` | string | 分辨率,默认 `720p`。Standard 档:`480p`/`720p`/`1080p`/`2k`/`4k`/`native1080p`/`native4k`;Fast、Mini 档:`480p`/`720p`/`1080p`/`2k`/`4k`。其中 `1080p`/`2k`/`4k` 为超分档,另收附加费(见「价格」) | | `ratio` | string | 画面比例,默认 `adaptive`(自适应)。可选 `16:9`/`4:3`/`1:1`/`3:4`/`9:16`/`21:9` | | `seed` | integer | 随机种子,`-1`(默认,随机)~ `2147483647` | | `generate_audio` | boolean | 是否生成配音/音效,默认 `true` | | `return_last_frame` | boolean | 是否额外返回视频最后一帧图片,默认 `false` | | `content` | array | 仅 `-multi` 模型使用,参考素材数组,见下方 | ### 各任务类型的传参方式与素材限制 | 任务类型 | 传参方式 | 素材限制 | | --- | --- | --- | | `-t2v` 文生视频 | 只传 `prompt` | 无素材 | | `-i2v` 图生视频 | `prompt`(可选)+ 顶层 `images` | 图片 1~2 张:第 1 张首帧(必填),第 2 张尾帧(可选)。JPG/JPEG/PNG/WEBP,单张 ≤30MB | | `-multi` 多模态视频 | `prompt`(必填)+ `metadata.content` | 图片 ≤9 张(JPG/JPEG/PNG/WEBP,单张 ≤30MB);视频 ≤3 个(MP4,单个 ≤50MB);音频 ≤3 个(MP3/WAV,单个 ≤50MB,国内版 Fast 档 ≤15MB)。三类可混合,至少 1 个参考素材 | ### metadata.content 数组元素结构(仅 -multi 模型) ```json { "type": "image_url", "image_url": { "url": "https://..." } } { "type": "video_url", "video_url": { "url": "https://..." } } { "type": "audio_url", "audio_url": { "url": "https://..." } } ``` - 传入 `video_url` 参考视频后,整个任务按「有参考视频」的更低 Token 单价档计费。 - 注意:一旦传了 `metadata.content`,它会整体覆盖顶层 `images` 的效果。多模态场景把图片也写进 `content` 数组,不要再单独传顶层 `images`。 ### 请求示例(文生视频) ```bash curl -X POST https://api.seedance.nz/v1/videos \ -H "Authorization: Bearer sk-xxxx" \ -H "Content-Type: application/json" \ -d '{ "model": "seedance-2.0-mini-t2v", "prompt": "a calm lake at sunrise, cinematic light", "seconds": "5", "metadata": { "resolution": "480p" } }' ``` 注意(Windows PowerShell):把 JSON 写入文件后用 `--data-binary "@request.json"` 提交,直接在命令行拼接带空格的 JSON 会被拆成多个参数导致请求失败。 ### 请求示例(多模态:1 张图 + 1 个视频,换人) ```json { "model": "seedance-2.0-standard-multi", "prompt": "把 @Video 1 中的人物替换成 @Image 1 中的人物", "seconds": "5", "metadata": { "resolution": "1080p", "content": [ { "type": "image_url", "image_url": { "url": "https://your-cdn.example.com/person.png" } }, { "type": "video_url", "video_url": { "url": "https://your-cdn.example.com/source.mp4" } } ] } } ``` ### 响应(200,提交成功) ```json { "id": "task_xxxxxxxxxxxx", "object": "video", "model": "seedance-2.0-mini-t2v", "status": "queued", "progress": 0, "created_at": 1783377182 } ``` --- ## GET /v1/videos/{task_id} — 查询任务状态与结果 路径参数 `task_id` 为提交任务时返回的 `id`。建议每 3~5 秒轮询一次。 ### status 取值 | status | 含义 | | --- | --- | | `queued` | 排队中 | | `in_progress` | 生成中,`progress` 为 0~100 的进度百分比 | | `completed` | 生成成功,`metadata.url` 为视频直链 | | `failed` | 生成失败,详见 `error.code`/`error.message`,费用全额退还 | ### 响应示例 生成中: ```json { "id": "task_xxxxxxxxxxxx", "object": "video", "model": "seedance-2.0-mini-t2v", "status": "in_progress", "progress": 50, "created_at": 1783377182, "metadata": { "url": "" } } ``` 生成成功(`metadata.url` 为带签名有效期的临时直链,请立即下载转存): ```json { "id": "task_xxxxxxxxxxxx", "object": "video", "model": "seedance-2.0-mini-t2v", "status": "completed", "progress": 100, "created_at": 1783377182, "completed_at": 1783377298, "metadata": { "url": "https://.../output.mp4?X-Tos-Signature=..." } } ``` 生成失败: ```json { "id": "task_xxxxxxxxxxxx", "object": "video", "model": "seedance-2.0-mini-t2v", "status": "failed", "progress": 100, "error": { "code": "video_generation_failed", "message": "..." } } ``` --- ## 视频超分(Zhenzhen Upscaler)— 独立分类 把已有 MP4 提升到更高分辨率。走 `POST /v1/videos`(兼容 `POST /v1/video/generations`),查询同普通视频任务。 - 模型:`zhenzhen-upscaler`(上游 `rhart-video/video-upscaler`) - 必填:`metadata.content` 中恰好 1 条 `video_url`(MP4,最长约 10 分钟) - 可选:`metadata.resolution` → 目标分辨率 `720p` / `1080p` / `2k` / `4k`(默认 `1080p`) - `prompt` / `seconds` 不参与上游提交(时长由上游从输入视频读取) - 计费:按输入时长 × 目标分辨率单价;price-preview 全额预扣,终态按最终实扣金额结算 ### 请求示例 ```json { "model": "zhenzhen-upscaler", "prompt": "upscale", "metadata": { "resolution": "1080p", "content": [ { "type": "video_url", "video_url": { "url": "https://your-cdn.example.com/source.mp4" } } ] } } ``` ### 牌价(元 / 秒,指导价) | 目标分辨率 | 单价 | | --- | --- | | 720p | ¥0.14 | | 1080p | ¥0.21 | | 2k | ¥0.35 | | 4k | ¥0.56 | 与 Seedance 生成后再升分辨率的「超分附加费」不是同一套计费。 --- ## POST /v1/files/upload — 上传参考素材 Content-Type: `multipart/form-data`,表单字段 `file`(二进制文件)。上传免费。 - 支持格式:图片 JPG/JPEG/PNG/WEBP、音频 MP3/WAV/FLAC、视频 MP4/AVI/MOV/MKV - 单文件 ≤50MB(生成任务对素材另有大小限制,见上文) - 频率限制:每令牌每分钟 30 次、每天 10000 次,超限返回 429;计数由 bridge 内存滑动窗口维护,重启 bridge 后清零 - 返回的 URL 仅 24 小时有效,不是图床/网盘,请在有效期内提交生成任务 ### 请求示例 ```bash curl -X POST https://api.seedance.nz/v1/files/upload \ -H "Authorization: Bearer sk-xxxx" \ -F "file=@/path/to/person.png" ``` ### 响应(200) ```json { "url": "https://.../xxxx.png?q-sign-algorithm=...", "file_type": "image", "size": 3490, "expires_in": 86400 } ``` 把返回的 `url` 直接填入视频的 `images` / `metadata.content`,或图片的 `images`。 ### 参考素材 URL 的通用要求 - 必须是 `http(s)://` 公网直链:请求该 URL 能直接得到文件本身(`Content-Type` 为对应媒体类型) - 不支持:base64 内嵌、本地文件路径、需要登录的链接、网盘分享页(百度网盘/阿里云盘分享链接打开是网页,无法使用) - URL 需在任务整个执行期间保持可访问;带签名的临时 URL 请确保有效期足够 - 素材不符合要求时任务会提交失败或生成失败,费用全额退还 --- ## POST /v1/audio/generations — 提交音频生成任务 支持 `doubao-seed-audio-1.0`、Mureka BGM/歌曲、MiniMax Speech 2.8/Voice Clone/Music 2.6、Qwen3 TTS。Mureka BGM 请求须在 `prompt` 与 `metadata.instrumental_id` 中二选一;`metadata.n` 为 1–3(默认 2, ¥0.34/条),`metadata.stream` 默认 false。成功时 `result_url` 为第一条音频, 完整有序列表位于 `data.content.audio_urls`。 Content-Type: `application/json` > 异步 Seed Audio,**不是**同步 TTS `POST /v1/audio/speech`。 ### 请求体字段 | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `model` | string | 是 | `doubao-seed-audio-1.0` | | `prompt` | string | 是 | 文本提示词,5 ~ 2048 字符 → 上游 `text_prompt` | | `images` | string[] | 否 | 参考图(取首张);不可与 speaker / 参考音频同时用 | | `metadata` | object | 否 | 见下表 | ### metadata 字段 | 字段 | 类型 | 说明 | | --- | --- | --- | | `speaker` | string | 音色 ID;与 `audio_url` / `images` 互斥 | | `audio_url` / `audio_urls` | string \| string[] | 参考音频,最多 3;与 speaker / images 互斥 | | `format` | string | `wav` / `mp3` / `pcm` / `ogg_opus`,默认 `wav` | | `sample_rate` | string | `8000` / `16000` / `24000` / `32000` / `44100`,默认 `24000` | | `speech_rate` | integer | `-50` ~ `100`,未传默认 `0` | | `loudness_rate` | integer | `-50` ~ `100`,未传默认 `0` | | `pitch_rate` | integer | `-12` ~ `12`,未传默认 `0` | ### 请求示例 ```bash curl -X POST https://api.seedance.nz/v1/audio/generations \ -H "Authorization: Bearer sk-xxxx" \ -H "Content-Type: application/json" \ -d '{ "model": "doubao-seed-audio-1.0", "prompt": "gentle rain falling on a quiet city street at night", "metadata": { "speaker": "zh_male_shaonianzixin_uranus_bigtts", "format": "mp3", "sample_rate": "24000" } }' ``` ### 提交响应(200) ```json { "id": "task_xxxxxxxxxxxx", "task_id": "task_xxxxxxxxxxxx", "status": "queued", "model": "doubao-seed-audio-1.0", "created_at": 1783870738 } ``` --- ## GET /v1/audio/generations/{task_id} — 查询音频任务 返回通用任务记录(与图片查询相同)。建议每 3~5 秒轮询。 ### data.status 取值 | status | 含义 | | --- | --- | | `NOT_START` / `SUBMITTED` | 排队中 | | `IN_PROGRESS` | 生成中 | | `SUCCESS` | 成功,`data.result_url` 为音频直链 | | `FAILURE` | 失败,见 `fail_reason`,全额退款 | ### 成功响应(节选) ```json { "code": "success", "data": { "task_id": "task_xxxxxxxxxxxx", "status": "SUCCESS", "progress": "100%", "result_url": "https://.../output.mp3", "quota": 42000, "data": { "status": "succeeded", "content": { "audio_url": "https://.../output.mp3" } } } } ``` --- ## POST /v1/image/generations — 提交图片生成任务 Content-Type: `application/json` ### 请求体字段 | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `model` | string | 是 | Seedream V5 Pro:`seedream-v5-pro-*` / `dola-seedream-5.0-pro-*`;V5 Flash:`seedream-v5-flash-*` / `dola-seedream-5.0-flash-*`(各含 t2i、i2i、layer-decomposition);Zhenzhen Image G-2:`zhenzhen-image-g2-t2i` / `zhenzhen-image-g2-i2i`;Zhenzhen 扩展:`zhenzhen-image-g-v2-lowprice` / `zhenzhen-image-gk-v15` / `zhenzhen-image-gk-v15-edit` / `zhenzhen-image-gk-v2` / `zhenzhen-image-gk-v2-edit` / `zhenzhen-image-gk-v2-segment` / `zhenzhen-image-gk-v2-region-edit` / `zhenzhen-image-nb-*` / `flux-3-image` / `flux-3-image-t2i` / `flux-3-image-i2i` / `flux-3-image-klein-t2i` / `flux-3-image-klein-i2i` / `mai-image-2-6` / `mai-image-2-6-flash` | | `prompt` | string | 视模型 | V5 Pro 普通生成:5 ~ 2000 字符;V5 Flash 文生图/图生图:5 ~ 5000 字符;图层拆分:可选,0 ~ 2000 字符;Zhenzhen Image G-2:最长 20000 字符 | | `images` | string[] | i2i / 图层拆分必填 | V5 Pro i2i 最多 10 张(单张 ≤10MB);V5 Flash i2i 1 ~ 10 张(单张 ≤30MB);图层拆分恰好 1 张(≤30MB)。也可用单数字段 `image` | | `metadata` | object | 否 | 见下表 | ### metadata 字段 | 字段 | 类型 | 说明 | | --- | --- | --- | | `resolution` | string | V5 Pro 普通生成:`1k` / `2k`;V5 Flash 普通生成:`1k` / `1.5k` / `2k`;均优先于宽高。图层拆分:`auto` / `1k` / `1.5k` / `2k`;Zhenzhen Image G-2:**仅 `1k`** | | `ratio` | string | 仅 Zhenzhen Image G-2:宽高比 → `aspectRatio`(如 `16:9` / `9:16` / `1:1`) | | `width` | integer | 仅 Seedream 文生图/图生图:240 ~ 8192,未传 resolution 时生效;图层拆分不支持 | | `height` | integer | 仅 Seedream 文生图/图生图:240 ~ 8192,未传 resolution 时生效;图层拆分不支持 | | `output_format` | string | Seedream 普通生成与图层拆分底图:`jpeg` / `png`;图层输出为 PNG(Zhenzhen Image G-2 不支持) | ### 请求示例(文生图) ```bash curl -X POST https://api.seedance.nz/v1/image/generations \ -H "Authorization: Bearer sk-xxxx" \ -H "Content-Type: application/json" \ -d '{ "model": "seedream-v5-pro-t2i", "prompt": "高端护肤品电商主图,纯白柔光展台,玻璃精华瓶", "metadata": { "resolution": "2k", "output_format": "jpeg" } }' ``` ### 请求示例(图生图) ```json { "model": "seedream-v5-pro-i2i", "prompt": "横版复古馆藏风美妆宣传海报,藏青深蓝色哑光底", "images": ["https://your-cdn.example.com/ref.png"], "metadata": { "resolution": "1k", "output_format": "jpeg" } } ``` ### 请求示例(图层拆分) ```json { "model": "seedream-v5-pro-layer-decomposition", "images": ["https://your-cdn.example.com/source.png"], "metadata": { "resolution": "auto", "output_format": "jpeg" } } ``` ### 请求示例(Seedream V5 Flash) 文生图: ```json {"model":"seedream-v5-flash-t2i","prompt":"雨后街角的咖啡店,暖色灯光","metadata":{"resolution":"1.5k","output_format":"jpeg"}} ``` 图生图: ```json {"model":"seedream-v5-flash-i2i","prompt":"将背景改为雨后街景","images":["https://your-cdn.example.com/ref.png"],"metadata":{"resolution":"1k","output_format":"png"}} ``` 图层拆分: ```json {"model":"seedream-v5-flash-layer-decomposition","images":["https://your-cdn.example.com/source.png"],"metadata":{"resolution":"auto","output_format":"jpeg"}} ``` 海外站使用对应的 `dola-seedream-5.0-flash-{t2i,i2i,layer-decomposition}` 名称,参数限制相同。Flash 图层拆分成功后读取 `data.data.content.image_urls` 中的图片 URL 列表。两站一次成功探测均返回 JPEG 底图与 PNG 图层两项;该样本不保证每次的图层数量。当上游结果带元数据时,响应可能附带与 `image_urls` 顺序对齐的 `data.data.content.layers`;每项有 `url`,其余 `outputType`、`size`、`text`、`zindex`、`boundingBox`、`description`、`name` 为可选。仅有 URL 时省略 `layers`。 ### 提交响应(200) ```json { "id": "task_xxxxxxxxxxxx", "task_id": "task_xxxxxxxxxxxx", "status": "queued", "model": "seedream-v5-pro-t2i", "created_at": 1783717700 } ``` --- ## GET /v1/image/generations/{task_id} — 查询图片任务 返回通用任务记录(与视频的 OpenAI Video 风格不同)。建议每 3~5 秒轮询。 ### data.status 取值 | status | 含义 | | --- | --- | | `NOT_START` / `SUBMITTED` | 排队中 | | `IN_PROGRESS` | 生成中 | | `SUCCESS` | 成功,`data.result_url` 为图片直链 | | `FAILURE` | 失败,见 `fail_reason`,全额退款 | ### 成功响应(节选) ```json { "code": "success", "data": { "task_id": "task_xxxxxxxxxxxx", "status": "SUCCESS", "progress": "100%", "result_url": "https://.../output.jpg", "quota": 270000, "data": { "status": "succeeded", "content": { "image_url": "https://.../base.jpg", "image_urls": ["https://.../base.jpg", "https://.../layer-1.png"] } } } } ``` --- ## POST /v1/3d/generations — 混元 3D v3.1 模型:`hunyuan3d-v3.1-text-to-3d`(prompt 必填)与 `hunyuan3d-v3.1-image-to-3d`(`images` 1–8 张 JPG/PNG,固定顺序为正、左、右、后、上、下、左前、右前视图)。可选参数:`face_count` 10000–1500000(默认 500000)、`enable_pbr`(默认 false)、`generate_type`(`Normal` / `Geometry` / `Sketch`)。 查询:`GET /v1/3d/generations/{task_id}`。成功时 `data.result_url` / `data.data.content.file_url` 为 GLB 文件 URL;约 24 小时过期,不返回额外几何体元数据。 ```json {"model":"hunyuan3d-v3.1-text-to-3d","prompt":"一只青花陶瓷茶壶","face_count":500000,"enable_pbr":false,"generate_type":"Normal"} ``` --- ## 模型列表 ### 视频模型(Seedance 2.0,共 18 个) 模型名格式:`seedance-2.0-[global-]{tier}-{task}` - `[global-]`:省略 = 国内版(人民币);`global-` = 国际版(美元换算人民币) - `{tier}`:`standard` / `fast` / `mini` - `{task}`:`t2v` / `i2v` / `multi` 国内版 9 个: ``` seedance-2.0-standard-t2v seedance-2.0-standard-i2v seedance-2.0-standard-multi seedance-2.0-fast-t2v seedance-2.0-fast-i2v seedance-2.0-fast-multi seedance-2.0-mini-t2v seedance-2.0-mini-i2v seedance-2.0-mini-multi ``` 国际版 9 个: ``` seedance-2.0-global-standard-t2v seedance-2.0-global-standard-i2v seedance-2.0-global-standard-multi seedance-2.0-global-fast-t2v seedance-2.0-global-fast-i2v seedance-2.0-global-fast-multi seedance-2.0-global-mini-t2v seedance-2.0-global-mini-i2v seedance-2.0-global-mini-multi ``` ### 视频模型(Seedance 2.5 Standard Token,共 6 个) 仅 Standard。分辨率 `480p`/`720p`/`1080p`/`2k`/`4k`/`native1080p`(无 `native4k`);时长 4–30s 或 `metadata.duration=-1`。 多模态最多 **50** 个参考:30 图 + 10 视频 + 10 音频(单段音视频 2–30s,总长 ≤30s;不同于 2.0 的 9/3/3)。 ``` seedance-2.5-standard-t2v seedance-2.5-standard-i2v seedance-2.5-standard-multi seedance-2.5-global-standard-t2v seedance-2.5-global-standard-i2v seedance-2.5-global-standard-multi ``` ### 图片模型(Seedream V5 Pro / V5 Flash / Dola / Zhenzhen Image G-2) ``` seedream-v5-pro-t2i # 文生图(国内 .cn) seedream-v5-pro-i2i # 图生图(国内,需 images) seedream-v5-pro-layer-decomposition # 图层拆分(国内;单图输入;底图 + 最多 16 图层) dola-seedream-5.0-pro-t2i # 文生图(海外版) dola-seedream-5.0-pro-i2i # 图生图(海外,需 images) dola-seedream-5.0-pro-layer-decomposition # 图层拆分(海外;单图输入;底图 + 有序图层 URL) seedream-v5-flash-t2i # V5 Flash 文生图(国内 .cn) seedream-v5-flash-i2i # V5 Flash 图生图(国内;images 1–10,单张 ≤30MB) seedream-v5-flash-layer-decomposition # V5 Flash 图层拆分(国内;单图输入;图片 URL 列表) dola-seedream-5.0-flash-t2i # V5 Flash 文生图(海外 .ai) dola-seedream-5.0-flash-i2i # V5 Flash 图生图(海外;images 1–10,单张 ≤30MB) dola-seedream-5.0-flash-layer-decomposition # V5 Flash 图层拆分(海外;单图输入;图片 URL 列表) zhenzhen-image-g2-t2i # Zhenzhen Image G-2 文生图(resolution 仅 1k;可选 ratio) zhenzhen-image-g2-i2i # Zhenzhen Image G-2 图生图(需 images;resolution 仅 1k;ratio→aspectRatio) ``` ### 图片模型(Qwen-Image 3.0 / 3.0-Pro,共 8 个) ``` qwen-image-3.0-t2i # 文生图(国内 .cn) qwen-image-3.0-i2i # 图像编辑(国内;images 1–3) qwen-image-3.0-pro-t2i # Pro 文生图(国内) qwen-image-3.0-pro-i2i # Pro 图像编辑(国内;images 1–3) qwen-image-3.0-global-t2i # 文生图(海外版) qwen-image-3.0-global-i2i # 图像编辑(海外) qwen-image-3.0-global-pro-t2i # Pro 文生图(海外) qwen-image-3.0-global-pro-i2i # Pro 图像编辑(海外) ``` 参数:`prompt`(≤3000);可选 `n`(1–6→imageNum)、`negative_prompt`(≤600)、`prompt_extend`、`metadata.prompt_extend_mode`(`direct`|`agent`)、`metadata.seed`; `metadata.ratio`+`metadata.resolution`(1k|2k) 或 `size`(如 `1024*1024`);省略 size 由上游按提示词自动推荐。 `qwen-image-3.0-global-*` 使用海外版。 Pro 牌价参考(CNY):输出 1K ≈¥0.23/张、2K ≈¥0.45/张;编辑另计输入约 ¥0.02/张。标准文生图约 ¥0.16/张。实际按最终实扣金额结算。 ### 视频模型(Wan 2.7 Spicy,1 个) ``` wan-2.7-spicy-i2v # 图生视频;images[0]→imageUrl;seconds=2..15;720p|1080p;可选 audio_url/negative_prompt/prompt_extend ``` 牌价(按秒,指导价):720p ¥0.91/s,1080p ¥1.4/s。 ### 视频模型(Wan 3.0 标准版与 Prime 高速版,国内与海外共 12 个) ``` wan-3.0-i2v # 首帧必填、尾帧可选;2..30 秒或 auto;480P|720P|1080P wan-3.0-r2v # 图片≤10、视频≤5、音频≤5;可选互斥的 file_url/link_url wan-3.0-global-i2v # 海外图生视频;美元计价 wan-3.0-global-r2v # 海外参考生视频;file_url/link_url 自动开启深度思考 wan-3.0-prime-i2v # Prime 国内高速图生视频;首帧必填、尾帧可选 wan-3.0-prime-r2v # Prime 国内高速参考生视频;图片≤10、视频≤5、音频≤5 wan-3.0-global-prime-i2v # Prime 海外高速图生视频 wan-3.0-global-prime-r2v # Prime 海外高速参考生视频 wan-3.0-t2v # 国内文生视频;必填 prompt,无参考素材;默认 720P wan-3.0-prime-t2v # Prime 国内高速文生视频;默认 1080P wan-3.0-global-t2v # 海外文生视频;默认 720P;美元计价 wan-3.0-global-prime-t2v # Prime 海外高速文生视频;默认 1080P;美元计价 ``` 通用:`prompt`≤20000;`metadata.ratio`=`adaptive|16:9|4:3|1:1|3:4|9:16`;`generate_audio` 默认 true;`seed`=0..2147483647。终态按最终实扣金额结算,成功结果为单个 MP4 URL,价格以控制台为准。 文生视频使用 `POST /v1/video/generations`,以 `GET /v1/video/generations/{id}` 轮询;必填 `prompt`,不传参考素材。`seconds` 为 2–30(默认 5),或省略 `seconds` 并传 `metadata.duration=-1` 使用自动时长;`metadata.resolution` 为 `480P|720P|1080P`;`metadata.generate_audio=false` 可关闭音轨;可选 `metadata.seed` 支持显式 0。 ### 图片模型(Wan 2.7 海外,共 3 个) ``` wan-2.7-global-t2i # 文生图;prompt≤5000;可选 width/height=512..4096、thinking_mode wan-2.7-global-i2i # 图像编辑;images 1–9;prompt≤2048 wan-2.7-global-i2i-pro # Pro 图像编辑;images 1–9;prompt≤2048 ``` 请求路径:`POST /v1/image/generations`,轮询:`GET /v1/image/generations/{id}`。三个 SKU 均使用海外版,最终费用按人民币结算。 ### 视频超分(Zhenzhen Upscaler,1 个)— 独立分类 详见上方专节「视频超分(Zhenzhen Upscaler)」。 ``` zhenzhen-upscaler # video_url + targetResolution;720p|1080p|2k|4k ``` ### 视频模型(HappyHorse 1.1,共 3 个) ``` happyhorse-1.1-t2v # 文生视频;resolution=720p|1080p;seconds=3..15;metadata.ratio→aspectRatio happyhorse-1.1-i2v # 图生视频(需 images);取首图为 imageUrl;prompt 可选 happyhorse-1.1-r2v # 参考图生视频;images 1~9 → imageUrls;prompt 可用「图1/图2」 ``` 牌价(按秒,指导价):720p ¥0.69/s,1080p ¥0.92/s。不支持 `seconds=-1`。 ### 媒体模型(共 68 个)— **按次计费** 计费:按次,price-preview 预扣 → 成功后按最终实扣金额结算 → 失败全额退款。接口同 `/v1/videos`。 #### Kling 4.0 新系列 | 模型 | 功能 | | --- | --- | | `kling-v4-t2v / kling-v4-i2v / kling-v4-omni` | 文生视频 / 首尾帧图生视频 / 全能参考视频 | | `kling-v4-custom-element / kling-v4-custom-voice` | 免费创建主体 / 免费创建音色 | 三个视频模型支持 720p、1080p,时长为 3–30 秒的整数。提示词英文字符数 / 26000 + 非英文字符数 / 11000 ≤ 1。可选 watermark 为布尔值;不提供 seed、声音开关或多镜头开关。视频按实际消耗结算。 文生视频比例:21:9、16:9、1:1、9:16。图生视频通过 image_urls 按顺序传入首帧和可选尾帧,最多 2 张,每张不超过 30MB;不传比例。 全能模型可传 image_urls(最多 10 张,每张 30MB)、video_urls(最多 5 段,每段 300MB,总时长最多 30 秒)、metadata.elementIds(最多 7 个)和 metadata.voiceIds(最多 3 个)。图片、视频、主体合计最多 15 项;视频主体最多 3 个,与视频合计最多 5 项。比例额外支持 adaptive。提示词可使用 @element_1、@1 引用对应素材。 主体创建:metadata.elementName 为 1–20 字,prompt 作为主体描述(1–100 字)。metadata.referenceType=image_refer 时通过 image_urls 提交 1 张正面图和 1–3 张不同参考图;图片 JPG/PNG、每张 10MB、最短边 300px、比例 1:2.5–2.5:1。video_refer 时只传一段 video_url:MP4/MOV、3–8 秒、1080p、16:9 或 9:16、最多 200MB。可选 metadata.elementVoiceId;metadata.tagList 为数组,值为 o_101 至 o_108。 音色创建:必填 metadata.voiceName,audio_url(最多 10MB)与 metadata.videoId 二选一,无需 prompt。主体和音色创建均为免费辅助接口,预扣和最终收费都是 0 元。 五个模型统一提交 POST /v1/video/generations,轮询 GET /v1/video/generations/{task_id}。主体和音色创建返回 result_text,内容是包含 results 数组的 JSON 字符串;按 name 读取 element_id、voice_id、trial_url。请保存自己的 ID,再用于全能参考视频。 #### 可灵 Kling(33) ``` kling-v3.0-std-t2v kling-v3.0-pro-t2v kling-v3.0-std-i2v kling-v3.0-pro-i2v kling-v3-turbo-std-t2v kling-v3-turbo-pro-t2v kling-v3-turbo-std-i2v kling-v3-turbo-pro-i2v kling-v3-4k-t2v kling-v3-4k-i2v kling-o3-std-t2v kling-o3-pro-t2v kling-o3-std-i2v kling-o3-pro-i2v kling-o3-std-r2v kling-o3-pro-r2v kling-o3-std-edit kling-o3-pro-edit kling-o3-4k-t2v kling-o3-4k-i2v kling-o3-4k-r2v kling-v3.0-std-motion kling-v3.0-pro-motion kling-v3.0-4k-motion kling-elements-advanced kling-lip-sync-identify-face kling-lip-sync-tts kling-lip-sync-video ``` - i2v 常用 `firstImageUrl`(`images[0]`);首尾帧用 `images[0]`+`images[1]` - edit / motion 需 `video_url`;lip-sync 为多步(metadata 传 sessionId/faceId 等) #### 海螺 Hailuo 2.3(6) ``` hailuo-2.3-t2v-standard hailuo-2.3-t2v-pro hailuo-2.3-i2v-standard hailuo-2.3-i2v-pro hailuo-2.3-fast-i2v hailuo-2.3-fast-pro-i2v ``` - i2v:`images[0]`→`imageUrl`;标准档时长多为 6/10 秒枚举 #### 海螺 Hailuo H3(6,国内 + 海外) ``` hailuo-h3-t2v hailuo-h3-i2v hailuo-h3-multi hailuo-h3-global-t2v hailuo-h3-global-i2v hailuo-h3-global-multi ``` - 分辨率 `768P` / `2K`;时长 5–15 秒(字符串枚举) - t2v / multi:`metadata.ratio`→`ratio`(含 `adaptive`) - i2v:`images[0]`→`firstFrameUrl`,`images[1]`→`lastFrameUrl` - multi:`images[]`→`imageUrls`(≤9),`video_url`→`videoUrls`(≤3),`audio_url`→`audioUrls`(≤3) - `hailuo-h3-global-*` 使用海外版,按 USD→CNY 结算 #### MiniMax H3 Max(2,国内版) ```text hailuo-h3-max-t2v hailuo-h3-max-i2v ``` - `hailuo-h3-max-t2v`:`prompt` 必填(1–20480);`seconds` 为 `5`–`15`;`metadata.resolution` 为 `480P|768P`;`metadata.ratio` 必填,枚举 `21:9|16:9|4:3|1:1|3:4|9:16` - `hailuo-h3-max-i2v`:同样要求 `prompt`、`seconds`、`metadata.resolution`;`images` 1–2 张,依次映射首帧 `firstFrameUrl` 与可选尾帧 `lastFrameUrl`;不接受 `metadata.ratio` - 两者牌价均为 `480P` ¥0.41/秒、`768P` ¥0.63/秒;任务完成后按最终实扣金额结算 #### MiniMax H3 Max Turbo(2,国内版) ```text hailuo-h3-max-turbo-t2v hailuo-h3-max-turbo-i2v ``` - `hailuo-h3-max-turbo-t2v`:`prompt` 必填;`seconds` 为 `5`–`15`;`metadata.resolution` 使用小写 `480p|768p`;`metadata.ratio` 必填,六种比例映射为上游 `aspectRatio` - `hailuo-h3-max-turbo-i2v`:`prompt`、`seconds`、小写 `resolution` 必填;`images` 1–2 张依次映射必填首帧与可选尾帧;不接受 `metadata.ratio` - 两者牌价均为 `480p` ¥0.175/秒、`768p` ¥0.28/秒;任务完成后按最终实扣金额结算 - `prompt` 最多 20480 字符 #### MiniMax H3 Context IR(3,返回增强提示词) ``` minmax-h3-context-ir-text minmax-h3-context-ir-image minmax-h3-context-ir-multimodal ``` - 只增强视频提示词,不生成视频;提交 `/v1/video/generations`,轮询 `/v1/video/generations/{id}` - 成功结果位于 `result_text` - `prompt` 1–7000 字符,`seconds` 为 4–15 的字符串枚举 - text:`metadata.ratio` 必填,支持 `21:9|16:9|4:3|1:1|3:4|9:16` - image:`images` 1–2 张,映射首帧/尾帧 - multimodal:图≤9、视频≤3、音频≤3,比例可选且支持 `adaptive` - 按最终实扣金额结算 #### FLUX 3 Video(8,国内 + 海外) ``` flux-3-video-t2v flux-3-video-i2v flux-3-video-v2v flux-3-video-draft-enhance flux-3-video-global-t2v flux-3-video-global-i2v flux-3-video-global-v2v flux-3-video-global-draft-enhance ``` - `t2v`:`prompt`;`i2v`:`prompt` + `images`(1–10 张关键帧) - `v2v`:`prompt` + `metadata.video_url`(单个 MP4) - `draft-enhance`:`metadata.draft_cache`(来自上一条 `metadata.draft=true` 的完成任务) - 通用:`seconds` 5–20;`metadata.resolution`=`hd`/`fhd`;`metadata.ratio`=`auto`/`21:9`/`2:1`/`16:9`/`4:3`/`1:1`/`3:4`/`9:16` - 可选:`metadata.draft`、`metadata.generate_audio`、`metadata.safety_tolerance`(0 最严,4 最宽) - `global` 变体使用海外版,按 USD→CNY 结算 ## Animate Motion Transfer(Animate 动作迁移) 公开模型 ID:`animate-motion-transfer`。将一条参考视频的动作迁移到一张角色图片,输出 MP4 视频。 `POST /v1/video/generations` 提交,`GET /v1/video/generations/{id}` 查询; 查询响应的成功视频位于 `data.result_url`,完整输出列表位于 `data.data.content.video_urls`。也可通过 OpenAI 兼容查询 `/v1/videos/{id}` 获取 `video_url` 与 `metadata.video_urls`。不需要提示词。 固定零售价:**480P ¥0.20/秒、720P ¥0.30/秒、1080P ¥0.40/秒**。 按生成视频的实际播放时长结算,包含小数秒;例如 480P 的 2 秒视频为 ¥0.40。 帧数上限用于预扣,完成后按实测输出结算差额。读取输出时长失败时会重试查询,不以 GPU 耗时或输入帧数冒充最终时长。 ```json { "model": "animate-motion-transfer", "images": ["https://cdn.example.com/character.png"], "metadata": { "video_url": ["https://cdn.example.com/motion.mp4"], "resolution": "720p", "ratio": "adaptive", "frame_rate": 30, "pose_method": "vitpose" } } ``` | 字段 | 范围与默认值 | | --- | --- | | `images` | 必填,恰好一张图片 | | `metadata.video_url` | 必填,恰好一条参考视频 | | `metadata.resolution` | `480p / 720p / 1080p`,默认 `720p` | | `metadata.ratio` | 默认 `adaptive`;或 `宽:高`,两项均为 1–999999 的整数 | | `metadata.frame_rate` | 正整数 1–999999,默认 30 | | `metadata.max_frames` | 正整数 1–999999,默认 840;1080P 默认取 840 与帧率×10 的较小值,且不能超过帧率×10 | | `metadata.skip_frames` | 整数 0–999999,默认 0 | | `metadata.pose_method` | `vitpose / sdpose / wuwupose`,默认 `vitpose` | | `metadata.normal_mode` | 布尔值,默认 true | | `metadata.neck_correction` | 布尔值,默认 false | | `metadata.pose_strength` | 数值,默认 1 | | `metadata.camera_motion` | 布尔值,默认 false | | `metadata.camera_strength` | 数值,默认 1 | | `metadata.mask_mode` | 布尔值,默认 false | | `metadata.expression_strength` | 数值,默认 0.8 | | `metadata.chest_motion_strength` | 数值,默认 0.2 | 输入帧数是上限,不能保证输出时长。1080P 依上游参数说明限制为最多 10 秒; 不提供 ZIP、原始节点 ID、音频、seed 或提示词控制。 #### qwen image global 2.1 `qwen-image-global-2.1`:`POST /v1/image/generations`,`GET /v1/image/generations/{id}` 查询。 使用海外应用。`metadata.resolution` 可选 1k、2k、4k,默认 2k,最高 4k。 `prompt` 必填;`images` 可选 0–10 张,不传图为文生图,传图为图生图。1K 为 ¥0.10、2K 为 ¥0.20/张,4K 为 ¥0.40/张,两种模式同价。 `metadata.ratio`:1:1、2:3、3:2、3:4、4:3、9:16、16:9、21:9,默认 3:4。 长边按所选分辨率限制为 1024、2048、4096 像素,实际尺寸随比例和工作流对齐略有变化;不再接受 `metadata.megapixels`。`metadata.seed`:可选 0–9007199254740991,默认随机,0 有效。 每任务一张图,仅支持 n=1。成功图片见 `data.result_url`;多图输出列表见 `data.data.content.image_urls`。 完整文档:https://api.seedance.nz/docs/qwen-image-global-2.1.md #### Minimax H3 OW / FlashVSR / VOSR2(视频与超分,11) ``` minimax-h3-ow-t2v minimax-h3-ow-r2v minimax-h3-ow-i2v minimax-h3-ow-r2v-fast minimax-h3-ow-i2v-fast minimax-h3-ow-fl2va-audio-drive-fast minimax-h3-ow-ref2va-audio-drive-fast minimax-h3-ow-t2v-fast FlashVSR_video_upscale vosr2-video-upscale vosr2-image-upscale ``` - 六个全能 SKU 的时长:`5` / `10` / `15`;分辨率:`480P` / `768P` / `1080P`。两个 audio-drive SKU 保持 `480p` / `720p`。 - `metadata.ratio`:`1:1` `2:3` `3:2` `3:4` `4:3` `9:16` `16:9`(默认)`21:9` - t2v / r2v / i2v 固定零售(元):480P 5/10/15s = 0.2/0.5/1.0;768P 5/10/15s = 0.5/1.0/2.0;1080P = 0.6/1.5/3.0 - 三个全能 fast SKU 零售(元/次):480P 5/10/15 秒 = 0.3/0.5/1.0;768P = 0.6/1.0/2.0;1080P = 0.9/1.5/3.0。两个 audio-drive SKU 的旧价格和分辨率不变。 - `FlashVSR_video_upscale`:使用 `POST /v1/video/generations`;`metadata.video_url` 必填且仅一条,输入 480P、3–15 秒;固定 ¥1/次。 - `vosr2-video-upscale`:使用 `POST /v1/video/generations`;`metadata.video_url` 必填且仅一条,输出 2K 视频;固定 1.00 元/次,报价、预扣和成功结算同价。 - `vosr2-image-upscale`:使用 `POST /v1/image/generations`;`images` 必填且仅一张,输出 4K 图片;固定 0.10 元/次,报价、预扣和成功结算同价。 - 两个 VOSR2 SKU 按最终实扣金额结算。 #### Vidu Q3(15) ``` vidu-q3-pro-t2v vidu-q3-turbo-t2v vidu-q3-pro-fast-t2v vidu-q3-pro-i2v vidu-q3-turbo-i2v vidu-q3-pro-fast-i2v vidu-q3-pro-start-end vidu-q3-turbo-start-end vidu-q3-pro-fast-start-end vidu-q3-r2v vidu-q3-mix-r2v vidu-q3-ad-r2v vidu-q3-drama-r2v vidu-q3-drama-short-play vidu-q3-ad-short-play ``` - t2v:`metadata.ratio`→`aspectRatio`;start-end 需两张图;r2v 用 `images[]`→`imageUrls` - short-play:`prompt`→`scriptContent`,`metadata.script_name`→`scriptName` #### Vidu Q4 Preview(4) ``` vidu-q4-preview-r2v vidu-q4-preview-i2v vidu-q4-preview-global-r2v vidu-q4-preview-global-i2v ``` - `POST /v1/video/generations`。参考生视频 `images` 1–15 → `imageUrls`,可选 `metadata.audio_urls` 0–3 个 MP3;图生视频恰好 1 张 `images` → `imageUrl`,提示词可省略 - `seconds` 3–16,默认 5;`metadata.resolution`:`540p` `720p` `1080p` `2k` `4k`,默认 `720p` - 只有参考生视频接受 `metadata.ratio`:`16:9`(默认)`9:16` `1:1` `4:3` `3:4` - `metadata.generate_audio` 默认开启;`metadata.is_rec` 默认开启;`metadata.watermark` 默认关闭 - 国内 SKU 按人民币上游消耗结算;`vidu-q4-preview-global-*` 走海外上游,美元金额先按汇率换成人民币 ### Zhenzhen 扩展视频 / 图片(共 13 个) 视频走 `POST /v1/videos`(兼容 `/v1/video/generations`),图片走 `POST /v1/image/generations`。 按实际消耗结算:提交预扣、成功多退少补、失败全额退款。结果直链约 24 小时过期,请及时下载转存。 命名注意:`zhenzhen-image-g-v2-lowprice` 与 `zhenzhen-image-g2-*` 是不同模型。 #### 视频 ``` zhenzhen-video-gk-v15 # 文生/图生视频;seconds 6–30;resolution 480p|720p;ratio 16:9|9:16|1:1|3:2|2:3;可选 images≤7 zhenzhen-video-v31-fast # 视频(fast);时长固定 8s;resolution 720p|1080p|4k;ratio 16:9|9:16;images≤3(3 张=reference) zhenzhen-video-v31-quality # 视频(quality);同 fast 但禁止 reference(勿传 type=reference 或 3 张参考图) zhenzhen-video-v31-lite # 视频(lite);仅文生视频;禁 images / type;时长固定 8s;resolution 720p|1080p|4k;ratio 16:9|9:16 zhenzhen-video-g-omni-flash # 多模态视频(文/图/视频编辑);prompt 和/或 images≤16 / metadata.video_url(≤1)/ metadata.extend_from_task_id(与 video_url 互斥);resolution 仅 720p;时长不可指定 zhenzhen-video-g-omni-flash-lowprice # 文/图/参考视频生成;prompt 必填;seconds 4|6|8|10(默认 6);resolution 720p|1080p|4k;aspect_ratio 16:9|9:16;images 为 0/1/3 张;generation_type frame|reference;metadata.video_url≤1(传视频时省略 seconds) zhenzhen-video-g-omni-1.1-flash-lowprice # 文/图/参考视频生成;prompt 必填;seconds 4|6|8|10(默认 6);resolution 720p|1080p|4k;aspect_ratio 16:9|9:16;images 为 0/1/3 张;generation_type frame|reference;metadata.video_url≤1(传视频时省略 seconds) ``` 示例 · `zhenzhen-video-gk-v15`: ```json { "model": "zhenzhen-video-gk-v15", "prompt": "A dog running on the beach, sunny weather, slow motion", "seconds": "6", "metadata": { "resolution": "480p", "ratio": "16:9" } } ``` 示例 · `zhenzhen-video-v31-fast`: ```json { "model": "zhenzhen-video-v31-fast", "prompt": "Dolphins leaping in the azure ocean", "seconds": "8", "metadata": { "resolution": "720p", "ratio": "16:9" } } ``` 示例 · `zhenzhen-video-g-omni-flash`: ```json { "model": "zhenzhen-video-g-omni-flash", "prompt": "a blue butterfly landing on a flower, macro, soft light", "metadata": { "ratio": "16:9", "resolution": "720p" } } ``` `metadata.video_url` 改视频时: ```json { "model": "zhenzhen-video-g-omni-flash", "prompt": "change the sky to sunset orange", "metadata": { "video_url": "https://cdn.example.com/clip.mp4", "ratio": "16:9", "resolution": "720p" } } ``` 示例 · `zhenzhen-video-g-omni-flash-lowprice`: ```json { "model": "zhenzhen-video-g-omni-flash-lowprice", "prompt": "a paper airplane glides across a quiet blue studio", "seconds": "6", "resolution": "720p", "aspect_ratio": "16:9", "nsfw_check": false } ``` 示例 · `zhenzhen-video-g-omni-1.1-flash-lowprice`: ```json { "model": "zhenzhen-video-g-omni-1.1-flash-lowprice", "prompt": "a paper airplane glides across a quiet blue studio", "seconds": "4", "resolution": "720p", "aspect_ratio": "16:9", "nsfw_check": false } ``` 图生视频可传 1 张首帧图,或设置 `generation_type=reference` 并传 1/3 张参考图。参考视频生成时传 `metadata.video_url`,并省略 `seconds`。 #### 图片 ``` zhenzhen-image-g-v2-lowprice # 文生图/图生图;resolution 1k|2k|4k;n 1–10;size 比例枚举或 WxH;可选 images≤16 zhenzhen-image-gk-v15 # 文生图;n 1–10;size 1:1|16:9|9:16|3:2|2:3 zhenzhen-image-gk-v15-edit # 图编辑;必填 images[](取首张);n 1–10 zhenzhen-image-gk-v2 # Grok Imagine 2.0 仅文生图,不接受 images;n 1–12;size 1:1|2:3|3:2|3:4|4:3|9:16|16:9;resolution 可省略或为 quality zhenzhen-image-gk-v2-edit # 图编辑/多图参考;必填 images 1–3;n 1–10;aspect_ratio 为 auto 或 13 种固定比例;resolution 1k|2k;可选 nsfw_check;不接受 quality zhenzhen-image-gk-v2-segment # 对已完成的单图任务分割;operation=segment;必填 source_task_id;免费;结果在 data.content.result zhenzhen-image-gk-v2-region-edit # 区域编辑;operation=region_edit;必填 image_id、prompt;selection_regions|boxes|object_indices 至少一项 zhenzhen-image-nb-flash # Nano Banana;resolution 仅 1k;n=1;size 含 auto/21:9;可选 images≤14;prompt≤1000 zhenzhen-image-nb-2 # Nano Banana 2;resolution 0.5k|1k|2k|4k;n=1;含极端比例 1:8/8:1;可选 images≤14;不支持 output_format(含 metadata.output_format),传入返回 400;输出图片格式由上游决定 zhenzhen-image-nb-2.1-lowprice # Nano Banana 2.1 低价版;文生图/多图编辑(最多 14 张参考图);resolution 1k|2k|4k;n=1;每张分别 ¥0.06/¥0.08/¥0.10 zhenzhen-image-nb-pro-lowprice # Nano Banana Pro 低价版;文生图/多图编辑(最多 14 张参考图);resolution 1k|2k|4k;n=1;每张分别 ¥0.09/¥0.12/¥0.15;支持 auto 与 10 种标准比例,不支持 1:4/4:1/1:8/8:1 zhenzhen-image-nb-2.1 # Nano Banana 2.1;文生图/图生图;resolution 1k|2k|4k;n=1;标准比例与 auto;可选 images≤14;不支持 output_format zhenzhen-image-nb-2-lite # Nano Banana Lite;resolution 仅 1k;n 1–4;可选 images≤14 zhenzhen-image-nb-pro # Nano Banana Pro;resolution 1k|2k|4k;n=1;可选 images≤14 mai-image-2-6 # 文生图/参考图编辑与合成;images 0–5;n=1;文生图 1k|2k 或精确像素;PNG mai-image-2-6-flash # 参数同 MAI Image 2.6 flux-3-image # FLUX 3 Image; text-to-image/reference editing; images<=10; aspect_ratio supports 15 ratios+auto; resolution 768sq|1k|1.5k|2k|4k; n=1; grounding default true; safety_tolerance 0-4 flux-3-image-t2i # FLUX 3 Image text-to-image; resolution 768sq|1k|1.5k|2k|4k; aspect_ratio 15 ratios+auto; grounding default true; safety_tolerance 0-4; USD usage flux-3-image-i2i # FLUX 3 Image image editing; images 1-10 (10 MB each); resolution 768sq|1k|1.5k|2k|4k; aspect_ratio 15 ratios+auto; grounding default true; safety_tolerance 0-4; USD usage flux-3-image-klein-t2i # FLUX 3 Image Klein text-to-image; resolution 768sq|1k|1.5k|2k|4k; aspect_ratio 15 ratios+auto; seed 0-2147483647; metadata.steps 1-16; output_format jpeg|png; USD usage flux-3-image-klein-i2i # FLUX 3 Image Klein image editing; images 1-10 (10 MB each); resolution 768sq|1k|1.5k|2k|4k; aspect_ratio 15 ratios+auto; seed 0-2147483647; metadata.steps 1-16; output_format jpeg|png; USD usage ``` 示例 · `zhenzhen-image-gk-v2-edit`: ```json { "model": "zhenzhen-image-gk-v2-edit", "prompt": "将产品图转换为水彩海报,并参考第二张图的配色", "images": [ "https://cdn.example.com/product.png", "https://cdn.example.com/style.png" ], "n": 1, "aspect_ratio": "auto", "resolution": "1k", "nsfw_check": false } ``` 示例 · `zhenzhen-image-gk-v2-segment`: ```json { "model": "zhenzhen-image-gk-v2-segment", "operation": "segment", "source_task_id": "task_completed_single_image", "include_mask_rle": true } ``` 完成后从 `data.content.result.image_id` 和 `data.content.result.objects` 读取区域信息,再提交区域编辑: ```json { "model": "zhenzhen-image-gk-v2-region-edit", "operation": "region_edit", "image_id": "image_from_segment_result", "prompt": "把选中物体替换成红色背包", "object_indices": [0] } ``` 示例 · `zhenzhen-image-g-v2-lowprice`: ```json { "model": "zhenzhen-image-g-v2-lowprice", "prompt": "A ginger cat sitting on a windowsill watching the sunset, watercolor", "n": 1, "size": "1:1", "metadata": { "resolution": "1k" } } ``` 示例 · `zhenzhen-image-gk-v15-edit`: ```json { "model": "zhenzhen-image-gk-v15-edit", "prompt": "Change the background to a soft starry night sky, keep the subject", "images": ["https://cdn.example.com/original.png"], "n": 1 } ``` `size` / `n` 也可写在顶层;`metadata.ratio` / `metadata.size` 等价于比例字段。 ### HY Image 3.5 Preview - Model: `zhenzhen-image-hy-v3.5-preview` - Guide: https://api.seedance.nz/docs/#hy-image-35-preview - Submit: `POST /v1/image/generations` - Poll: `GET /v1/image/generations/{id}` - Required nonempty `prompt`, in Chinese or English. Optional ordered `images`: 0–5 public HTTP(S) JPEG, PNG or WebP URLs. Base64 inputs are not supported; upload files first. Files under 7 MB each are recommended. - `size`: `auto|1:1|2:3|3:2|3:4|4:3|4:5|5:4|9:16|16:9|21:9` or exact pixels such as `2000x1104`. Default auto: 1:1 for text-to-image, or follows references. - `resolution`: `1K|2K|4K`, case-insensitive, default 1K. - `width` and `height`: optional paired integers, each 256–8192, total pixels at most 8,294,400. Multiples of 16 are recommended, not required. - Priority: width + height > exact pixel size > ratio or auto + resolution. All supplied fields must be valid, even when overridden. Exact pixels select the billing tier by short side: ≤1024 is 1K, 1025–2048 is 2K, >2048 is 4K. - `negative_prompt`: optional string. `seed`: optional nonnegative integer; omitted or 0 selects a random result. `n`: integer 1 only. - Returns one image URL. Save generated files before the URL expires. Charges settle after completion; failed tasks are refunded. See the console for pricing. - No masks, video/audio references, stream or custom output formats. Save the task ID and resume polling after a timeout instead of submitting again. ```bash curl https://api.seedance.nz/v1/image/generations \ -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \ -d '{"model":"zhenzhen-image-hy-v3.5-preview","prompt":"A blue ceramic mug on an ivory table","size":"16:9","resolution":"2K","seed":0,"n":1}' curl https://api.seedance.nz/v1/image/generations/TASK_ID \ -H "Authorization: Bearer $API_KEY" ``` ```json {"model":"zhenzhen-image-hy-v3.5-preview","prompt":"Combine both references into one scene","images":["https://example.com/first.png","https://example.com/second.png"],"width":2000,"height":1104,"negative_prompt":"text, watermark","seed":42,"n":1} ``` ### Muse Video - Model: `zhenzhen-video-muse` - Guide: https://api.seedance.nz/docs/#muse-video - Submit: `POST /v1/video/generations` - Poll: `GET /v1/video/generations/{id}` - Required nonempty `prompt`; optional ordered `images` (0–9 public HTTP(S) URLs, image Data URIs or base64). Total original image bytes must not exceed 11 MiB. - Each request returns one MP4 video of about 10 seconds at 720p with audio. - `duration`: 10; `resolution`: `720p`; `n`: integer 1; `audio`: true. Omitted fixed fields use these defaults. Other values are rejected. - `size`: `auto|1:1|16:9|9:16|4:3|3:4|3:2|2:3`. Auto uses 16:9 for text-to-video or follows the reference composition. - `aspect_ratio`: one of those seven numeric ratios; omit for auto. It overrides valid `size`, but both fields are validated independently. - Reference images guide composition without guaranteeing an identical first frame. No reference video/audio, silent output, first/last-frame control, extension, remix, seed, negative prompt, custom dimensions or output formats. - Charges settle after completion. Failed tasks are refunded; see the console for pricing. Save the task ID and resume polling after a timeout instead of submitting again. ```bash curl https://api.seedance.nz/v1/video/generations \ -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \ -d '{"model":"zhenzhen-video-muse","prompt":"Ocean waves at sunset, natural wave sounds","size":"auto","duration":10,"resolution":"720p"}' curl https://api.seedance.nz/v1/video/generations/TASK_ID \ -H "Authorization: Bearer $API_KEY" ``` ```json {"model":"zhenzhen-video-muse","prompt":"Gently animate the reference scene with natural sound","images":["https://example.com/first.png","https://example.com/second.png"],"aspect_ratio":"16:9","duration":10,"resolution":"720p"} ``` ### Muse Image - Model: `zhenzhen-image-muse` - Guide: https://api.seedance.nz/docs/#muse-image - Submit: `POST /v1/image/generations` - Poll: `GET /v1/image/generations/{id}` - `n`: integer `1` only. - `size`: `auto|1:1|16:9|9:16|4:3|3:4|3:2|2:3`. Text-to-image and composition with up to 9 ordered reference images. Each request generates one image. Up to 9 reference images in order, totaling at most 11 MiB before base64 encoding. Omit for text-to-image. A non-empty prompt is required, including when reference images are provided. Images accept public HTTP(S) URLs, image data URIs or base64. Choose auto or one of seven aspect ratios. Both size and aspect_ratio are validated independently; a valid aspect_ratio cannot override an invalid size. Auto uses 1:1 for text-to-image or follows the reference composition. Pixel dimensions are not supported. Each task returns one image URL. The model chooses the image dimensions and format; WebP and PNG have been observed. The API also accepts aspect_ratio with one of the seven ratios. It takes priority over size; omit it for automatic composition. Resolution tiers, pixel dimensions, masks, video and audio references are not supported. Charges are settled after completion. Failed tasks are refunded; see the console for pricing. Keep the returned task ID and poll until success or failure. A timeout does not cancel the task; resume polling instead of submitting again. ```json {"model":"zhenzhen-image-muse","prompt":"Combine both references into one scene","images":["https://example.com/first.png","https://example.com/second.png"],"aspect_ratio":"16:9","n":1} ``` ### MAI Image 2.6 / Flash - 网页指南:https://api.seedance.nz/docs/#mai-image-26 - 模型:`mai-image-2-6`、`mai-image-2-6-flash`。 - 提交:`POST /v1/image/generations`;查询:`GET /v1/image/generations/{id}`。 - 支持文生图、单图编辑和多图参考合成,每次输出一张 PNG。 | 字段 | 契约 | | --- | --- | | `prompt` | 必填,中英文描述或编辑指令,上限约 32000 Token。 | | `images` | 可选,0–5 张公开图片 URL 或 Base64 图片 data URL。JPEG、PNG 直接使用,WebP、GIF 转换。 | | `n` | 固定 1,默认 1。 | | `size` | 文生图:auto、1:4 至 4:1 的整数宽高比,或 1536x1024 等像素尺寸,支持 x、*、×。 | | `resolution` | 文生图:1k / 2k(兼容大小写),默认 1k;精确像素优先。 | | `width` / `height` | 成对提供,优先于 size;每边 ≥768,宽×高 ≤2359296,向下取整至 32 的倍数。 | | `auto_aspect_ratio` | boolean,默认 false;true 等价于 size=auto。 | | `web_grounding` | boolean,默认 false;true 使用 Bing 检索当前信息。 | 参考图编辑忽略 size、resolution、width、height,模型根据参考图比例选择约 100 万像素的输出。不支持蒙版参数或自定义输出格式。按实际文本输入、参考图输入和图片输出用量结算,失败全额退款,价格以控制台为准。结果链接有效期为 72 小时,请及时保存。 ```bash curl https://api.seedance.nz/v1/image/generations \ -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \ -d '{"model":"mai-image-2-6","prompt":"A red ceramic teapot on a white table","resolution":"2k","size":"1:1","n":1,"web_grounding":false,"auto_aspect_ratio":false}' curl https://api.seedance.nz/v1/image/generations/TASK_ID \ -H "Authorization: Bearer $API_KEY" ``` 精确尺寸:`{"model":"mai-image-2-6-flash","prompt":"A blue teapot on a white table","width":1536,"height":1024,"n":1}`。 参考图编辑:`{"model":"mai-image-2-6-flash","prompt":"Change the teapot to blue, preserve the composition","images":["https://example.com/reference.png"],"n":1}`。 ### Nano Banana 2.1 低价版(zhenzhen-image-nb-2.1-lowprice) POST /v1/image/generations;GET /v1/image/generations/{id} 查询异步任务,均使用 Bearer API Key。 文生图和图生图同价,每次一张:1k ¥0.06、2k ¥0.08、4k ¥0.10;失败退费。 prompt 必填,1–5000 字符;n=1 表示每次输出一张图片;可选 images 数组最多 14 张参考图,支持公开图片 URL 或 data:image URI,按传入顺序使用。 metadata.resolution 为 1k|2k|4k,默认 1k,兼容顶层 resolution 和大小写。 size 支持 auto、1:1、2:3、3:2、3:4、4:3、4:5、5:4、9:16、16:9、21:9、1:4、4:1、1:8、8:1。 不支持 output_format。结果链接 2 小时有效,请及时下载。 文生图请求: ```json {"model":"zhenzhen-image-nb-2.1-lowprice","prompt":"A blue ceramic teapot on a white table","n":1,"size":"1:1","metadata":{"resolution":"1k"}} ``` 图生图请求: ```json {"model":"zhenzhen-image-nb-2.1-lowprice","prompt":"Place the teapot from image 1 on the table from image 2, preserving both designs","images":["https://example.com/teapot.png","https://example.com/table.png"],"n":1,"size":"1:1","metadata":{"resolution":"4k"}} ``` ### Nano Banana 2.1(zhenzhen-image-nb-2.1) - 网页指南:https://api.seedance.nz/docs/#nano-banana-21 - 提交:`POST /v1/image/generations`;查询:`GET /v1/image/generations/{task_id}`。 - 不传 `images` 为文生图,传入参考图片为图生图,每次生成 1 张图片。 | 字段 | 说明 | | --- | --- | | `model` | 必填,`zhenzhen-image-nb-2.1`。 | | `prompt` | 必填,5–5000 字符,描述生成或编辑需求。 | | `images` | 可选,最多 14 张参考图片的公开 HTTP(S) 地址。 | | `n` | 仅支持 1,默认 1。 | | `size` | auto / 1:1 / 2:3 / 3:2 / 3:4 / 4:3 / 4:5 / 5:4 / 9:16 / 16:9 / 21:9;文生图默认 1:1。 | | `metadata.resolution` | 1k / 2k / 4k,默认 1k。 | 不支持 `output_format`(包括 `metadata.output_format`),请省略;图片格式由生成服务决定。按实际消耗结算,失败全额退款,金额以控制台为准。 文生图: ```bash curl -X POST https://api.seedance.nz/v1/image/generations \ -H "Authorization: Bearer $SEEDANCE_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"zhenzhen-image-nb-2.1","prompt":"A small ceramic teapot on a wooden table, soft studio light","n":1,"size":"1:1","metadata":{"resolution":"1k"}}' ``` 图生图添加参考图片: ```json { "model": "zhenzhen-image-nb-2.1", "prompt": "将茶壶改成蓝色,保留原有形状与桌面背景", "images": ["https://example.com/reference.png"], "n": 1, "size": "auto", "metadata": { "resolution": "2k" } } ``` 每 3–5 秒查询一次,直到 `data.status` 为 `SUCCESS` 或 `FAILURE`。成功图片直链位于 `data.result_url`,最终实扣金额位于 `data.usage`: ```bash curl https://api.seedance.nz/v1/image/generations/TASK_ID \ -H "Authorization: Bearer $SEEDANCE_API_KEY" ``` 结果链接约 24 小时过期,请及时下载转存。 ### 音频模型(Doubao Seed Audio + Mureka BGM,共 3 个) ``` doubao-seed-audio-1.0 # POST /v1/audio/generations;prompt→text_prompt;可选 speaker / audio_url / images mureka-v8-bgm # POST /v1/audio/generations;prompt / metadata.instrumental_id 二选一;n=1–3 mureka-v9-bgm # POST /v1/audio/generations;prompt / metadata.instrumental_id 二选一;n=1–3 minimax-speech-2.8-turbo # prompt + metadata.voice_id minimax-speech-2.8-hd # prompt + metadata.voice_id minimax-voice-clone # prompt + metadata.audio_url + metadata.custom_voice_id minimax-music-2.6 # prompt/metadata.lyrics + metadata.is_instrumental mureka-v9-song # metadata.lyrics;n=1–3;支持 vocal_id/melody_id/stream mureka-o2-song # metadata.lyrics;n=1–3;支持 reference_id qwen3-tts-flash # prompt + metadata.voice qwen3-tts-instruct-flash # prompt + metadata.voice + 可选 instructions ``` 牌价约 ¥0.004/秒(输出时长)。成功后读 `data.result_url`(音频)。 --- ## 价格与计费 ### 可灵 / 海螺 / Vidu(按次) 按次计费,非 Token。预扣 → 终态按最终实扣金额多退少补。具体金额以控制台预估与余额变动为准。 ### 视频(Seedance Token 计费) ``` 总费用 = Token 单价 × 实际消耗 Token 数 ÷ 1,000,000 + 超分附加费单价 × 输出视频时长(秒) # 仅 1080p/2k/4k 超分档 ``` - Token 消耗量由模型在任务完成后返回,与分辨率、时长、内容复杂度相关,提交前只能估算区间 - 提交时预扣额度仅为占位,任务成功后按实际用量结算并自动退还差额(多退少补) - 提交失败、生成失败均全额退款 - 最终计费以控制台余额扣减为准 ### Token 单价(人民币元 / 百万 Token) `-multi` 模型传入参考视频(`video_url`)时按「有参考视频」低单价档计费;t2v、i2v 均按「无参考视频」档。国内版与国际版价格相同。 | 档位 | 分辨率 | 无参考视频 | 有参考视频 | | --- | --- | --- | --- | | Standard | 480p / 720p | 46 | 28 | | Standard | 1080p / 2k / 4k / native1080p | 51 | 31 | | Standard | native4k | 26 | 16 | | Fast | 全部分辨率 | 37 | 22 | | Mini | 全部分辨率 | 23 | 14 | 注:`native4k` 的 Token 单价最低,但 4K 原生输出单位时长消耗的 Token 数远高于低分辨率,总价并不低。`native1080p`/`native4k` 仅 Standard 档支持。 ### 超分附加费(人民币元 / 秒,按输出视频时长计) | 分辨率 | 附加费 | | --- | --- | | 480p / 720p / native1080p / native4k | 0(免费) | | 1080p | 0.28 | | 2k | 0.42 | | 4k | 0.63 | ### 计费示例 `seedance-2.0-standard-t2v`(无参考视频)+ `1080p` + 输出 5 秒 + 实际消耗 400,000 Token: ``` Token 费用 = 51 × 400,000 ÷ 1,000,000 = ¥20.40 超分附加费 = 0.28 × 5 = ¥ 1.40 总费用 = ¥21.80 ``` ### 图片(Seedream,按上游金额结算) ``` 总费用 = 最终实扣金额(人民币) ``` - 提交前按价格预估全额预扣,成功后多退少补;失败全额退款 - 实测参考:`t2i` + `2k` ≈ ¥0.54 / 张;`i2i` + `1k` ≈ ¥0.27 / 张(最终以控制台为准) - 国内图层拆分按输出张数 × 分辨率档计费:≤236 万像素 ¥0.27/张,>236 万像素 ¥0.54/张 - V5 Flash 官方参考价:国内 ¥0.11/实际输出图,海外 $0.016/实际输出图;图层拆分按实际输出张数计算。终态实际消费和控制台扣费为准;海外成本按 `RhAiUsdToCnyRate` 换算成人民币 - Dola 海外图层拆分:≤236 万像素 $0.041/张,>236 万像素 $0.081/张;USD 先按 `结算汇率` 换算 - V5 Pro/Dola Pro 图层拆分的实测成功结果仅含有序图片 URL,没有 `z_index` / `bounding_box`;公共响应不合成这些字段。V5 Flash 上游成功样本有图层元数据;公共结果总含有序 URL 列表,`layers` 元数据数组有条件返回,不保证存在 ### Zhenzhen 扩展模型 按实际消耗结算(人民币):提交预扣 → 成功多退少补 → 失败全额退款。结果 URL 约 24 小时过期。最终以控制台余额扣减为准。 ### Midjourney(按上游 cost USD) ``` 按任务完成后的实际上游消耗结算为人民币;提交预扣,成功多退少补,失败全额退款。具体金额以控制台预估与余额变动为准。 ``` - 实测:`midjourney-imagine` @ v6.1 relax 常见 cost≈0.045 USD - 详见专节「Midjourney」 ### Suno(按上游 cost USD) ``` 按任务完成后的实际上游消耗结算为人民币(部分工具类按次);提交预扣,成功多退少补,失败全额退款。具体金额以控制台预估与余额变动为准。 ``` - 实测:`suno-generation` @ v3.5 常见 cost≈0.05 USD(常 2 轨) - 工具类无 cost 的 action 按次;失败全额退;详见专节「Suno 音乐」 ### 视频超分(Zhenzhen Upscaler,独立分类) 按输入视频时长 × 目标分辨率单价;详见专节「视频超分(Zhenzhen Upscaler)」。 | 目标分辨率 | 单价(元 / 秒) | | --- | --- | | 720p | 0.14 | | 1080p | 0.21 | | 2k | 0.35 | | 4k | 0.56 | 与上文 Seedance「超分附加费」无关。 --- ## Midjourney(独立分类)— `/v1/midjourney/*` > **不是** 旧版 `/mj/*` Discord 代理。计费 SKU=`midjourney-{action}`;body.`model`=`midjourney` 不参与路由。 > 结算:任务成功后按实际上游消耗结算;金额以控制台为准。 ### 典型流程 1. `POST /v1/midjourney/generations`(或 `/imagine`),记录 `data[0].task_id`。 2. 每 3~5 秒 `GET /v1/midjourney/tasks/{task_id}`,直到 `SUCCESS` / `FAILURE`(或 `MODAL`)。 3. 成功时取 `image_urls` / `grid_image_url`;二次操作用公开 `task_id` + `index` 或 `custom_id`。 ### POST /v1/midjourney/generations[/:action] | 路径 | SKU | | --- | --- | | `POST /v1/midjourney/generations` | `midjourney-imagine` | | `POST …/generations/imagine` | `midjourney-imagine` | | `POST …/generations/{action}` | `midjourney-{action}` | Imagine 必填 `prompt`;可选 `speed`=`relax|fast|turbo`、`size`、`version`、`image_urls` 等。 ```bash curl -X POST https://api.seedance.nz/v1/midjourney/generations \ -H "Authorization: Bearer sk-xxxx" -H "Content-Type: application/json" \ -d '{"prompt":"a small red apple on a white table","size":"1:1","version":"6.1","speed":"relax"}' ``` ### GET /v1/midjourney/tasks/{task_id} 返回 MJ 风格字段(含 `buttons`),并附带结算用 `cost`(网关合并统一任务接口)。 ### Action 一览(16) `midjourney-imagine` `midjourney-blend` `midjourney-describe` `midjourney-edits` `midjourney-upscale` `midjourney-variation` `midjourney-high-variation` `midjourney-low-variation` `midjourney-reroll` `midjourney-zoom` `midjourney-pan` `midjourney-inpaint` `midjourney-modal` `midjourney-video` `midjourney-remix-strong` `midjourney-remix-subtle` 元数据:`GET /api/midjourney/actions`。 ### Midjourney 计费 ``` 按任务完成后的实际上游消耗结算为人民币;提交预扣,成功多退少补,失败全额退款。具体金额以控制台预估与余额变动为准。 ``` 实测:`imagine` @ v6.1 relax 常见 cost≈0.045 USD。 --- ## Suno 音乐(独立分类)— `/v1/music/*` > **不是** Seed Audio(`/v1/audio/generations`)也 **不是** Whisper(`/v1/audio/transcriptions`)。 > 计费 SKU = 路径推导的 `suno-{action}`;body.`model` 固定/可写 `suno`,不参与路由。 > 结算:多数 action 按实际上游消耗结算,工具类按次;失败全额退;金额以控制台为准。 ### 典型流程 1. `POST /v1/music/generations` 或 `…/generations/{action}`,记录 `data[0].task_id`。 2. 每 3~5 秒 `GET /v1/music/tasks/{task_id}`,直到 `data.status` 为 `completed` / `failed`。 3. 成功时从 `data.result.music[]` 取 `audio_url`(常见 2 轨),立即下载转存。 4. 二次处理用本站公开 `task_*` id(+ 可选 `audio_index`,1-based)。 ### POST /v1/music/generations[/:action] | 路径 | 计费 SKU | | --- | --- | | `POST /v1/music/generations` | `suno-generation` | | `POST /v1/music/generations/{action}` | `suno-{action}`(kebab-case) | #### generation 常用字段 | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | | `version` | string | 是 | `v3.5`/`v4`/`v4.5`/`v4.5+`/`v4.5-all`/`v5`/`v5.5` | | `prompt` | string | 是 | 灵感文案或歌词(取决于 `custom`) | | `custom` | bool | 否 | `false` 灵感;`true` 自定义歌词 | | `instrumental` | bool | 否 | `true` 纯伴奏 | | `title` / `style` / `vocal_gender` | string | 否 | 曲名、风格标签、人声偏好 | | `model` | string | 否 | 可写 `suno`;不参与路由 | #### 二次处理引用 | 字段 | 场景 | | --- | --- | | `task_id` + `audio_index` | 多数基于已有轨的 action | | `task_ids`(恰好 2) | `mashup` | | `audioFilePath` / `audio_url` / `audio_urls` | upload / create-voice / inspo | | `continue_at` / `start_s` / `end_s` / `duration_s` / `speed` | 按 action 必填 | 提交响应: ```json { "code": 200, "data": [{ "status": "submitted", "task_id": "task_xxxxxxxxxxxx" }] } ``` 示例 · generation: ```bash curl -X POST https://api.seedance.nz/v1/music/generations \ -H "Authorization: Bearer sk-xxxx" \ -H "Content-Type: application/json" \ -d '{"model":"suno","custom":false,"version":"v5","prompt":"lo-fi piano with soft rain","instrumental":true}' ``` 示例 · extend: ```bash curl -X POST https://api.seedance.nz/v1/music/generations/extend \ -H "Authorization: Bearer sk-xxxx" \ -H "Content-Type: application/json" \ -d '{"model":"suno","task_id":"task_xxx","audio_index":1,"continue_at":30,"version":"v5.5"}' ``` ### GET /v1/music/tasks/{task_id} 成功时(节选): ```json { "code": 200, "data": { "id": "task_xxxxxxxxxxxx", "status": "completed", "progress": 100, "cost": 0.05, "result": { "music": [ { "audio_url": "https://.../a.mp3", "duration": 103.56, "title": "..." }, { "audio_url": "https://.../b.mp3", "duration": 86 } ] } } } ``` ### Action / SKU 一览(31) 生成类:`suno-generation` `suno-lyrics` `suno-upload` `suno-inspo` `suno-sounds` `suno-create-voice` `suno-upsample-tags` 任务引用类:`suno-extend` `suno-cover-song` `suno-mashup` `suno-stems` `suno-stems-all` `suno-wav` `suno-generate-mp4` `suno-concat` `suno-crop` `suno-fade-in` `suno-fade-out` `suno-remove-section` `suno-replace-music` `suno-adjust-speed` `suno-remaster` `suno-midi` `suno-bpm` `suno-aligned-lyrics` `suno-persona` `suno-vox` `suno-sample` `suno-add-vocals` `suno-add-instrumental` `suno-add-stem` 元数据:`GET /api/music/actions`(无需鉴权,返回 registry)。 ### Suno 计费 ``` 按任务完成后的实际上游消耗结算为人民币(部分工具类按次);提交预扣,成功多退少补,失败全额退款。具体金额以控制台预估与余额变动为准。 ``` - 实测:`suno-generation` @ v3.5 常见 `cost≈0.05` USD(常 2 轨) - 无 `cost` 的工具类 action 按次计费;本地 400 零扣费;失败全额退 --- ## 错误处理 | HTTP | 场景 | 响应示例 | | --- | --- | --- | | 400 | 缺少必填参数(如 prompt) | `{"code":"invalid_request","message":"prompt is required"}` | | 400 | 缺少任务类型所需素材(如 i2v 缺 images) | `{"code":"fail_to_fetch_task","message":"...image-to-video requires at least one input image..."}` | | 401 | 鉴权失败 | 缺少或格式错误的 `Authorization` 头 | | 429 | 上传接口超过频率限制 | 每令牌每分钟 30 次 / 每天 10000 次 | | 503 | model 不存在/未挂载 | `{"error":{"code":"model_not_found","message":"No available channel for model ..."}}` | 提交失败不会真正扣费;生成阶段失败通过查询接口的 `status: "failed"` + `error` 字段返回,同样全额退款。 --- ## 完整代码示例 ### Python ```python import time import requests BASE_URL = "https://api.seedance.nz" API_KEY = "sk-xxxxxxxxxxxx" headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"} resp = requests.post( f"{BASE_URL}/v1/videos", headers=headers, json={ "model": "seedance-2.0-mini-t2v", "prompt": "a calm lake at sunrise", "seconds": "5", "metadata": {"resolution": "480p"}, }, ) resp.raise_for_status() task_id = resp.json()["id"] while True: result = requests.get(f"{BASE_URL}/v1/videos/{task_id}", headers=headers).json() if result["status"] in ("completed", "failed"): break time.sleep(3) if result["status"] == "completed": print("video url:", result["metadata"]["url"]) else: print("failed:", result.get("error")) ``` ### Node.js ```javascript const BASE_URL = "https://api.seedance.nz"; const API_KEY = "sk-xxxxxxxxxxxx"; const headers = { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json" }; const submit = await fetch(`${BASE_URL}/v1/videos`, { method: "POST", headers, body: JSON.stringify({ model: "seedance-2.0-mini-t2v", prompt: "a calm lake at sunrise", seconds: "5", metadata: { resolution: "480p" }, }), }); const { id: taskId } = await submit.json(); let result; do { await new Promise((r) => setTimeout(r, 3000)); result = await (await fetch(`${BASE_URL}/v1/videos/${taskId}`, { headers })).json(); } while (!["completed", "failed"].includes(result.status)); console.log(result.status === "completed" ? result.metadata.url : result.error); ``` --- ## 给 AI 编程工具的实现要点(Checklist) - [ ] 视频用 `/v1/videos`;图片用 `/v1/image/generations`;音频用 `/v1/audio/generations`(不要与 `/v1/audio/speech` 混用) - [ ] 视频 `seconds` 是字符串类型(如 `"5"`),不是数字 - [ ] 视频轮询终态:`completed` / `failed`,结果在 `metadata.url` - [ ] 图片轮询终态:`data.status` 为 `SUCCESS` / `FAILURE`,结果在 `data.result_url` - [ ] 轮询间隔 3~5 秒;成功后立即下载直链(临时签名,会过期) - [ ] 视频 `-i2v` 用顶层 `images`;`-multi` 用 `metadata.content`(会覆盖 `images`) - [ ] 图片 `i2i` 必须传 `images`(1~10 张);`prompt` 长度 5~2000 - [ ] 图片 `metadata.resolution`(`1k`/`2k`)优先于 `width`/`height` - [ ] 本地素材先经 `POST /v1/files/upload` 换直链(24 小时有效) - [ ] API Key 放服务端环境变量,不要写进前端代码 - [ ] 失败任务无需重复扣费处理——网关自动全额退款 # Midjourney、Suno 与 Flow Music(api.seedance.nz) Flow Music 路径 SKU:`flowmusic-generation`、`flowmusic-lyrics`、`flowmusic-extend`、`flowmusic-replace`、`flowmusic-cover`、`flowmusic-stems`、`flowmusic-upload-audio`、`flowmusic-download-audio`、`flowmusic-video-clip`。 ## MIDJOURNEY ### Midjourney API 概览 (#mj-overview) # Midjourney API 概览 > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > - Midjourney 文生图(Imagine)/ 垫图 / 二次操作 / 图生视频接口总览 - 异步任务模式:提交后返回 task_id,轮询查询结果 - 新版路由自动注入 model=midjourney,支持原生 MJ 参数、body 结构化参数与 metadata **Base URL:** `https://api.seedance.nz` **鉴权:** `Authorization: Bearer ` 新版 `/v1/midjourney/...` 路由会自动注入 `model=midjourney`,请求体不需要传 `model`。 ## 快速开始 ```bash # 1. 提交绘图 curl -X POST https://api.seedance.nz/v1/midjourney/generations \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"prompt": "a cute cat, watercolor style --ar 16:9"}' # 2. 查询结果(推荐轮询统一任务接口直到 status=completed) curl https://api.seedance.nz/v1/tasks/task_01JWXXXX \ -H "Authorization: Bearer " # 3. 放大第1张图 curl -X POST https://api.seedance.nz/v1/midjourney/generations/upscale \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"task_id": "task_01JWXXXX", "index": 1}' ``` ## 接口总览 每个功能的完整字段、示例、注意事项见对应子页面。 | 功能 | 路径 | 文档 | | ---------- | ---------------------------------------------------------------- | ---------------------------------- | | 文生图(默认入口) | `POST /v1/midjourney/generations` | [Imagine](#mj-imagine) | | 文生图(显式入口) | `POST /v1/midjourney/generations/imagine` | [Imagine](#mj-imagine) | | 多图融合 | `POST /v1/midjourney/generations/blend` | [Blend](#mj-blend) | | 图生文(识图) | `POST /v1/midjourney/generations/describe` | [Describe](#mj-describe) | | 图片编辑 | `POST /v1/midjourney/generations/edits` | [Edits](#mj-edits) | | 放大选图 | `POST /v1/midjourney/generations/upscale` | [Upscale](#mj-upscale) | | 生成变体 | `POST /v1/midjourney/generations/variation` | [Variation](#mj-variation) | | 大幅变体 | `POST /v1/midjourney/generations/high-variation` | [High Variation](#mj-high-variation) | | 微调变体 | `POST /v1/midjourney/generations/low-variation` | [Low Variation](#mj-low-variation) | | 重新生成 | `POST /v1/midjourney/generations/reroll` | [Reroll](#mj-reroll) | | 缩放扩展 | `POST /v1/midjourney/generations/zoom` | [Zoom](#mj-zoom) | | 平移扩展 | `POST /v1/midjourney/generations/pan` | [Pan](#mj-pan) | | 局部重绘 | `POST /v1/midjourney/generations/inpaint` | [Inpaint](#mj-inpaint) | | Modal 补充参数 | `POST /v1/midjourney/generations/modal` | [Modal](#mj-modal) | | 图生视频 | `POST /v1/midjourney/generations/video` | [Video](#mj-video) | | 重塑(强 / 弱) | `POST /v1/midjourney/generations/remix-strong` · `/remix-subtle` | [Remix](#mj-remix) | | 任务查询 | `GET /v1/tasks/{task_id}` · `/v1/midjourney/{task_id}` | [任务查询](#mj-query) | 参考:[最佳实践](#mj-best-practices)(轮询 / 重试 / 排错) · [完整工作流示例](#mj-workflow)(端到端 curl + 客户端封装) ## 完整使用流程 ```mermaid flowchart TB A["① POST /generations
提交 Imagine"] --> B["② GET /v1/tasks/{task_id}
轮询至 completed"] B --> C["③ 如需按钮
GET /v1/midjourney/{task_id}"] C --> D1["/upscale"] C --> D2["/variation"] C --> D3["/reroll"] C --> D4["/zoom"] C --> D5["/inpaint
(进入 MODAL)"] D5 --> M["/modal
提交遮罩 + prompt"] ``` ## 错误处理 ### 错误响应格式 ```json { "error": { "type": "invalid_request_error", "message": "prompt is required" } } ``` ### 常见错误 | HTTP 状态码 | type | 说明 | | -------- | ----------------------- | ---------------- | | 400 | `invalid_request_error` | 参数错误(缺少必填、格式错误等) | | 401 | `authentication_error` | API Key 无效 | | 402 | `payment_required` | 余额不足 | | 404 | `not_found` | 任务不存在 | | 429 | `rate_limit_error` | 请求频率超限 | | 500 | `internal_error` | 服务器内部错误 | ### 任务失败 `fail_reason` 常见值: * `Banned prompt detected` — 提示词含违禁内容 * `Task timeout` — 任务超时(超过 30 分钟未完成),已自动退款 * `No available upstream` — 服务暂不可用,请稍后重试 ## 计费说明 MJ 新版统一模型名是 `midjourney`,通过 action、version、speed 生成计费 key。匹配顺序通常为: ```text midjourney@-- -> midjourney@- -> midjourney@- -> midjourney@ -> midjourney ``` | 操作 | 计费名称 | 说明 | | -------------- | --------------------------------------------- | ---------------------- | | Imagine | `midjourney@imagine[-version][-speed]` | 文生图 / 垫图 | | Blend | `midjourney@blend[-speed]` | 多图融合 | | Describe | `midjourney@describe[-speed]` | 图生文 | | Edits | `midjourney@edits[-speed]` | 图片编辑 | | Upscale | `midjourney@upscale[-version][-speed]` | 放大 | | Variation | `midjourney@variation[-version][-speed]` | 变体 | | High Variation | `midjourney@high_variation[-version][-speed]` | 强变体 | | Low Variation | `midjourney@low_variation[-version][-speed]` | 弱变体 | | Reroll | `midjourney@reroll[-version][-speed]` | 重新生成 | | Zoom | `midjourney@zoom[-version][-speed]` | 缩放扩图 | | Pan | `midjourney@pan[-version][-speed]` | 平移扩图 | | Inpaint | `midjourney@inpaint[-version][-speed]` | 局部重绘入口 | | Modal | `midjourney@modal[-speed]` | 局部重绘补参 | | Video | `midjourney@video` / `midjourney@video-720p` | 图生视频,实扣 × `batch_size` | | Remix Strong | `midjourney@remix_strong[-speed]` | 强重塑(仅 v8.1 / v8.2) | | Remix Subtle | `midjourney@remix_subtle[-speed]` | 弱重塑(仅 v8.1 / v8.2) | 说明: * `speed=relax` 或未传 `speed` 时,不追加 speed 后缀;`fast` / `turbo` 会追加对应后缀。 * 主版本归一化为 `v8.2`、`v8.1`、`v7`、`v6.1`、`v5.2`、`v5.1`。 * `niji=true + version=7/6` 归一化为 `niji7` / `niji6`。 > 具体价格以控制台模型定价页为准。任务失败会自动全额退款。 ### Imagine(文生图) (#mj-imagine) # Imagine(文生图) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > Midjourney 文生图 / 垫图。默认入口 /v1/midjourney/generations 与显式入口 /imagine 行为一致 ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "prompt": "a beautiful sunset over mountains", "size": "16:9", "version": "6.1", "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations" payload = { "prompt": "a beautiful sunset over mountains", "size": "16:9", "version": "6.1", "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations"; const payload = { prompt: "a beautiful sunset over mountains", size: "16:9", version: "6.1", speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations" payload := map[string]interface{}{ "prompt": "a beautiful sunset over mountains", "size": "16:9", "version": "6.1", "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations"; String payload = """ { "prompt": "a beautiful sunset over mountains", "size": "16:9", "version": "6.1", "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "a beautiful sunset over mountains", "size" => "16:9", "version" => "6.1", "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations") payload = { prompt: "a beautiful sunset over mountains", size: "16:9", version: "6.1", speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations")! let payload: [String: Any] = [ "prompt": "a beautiful sunset over mountains", "size": "16:9", "version": "6.1", "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations"; var payload = @"{ ""prompt"": ""a beautiful sunset over mountains"", ""size"": ""16:9"", ""version"": ""6.1"", ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations"; const char *payload = "{" "\"prompt\":\"a beautiful sunset over mountains\"," "\"size\":\"16:9\"," "\"version\":\"6.1\"," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations"]; NSDictionary *payload = @{ @"prompt": @"a beautiful sunset over mountains", @"size": @"16:9", @"version": @"6.1", @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations" let payload = {|{ "prompt": "a beautiful sunset over mountains", "size": "16:9", "version": "6.1", "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations'); final payload = { 'prompt': 'a beautiful sunset over mountains', 'size': '16:9', 'version': '6.1', 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations" payload <- list( prompt = "a beautiful sunset over mountains", size = "16:9", version = "6.1", speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 422, "message": "图片或提示词未通过内容审核,已自动退款", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 默认文生图 / 垫图接口,等同于 `imagine`。显式入口 `/v1/midjourney/generations/imagine` 行为一致。 | 项目 | 内容 | | ------ | ----------------------------------------- | | action | `IMAGINE` | | 计费 | `midjourney@imagine[-version][-speed]` | | 必填 | `prompt` | | 可选 | `image_urls`、Prompt 参数、`speed`、`metadata` | ## 请求参数 | 字段 | 类型 | 必填 | 说明 | | ------------ | --------- | -- | ------------------------------------- | | `prompt` | string | 是 | 提示词,支持原生 MJ 参数(如 `--ar 16:9 --v 6.1`) | | `speed` | string | 否 | 速度模式:`relax`(默认)/ `fast` / `turbo` | | `image_urls` | string\[] | 否 | 垫图 URL(图生图场景),支持 URL 或 base64 | | `metadata` | object | 否 | 自定义元数据,会随任务保存,便于业务侧追踪 | ### 结构化参数(可选) 以下参数可以写在 body 里,也可以直接写在 prompt 中(如 `--ar 16:9`)。body 优先级高于 prompt。 | 字段 | 类型 | 等价 MJ 参数 | 说明 | | ----------------- | ------ | ---------- | -------------------------------------------------------------------------- | | `size` | string | `--ar` | 宽高比,如 `"16:9"`, `"1:1"`, `"9:16"` | | `quality` | string | `--q` | 质量:`"0.25"`, `"0.5"`, `"1"`, `"2"` | | `style` | string | `--style` | 风格:`"raw"` 等 | | `version` | string | `--v` | 版本号。主版本会追加为 `--v `;与 `niji: true` 搭配 `"7"` / `"6"` 时会归一化为 Niji 版本 | | `seed` | int | `--seed` | 随机种子 | | `negative_prompt` | string | `--no` | 负面提示词,如 `"ugly, blurry"` | | `stylize` | int | `--s` | 风格化强度 (0-1000) | | `chaos` | int | `--c` | 混乱度 (0-100) | | `weird` | int | `--w` | 怪异度 (0-3000) | | `tile` | bool | `--tile` | 平铺模式 | | `niji` | bool | `--niji` | Niji 开关。推荐传 `niji: true` + `version: "7"` / `"6"` | | `iw` | float | `--iw` | 图片权重 (0-3),垫图时使用 | | `cw` | int | `--cw` | 角色权重 (0-100) | | `sw` | int | `--sw` | 风格权重 (0-1000) | | `cref` | string | `--cref` | 角色参考图 URL | | `sref` | string | `--sref` | 风格参考图 URL | | `dref` | string | `--dref` | 深度参考图 URL | | `dw` | float | `--dw` | 深度权重 (0-100) | | `repeat` | int | `--repeat` | 重复生成次数 (2-40) | | `raw` | bool | `--raw` | 原始风格 (v5.1+ 支持) | | `draft` | bool | `--draft` | 草图模式 (v7+ 支持) | | `hd` | bool | `--hd` | HD 高清 (仅 v8.1 / v8.2,未传 version 时后端自动补 `--v 8.1`) | | `stop` | int | `--stop` | 提前停止 (10-100,仅 v5-6.1 / niji 5-6) | | `extra` | string | 任意 `--xxx` | 逃生口,原样追加到 prompt 末尾 | ## 示例 **方式一:参数写在 prompt 里** ```json { "prompt": "a beautiful sunset over mountains --ar 16:9 --v 6.1 --style raw --s 750" } ``` **方式二:参数写在 body 里(推荐)** ```json { "prompt": "a beautiful sunset over mountains", "size": "16:9", "version": "6.1", "style": "raw", "stylize": 750 } ``` **主版本与 Niji 版本** ```json { "prompt": "anime girl in a moonlit garden", "niji": true, "version": "7", "size": "9:16" } ``` > 线上已验证可用版本:`8.2`、`8.1`、`7`、`6.1`、`5.2`、`5.1`、`niji 7`、`niji 6`。主版本使用 body 字段 `version`;Niji 推荐传 `niji: true` + `version: "7"` / `"6"`,计费版本会归一化为 `niji7` / `niji6`。 **方式三:混合使用(body 优先)** ```json { "prompt": "a beautiful sunset --ar 1:1", "size": "16:9" } ``` > 最终 prompt: `a beautiful sunset --ar 16:9`(body 中的 `size` 覆盖了 prompt 中的 `--ar 1:1`) **图生图(垫图)** ```json { "prompt": "turn this product into a luxury studio photo", "image_urls": ["https://example.com/product.png"], "size": "1:1", "iw": 1.2 } ``` **Fast 模式** ```json { "prompt": "a cute cat", "speed": "fast" } ``` > `speed=relax` 或未传 `speed` 时不追加计费 speed 后缀;`fast` / `turbo` 会通过对应速度通道生效,并匹配对应计费 key。 ## 响应 ```json { "code": 200, "data": [{ "status": "submitted", "task_id": "task_01JWXXXXXXXXXXXX" }] } ``` 成功后通过[任务查询](#mj-query)轮询结果。 ### Blend(多图融合) (#mj-blend) # Blend(多图融合) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 将 2–4 张图融合成一张新图(MJ 经典 blend),完全靠图融合,不支持 prompt ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/blend \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "image_urls": [ "https://example.com/a.png", "https://example.com/b.png" ], "dimensions": "SQUARE", "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/blend" payload = { "image_urls": [ "https://example.com/a.png", "https://example.com/b.png" ], "dimensions": "SQUARE", "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/blend"; const payload = { image_urls: [ "https://example.com/a.png", "https://example.com/b.png" ], dimensions: "SQUARE", speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/blend" payload := map[string]interface{}{ "image_urls": []string{ "https://example.com/a.png", "https://example.com/b.png", }, "dimensions": "SQUARE", "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/blend"; String payload = """ { "image_urls": [ "https://example.com/a.png", "https://example.com/b.png" ], "dimensions": "SQUARE", "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php [ "https://example.com/a.png", "https://example.com/b.png", ], "dimensions" => "SQUARE", "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/blend") payload = { image_urls: [ "https://example.com/a.png", "https://example.com/b.png", ], dimensions: "SQUARE", speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/blend")! let payload: [String: Any] = [ "image_urls": [ "https://example.com/a.png", "https://example.com/b.png", ], "dimensions": "SQUARE", "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/blend"; var payload = @"{ ""image_urls"": [ ""https://example.com/a.png"", ""https://example.com/b.png"" ], ""dimensions"": ""SQUARE"", ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/blend"; const char *payload = "{" "\"image_urls\":[\"https://example.com/a.png\",\"https://example.com/b.png\"]," "\"dimensions\":\"SQUARE\"," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/blend"]; NSDictionary *payload = @{ @"image_urls": @[ @"https://example.com/a.png", @"https://example.com/b.png", ], @"dimensions": @"SQUARE", @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/blend" let payload = {|{ "image_urls": [ "https://example.com/a.png", "https://example.com/b.png" ], "dimensions": "SQUARE", "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/blend'); final payload = { 'image_urls': [ 'https://example.com/a.png', 'https://example.com/b.png', ], 'dimensions': 'SQUARE', 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/blend" payload <- list( image_urls = list( "https://example.com/a.png", "https://example.com/b.png" ), dimensions = "SQUARE", speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 422, "message": "图片或提示词未通过内容审核,已自动退款", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 将 2–4 张图融合成一张新图(MJ 经典 blend 功能),完全靠图融合,**不支持 prompt 参数**。 | 项目 | 内容 | | ------ | -------------------------- | | action | `BLEND` | | 计费 | `midjourney@blend[-speed]` | | 必填 | `image_urls`(2–4 张) | ## 参数 | 字段 | 类型 | 必填 | 默认 | 说明 | | ------------ | --------- | -- | -------- | --------------------------------------------------------------------------- | | `image_urls` | string\[] | 是 | — | 垫图,2–4 张,后端自动转 base64;单图 ≤ 12 MiB | | `dimensions` | string | 否 | `SQUARE` | 三档画面比例:`SQUARE`(1:1) / `PORTRAIT`(2:3) / `LANDSCAPE`(3:2);传了 `size` 时被覆盖 | | `size` | string | 否 | — | 自由比例,任意 `w:h`(如 `"16:9"`、`"9:16"`、`"21:9"`),**优先级高于 `dimensions`**,作为画面比例生效 | | `speed` | string | 否 | `relax` | `relax` / `fast` / `turbo` | | `metadata` | object | 否 | — | 自定义元数据 | ## 请求示例 三档比例(`dimensions`): ```json { "image_urls": [ "https://example.com/a.png", "https://example.com/b.png" ], "dimensions": "SQUARE", "speed": "fast" } ``` 自由比例(`size`): ```json { "image_urls": [ "https://example.com/a.png", "https://example.com/b.png" ], "size": "16:9", "speed": "fast" } ``` > 最终 prompt 末尾会带 `--ar 16:9`。 ## 注意 * 比例选择优先级:`size`(自由) > `dimensions`(三档) > 默认 `SQUARE`。 * `image_urls` 少于 2 张或多于 4 张返回 `400`。 * `blend` 没有独立版本参数;如需区分速度价格,可配置 `midjourney@blend-fast` / `midjourney@blend-turbo`。 ### Describe(图生文) (#mj-describe) # Describe(图生文) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 图片反推 prompt,同步返回(1–3s),结果在 prompt / description 字段 ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/describe \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "image_urls": [ "https://example.com/input.png" ], "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/describe" payload = { "image_urls": [ "https://example.com/input.png" ], "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/describe"; const payload = { image_urls: [ "https://example.com/input.png" ], speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/describe" payload := map[string]interface{}{ "image_urls": []string{ "https://example.com/input.png", }, "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/describe"; String payload = """ { "image_urls": [ "https://example.com/input.png" ], "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php [ "https://example.com/input.png", ], "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/describe") payload = { image_urls: [ "https://example.com/input.png", ], speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/describe")! let payload: [String: Any] = [ "image_urls": [ "https://example.com/input.png", ], "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/describe"; var payload = @"{ ""image_urls"": [ ""https://example.com/input.png"" ], ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/describe"; const char *payload = "{" "\"image_urls\":[\"https://example.com/input.png\"]," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/describe"]; NSDictionary *payload = @{ @"image_urls": @[ @"https://example.com/input.png", ], @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/describe" let payload = {|{ "image_urls": [ "https://example.com/input.png" ], "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/describe'); final payload = { 'image_urls': [ 'https://example.com/input.png', ], 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/describe" payload <- list( image_urls = list( "https://example.com/input.png" ), speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 422, "message": "图片或提示词未通过内容审核,已自动退款", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 图片反推 prompt。通常 1–3s 同步返回,但**仍走平台标准异步流**——提交后照常轮询查询。 | 项目 | 内容 | | ------ | ----------------------------- | | action | `DESCRIBE` | | 计费 | `midjourney@describe[-speed]` | | 必填 | `image_urls`(1 张) | ## 参数 | 字段 | 类型 | 必填 | 默认 | 说明 | | ------------ | --------- | -- | ------- | ---------------------------- | | `image_urls` | string\[] | 是 | — | 单张图;数组形式,多传只取第一张;单图 ≤ 12 MiB | | `speed` | string | 否 | `relax` | `relax` / `fast` / `turbo` | | `metadata` | object | 否 | — | 自定义元数据 | ## 请求示例 ```json { "image_urls": ["https://example.com/input.png"], "speed": "fast" } ``` ## 响应 文字结果在查询结果的 `prompt` / `description`,**不返回 `image_urls` / `grid_image_url`**。反推为 4 段带编号建议,用 `\n` 分隔、数字 emoji `1️⃣2️⃣3️⃣4️⃣` 前缀: ```json { "id": "task_xxx", "status": "SUCCESS", "action": "DESCRIBE", "mode": "DESCRIBE", "prompt": "1️⃣ a serene mountain lake at sunrise --ar 3:2\n2️⃣ mountain landscape with reflections --v 6.1\n3️⃣ panoramic view of alpine lake --ar 16:9\n4️⃣ dawn light over still water --s 250", "description": "1️⃣ a serene mountain lake at sunrise --ar 3:2\n..." } ``` ## 注意 * describe 为独立处理通道,不占用普通生图的并发额度。 * 通常 1–3s 同步返回,但仍需轮询 `GET /v1/tasks/{task_id}`(或 `GET /v1/midjourney/{task_id}`)拿结果。 * 缺图返回 `400`;单图超 12 MiB 返回 `400`。 ### Edits(图片编辑) (#mj-edits) # Edits(图片编辑) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 基于已有图 + prompt 改写整张图。适合背景替换、风格迁移、内容修改 ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/edits \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", "image_urls": [ "https://example.com/product.png" ], "version": "8.1", "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/edits" payload = { "prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", "image_urls": [ "https://example.com/product.png" ], "version": "8.1", "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/edits"; const payload = { prompt: "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", image_urls: [ "https://example.com/product.png" ], version: "8.1", speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/edits" payload := map[string]interface{}{ "prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", "image_urls": []string{ "https://example.com/product.png", }, "version": "8.1", "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/edits"; String payload = """ { "prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", "image_urls": [ "https://example.com/product.png" ], "version": "8.1", "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", "image_urls" => [ "https://example.com/product.png", ], "version" => "8.1", "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/edits") payload = { prompt: "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", image_urls: [ "https://example.com/product.png", ], version: "8.1", speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/edits")! let payload: [String: Any] = [ "prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", "image_urls": [ "https://example.com/product.png", ], "version": "8.1", "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/edits"; var payload = @"{ ""prompt"": ""replace the background with a modern kitchen, keep the product unchanged --ar 1:1"", ""image_urls"": [ ""https://example.com/product.png"" ], ""version"": ""8.1"", ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/edits"; const char *payload = "{" "\"prompt\":\"replace the background with a modern kitchen, keep the product unchanged --ar 1:1\"," "\"image_urls\":[\"https://example.com/product.png\"]," "\"version\":\"8.1\"," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/edits"]; NSDictionary *payload = @{ @"prompt": @"replace the background with a modern kitchen, keep the product unchanged --ar 1:1", @"image_urls": @[ @"https://example.com/product.png", ], @"version": @"8.1", @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/edits" let payload = {|{ "prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", "image_urls": [ "https://example.com/product.png" ], "version": "8.1", "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/edits'); final payload = { 'prompt': 'replace the background with a modern kitchen, keep the product unchanged --ar 1:1', 'image_urls': [ 'https://example.com/product.png', ], 'version': '8.1', 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/edits" payload <- list( prompt = "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", image_urls = list( "https://example.com/product.png" ), version = "8.1", speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 422, "message": "图片或提示词未通过内容审核,已自动退款", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 基于已有图 + prompt **改写整张图**。适合背景替换、风格迁移、内容修改。 | 项目 | 内容 | | ------ | -------------------------- | | action | `EDITS` | | 计费 | `midjourney@edits[-speed]` | | 必填 | `prompt` + `image_urls` | ## 参数 | 字段 | 类型 | 必填 | 默认 | 说明 | | ------------ | --------- | -- | ------- | -------------------------- | | `prompt` | string | 是 | — | 编辑指令 | | `image_urls` | string\[] | 是 | — | 待编辑图;单图 ≤ 12 MiB | | `speed` | string | 否 | `relax` | `relax` / `fast` / `turbo` | | `metadata` | object | 否 | — | 自定义元数据 | ### 结构化参数(可选) 同 [Imagine](#mj-imagine),可写在 body 里或 prompt 中(如 `--ar 16:9`),body 优先级高于 prompt,会拼到 prompt 末尾并覆盖同名手写 flag。 | 字段 | 类型 | 等价 MJ 参数 | 说明 | | ----------------- | ------ | ---------- | -------------------------------------------------------------------------- | | `size` | string | `--ar` | 宽高比,如 `"16:9"`, `"1:1"`, `"9:16"` | | `quality` | string | `--q` | 质量:`"0.25"`, `"0.5"`, `"1"`, `"2"` | | `style` | string | `--style` | 风格:`"raw"` 等 | | `version` | string | `--v` | 版本号。主版本会追加为 `--v `;与 `niji: true` 搭配 `"7"` / `"6"` 时会归一化为 Niji 版本 | | `seed` | int | `--seed` | 随机种子 | | `negative_prompt` | string | `--no` | 负面提示词,如 `"ugly, blurry"` | | `stylize` | int | `--s` | 风格化强度 (0-1000) | | `chaos` | int | `--c` | 混乱度 (0-100) | | `weird` | int | `--w` | 怪异度 (0-3000) | | `tile` | bool | `--tile` | 平铺模式 | | `niji` | bool | `--niji` | Niji 开关。推荐传 `niji: true` + `version: "7"` / `"6"` | | `iw` | float | `--iw` | 图片权重 (0-3),垫图时使用 | | `cw` | int | `--cw` | 角色权重 (0-100) | | `sw` | int | `--sw` | 风格权重 (0-1000) | | `cref` | string | `--cref` | 角色参考图 URL | | `sref` | string | `--sref` | 风格参考图 URL | | `dref` | string | `--dref` | 深度参考图 URL | | `dw` | float | `--dw` | 深度权重 (0-100) | | `repeat` | int | `--repeat` | 重复生成次数 (2-40) | | `raw` | bool | `--raw` | 原始风格 (v5.1+ 支持) | | `draft` | bool | `--draft` | 草图模式 (v7+ 支持) | | `hd` | bool | `--hd` | HD 高清 (仅 v8.1 / v8.2,未传 version 时后端自动补 `--v 8.1`) | | `stop` | int | `--stop` | 提前停止 (10-100,仅 v5-6.1 / niji 5-6) | | `extra` | string | 任意 `--xxx` | 逃生口,原样追加到 prompt 末尾 | ## 请求示例 ```json { "prompt": "replace the background with a modern kitchen, keep the product unchanged --ar 1:1", "image_urls": ["https://example.com/product.png"], "version": "8.1", "speed": "fast" } ``` ## 响应 提交返回 `task_id`,SUCCESS 后含编辑结果 `image_urls`(可能 1–4 张)+ `grid_image_url`。 ## 注意 * 与 imagine 垫图的区别:edits 重在"改写整张图",imagine + 垫图重在"参考风格"。 * 缺 `prompt` 或 `image_urls` 返回 `400`;单图超 12 MiB 返回 `400`。 ### Upscale(放大选图) (#mj-upscale) # Upscale(放大选图) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 对 Imagine 四宫格选取 U1–U4 中的一张得到单图,本地合成、通常瞬时返回 ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/upscale \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 1, "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/upscale" payload = { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 1, "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/upscale"; const payload = { task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK", index: 1, speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/upscale" payload := map[string]interface{}{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 1, "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/upscale"; String payload = """ { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 1, "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQVZAPBW13W63DQNQZT7FCQK", "index" => 1, "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/upscale") payload = { task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK", index: 1, speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/upscale")! let payload: [String: Any] = [ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 1, "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/upscale"; var payload = @"{ ""task_id"": ""task_01KQVZAPBW13W63DQNQZT7FCQK"", ""index"": 1, ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/upscale"; const char *payload = "{" "\"task_id\":\"task_01KQVZAPBW13W63DQNQZT7FCQK\"," "\"index\":1," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/upscale"]; NSDictionary *payload = @{ @"task_id": @"task_01KQVZAPBW13W63DQNQZT7FCQK", @"index": @1, @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/upscale" let payload = {|{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 1, "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/upscale'); final payload = { 'task_id': 'task_01KQVZAPBW13W63DQNQZT7FCQK', 'index': 1, 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/upscale" payload <- list( task_id = "task_01KQVZAPBW13W63DQNQZT7FCQK", index = 1, speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 对父任务四宫格(`grid_image_url`)选取 U1–U4 中的一张,得到单图。通过**从已有 4 张图里截取**实现,本地合成、通常瞬时返回。 | 项目 | 内容 | | ------ | --------------------------------------------- | | action | `UPSCALE` | | 计费 | `midjourney@upscale[-version][-speed]` | | 必填 | `task_id` + `index`,或 `task_id` + `custom_id` | | 可选 | `speed`、`metadata` | ## 参数 | 字段 | 类型 | 说明 | | ----------- | ------ | ---------------------------------------------------- | | `task_id` | string | 父任务 ID(须为 imagine / variation / reroll 等 SUCCESS 任务) | | `index` | int | 选第几张(U1–U4),范围 `1`–`4`;与 `custom_id` 二选一 | | `custom_id` | string | 直接传对应操作的按钮 ID;与 `index` 二选一,传了它就不按 `index` 匹配 | | `speed` | string | `relax` / `fast` / `turbo`(本地合成,实际无影响) | | `metadata` | object | 自定义元数据 | ## 请求示例 按 `index` 选图: ```json { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 1, "speed": "fast" } ``` 直接传按钮: ```json { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "custom_id": "MJ::JOB::upsample::1::xxxx" } ``` ## 响应 提交返回新 `task_id`,**通常毫秒级即 SUCCESS**。SUCCESS 后 `image_urls` 只有 1 个元素(单图),`buttons` 含可继续的操作(zoom / inpaint / pan / variation 等)。 ## 注意 * 父任务必须是 SUCCESS 状态,否则返回 `400`(`task is not in SUCCESS state`)。 * `index` 必须 `1`–`4`,越界返回 `400`;`custom_id` 与 `index` 二选一,都传时 `custom_id` 优先。 * 真正消耗资源的是 imagine 阶段,upscale 只是从已有图里挑,几乎不会失败。 * upscale 后的单图可继续用 Zoom / Inpaint / Variation。 ## HD upscale(高清放大,输出 2x 单图) 普通 upscale 是**本地合成**——从父任务已有的 4 张图里截取其中一张,瞬时返回。如果后续要对单图做 zoom / inpaint 等精细操作,建议改用 **HD upscale**:执行真实放大,输出 **2x 高清单图**,约 60–120s 完成,产出的单图能更稳定地支持后续 zoom / inpaint。 HD upscale 通过 `custom_id` 指定放大命令,不同 imagine 版本对应不同命令: | customId 命令 | 适用版本 | | ------------------------- | --------------------- | | `upsample_v5_2x` | v5 imagine | | `upsample_v5_4x` | v5 imagine | | `upsample_v6_2x_subtle` | v6 / v6.1 imagine | | `upsample_v6_2x_creative` | v6 / v6.1 imagine | | `upsample_v7_2x_subtle` | **v7 / v8.1 imagine** | | `upsample_v7_2x_creative` | v7 / v8.1 imagine | ### HD upscale 示例 ```json { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "custom_id": "MJ::JOB::upsample_v7_2x_subtle::1::xxxx" } ``` 完成后得到一张真正的 2x 高清单图任务,可继续对它做 zoom / inpaint。 ### 与普通 upscale 对比 | 维度 | 普通 upscale | HD upscale | | -- | -------------------------- | ------------------ | | 实现 | 本地合成(截取) | 真实放大处理 | | 耗时 | 毫秒级 | 约 60–120s | | 输出 | 4 张里取第 N 张 | **2x 高清单图** | | 后续 | zoom / inpaint / variation | zoom / inpaint 更稳定 | ### ⚠️ pan 仍不可用 即使是 HD upscale 产出的高清单图,**pan 操作仍会被拒**(返回"无效生图请求")——这是 Midjourney 对 pan 操作本身的限制,与放大方式无关。详见 [Pan](#mj-pan)。 ### Variation(生成变体) (#mj-variation) # Variation(生成变体) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 对 Imagine 四宫格的某一张做弱变体(varySubtle,等价 V1–V4) ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/variation \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 3, "speed": "turbo" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/variation" payload = { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 3, "speed": "turbo" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/variation"; const payload = { task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK", index: 3, speed: "turbo" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/variation" payload := map[string]interface{}{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 3, "speed": "turbo", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/variation"; String payload = """ { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 3, "speed": "turbo" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQVZAPBW13W63DQNQZT7FCQK", "index" => 3, "speed" => "turbo", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/variation") payload = { task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK", index: 3, speed: "turbo", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/variation")! let payload: [String: Any] = [ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 3, "speed": "turbo", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/variation"; var payload = @"{ ""task_id"": ""task_01KQVZAPBW13W63DQNQZT7FCQK"", ""index"": 3, ""speed"": ""turbo"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/variation"; const char *payload = "{" "\"task_id\":\"task_01KQVZAPBW13W63DQNQZT7FCQK\"," "\"index\":3," "\"speed\":\"turbo\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/variation"]; NSDictionary *payload = @{ @"task_id": @"task_01KQVZAPBW13W63DQNQZT7FCQK", @"index": @3, @"speed": @"turbo", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/variation" let payload = {|{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 3, "speed": "turbo" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/variation'); final payload = { 'task_id': 'task_01KQVZAPBW13W63DQNQZT7FCQK', 'index': 3, 'speed': 'turbo', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/variation" payload <- list( task_id = "task_01KQVZAPBW13W63DQNQZT7FCQK", index = 3, speed = "turbo" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 对 imagine 四宫格里的某一张做**弱变体**(varySubtle,等价 V1–V4)。强变体见 [High Variation](#mj-high-variation)。 | 项目 | 内容 | | ------ | --------------------------------------------- | | action | `VARIATION` | | 计费 | `midjourney@variation[-speed]` | | 必填 | `task_id` + `index`,或 `task_id` + `custom_id` | | 可选 | `speed`、`metadata` | ## 参数 | 字段 | 说明 | | ----------- | -------------------------------------- | | `task_id` | 本平台返回的原任务 ID(须为 SUCCESS) | | `index` | `1`–`4`,对应 `V1`–`V4`;与 `custom_id` 二选一 | | `custom_id` | 直接指定对应操作的按钮 ID,传了它就不按 `index` 自动匹配 | | `speed` | `relax` / `fast` / `turbo` | | `metadata` | 自定义元数据 | ## 请求示例 ```json { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "index": 3, "speed": "turbo" } ``` ## 响应 提交返回新的本地 `task_id`,轮询 `GET /v1/tasks/{task_id}`,SUCCESS 后含变体的新四宫格 `grid_image_url` + 4 张 `image_urls`: ```json { "id": "task_xxx", "status": "SUCCESS", "action": "VARIATION", "grid_image_url": "...", "image_urls": ["...", "...", "...", "..."] } ``` 来源任务的 `version` / `niji` 会自动继承(影响计费 fallback);如需区分速度价格,可配置 `midjourney@variation-fast` / `midjourney@variation-turbo`。 ## 注意 * 父任务必须是 SUCCESS 状态,否则返回 `400`(`task is not in SUCCESS state`)。 * `index` 必须 `1`–`4`;`custom_id` 与 `index` 二选一。 * 默认走 `varySubtle`(弱变体);强变体用 [High Variation](#mj-high-variation);[Low Variation](#mj-low-variation) 是同 action 不同计费 key,行为相同。 ### High Variation(大幅变体) (#mj-high-variation) # High Variation(大幅变体) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 对已 upscale 的单图做强变体(varyStrong,对应 Vary (Strong)) ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/high-variation \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/high-variation" payload = { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/high-variation"; const payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", index: 1, speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/high-variation" payload := map[string]interface{}{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/high-variation"; String payload = """ { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index" => 1, "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/high-variation") payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", index: 1, speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/high-variation")! let payload: [String: Any] = [ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/high-variation"; var payload = @"{ ""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"", ""index"": 1, ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/high-variation"; const char *payload = "{" "\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\"," "\"index\":1," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/high-variation"]; NSDictionary *payload = @{ @"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", @"index": @1, @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/high-variation" let payload = {|{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/high-variation'); final payload = { 'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R', 'index': 1, 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/high-variation" payload <- list( task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", index = 1, speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 对已 upscale 的单图做**强变体**(varyStrong,对应 Vary (Strong),变化幅度大、偏离原图更多)。弱变体见 [Variation](#mj-variation)。 | 项目 | 内容 | | ------ | --------------------------------------------- | | action | `HIGH_VARIATION` | | 计费 | `midjourney@high_variation[-speed]` | | 必填 | `task_id` + `index`,或 `task_id` + `custom_id` | | 可选 | `speed`、`metadata` | ## 参数 | 字段 | 说明 | | ----------- | ------------------------------------------ | | `task_id` | 本平台返回的任务 ID(通常为 Upscale 后的单图任务) | | `index` | `1`–`4`;未传 `custom_id` 时必填,按钮匹配不使用 `index` | | `custom_id` | 直接指定对应操作的按钮 ID;传入后不按 `index` 自动匹配 | | `speed` | `relax` / `fast` / `turbo` | | `metadata` | 可选,自定义元数据 | ## 自动匹配 优先匹配 `Vary (Strong)`,失败回退 `Make Variations`。 ## 请求示例 ```json { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" } ``` ## 注意 * 通常先对四宫格调用 `upscale`,再拿 upscale 产生的新 `task_id` 调用本接口。 * 当前实现中未传 `custom_id` 时仍要求 `index`,虽然按钮匹配本身不使用 index。 * 来源任务的版本 metadata 会自动继承;如需区分速度价格,可配置 `midjourney@high_variation-fast` / `midjourney@high_variation-turbo`。 ## 返回 提交成功返回新的本地 `task_id`,请轮询 `GET /v1/tasks/{task_id}` 查询结果。 ### Low Variation(微调变体) (#mj-low-variation) # Low Variation(微调变体) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 对已 upscale 的单图做弱变体(varySubtle,与 Variation 行为一致,仅计费 key 不同) ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/low-variation \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/low-variation" payload = { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/low-variation"; const payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", index: 1, speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/low-variation" payload := map[string]interface{}{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/low-variation"; String payload = """ { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index" => 1, "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/low-variation") payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", index: 1, speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/low-variation")! let payload: [String: Any] = [ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/low-variation"; var payload = @"{ ""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"", ""index"": 1, ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/low-variation"; const char *payload = "{" "\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\"," "\"index\":1," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/low-variation"]; NSDictionary *payload = @{ @"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", @"index": @1, @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/low-variation" let payload = {|{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/low-variation'); final payload = { 'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R', 'index': 1, 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/low-variation" payload <- list( task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", index = 1, speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 对已 upscale 的单图做**弱变体**(varySubtle,与 Variation 行为完全一致)。独立 endpoint 主要用于命名一致性(与 [High Variation](#mj-high-variation) 对偶)和价格独立配置;新接入推荐直接用 [Variation](#mj-variation)。 | 项目 | 内容 | | ------ | --------------------------------------------- | | action | `LOW_VARIATION` | | 计费 | `midjourney@low_variation[-speed]` | | 必填 | `task_id` + `index`,或 `task_id` + `custom_id` | | 可选 | `speed`、`metadata` | ## 参数 | 字段 | 说明 | | ----------- | ------------------------------------------ | | `task_id` | 本平台返回的任务 ID(通常为 Upscale 后的单图任务) | | `index` | `1`–`4`;未传 `custom_id` 时必填,按钮匹配不使用 `index` | | `custom_id` | 直接指定对应操作的按钮 ID;传入后不按 `index` 自动匹配 | | `speed` | `relax` / `fast` / `turbo` | | `metadata` | 可选,自定义元数据 | ## 自动匹配 优先匹配 `Vary (Subtle)`,失败回退 `Make Variations`。 ## 请求示例 ```json { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "index": 1, "speed": "fast" } ``` ## 注意 * 通常先对四宫格调用 `upscale`,再拿 upscale 产生的新 `task_id` 调用本接口。 * 当前实现中未传 `custom_id` 时仍要求 `index`,虽然按钮匹配本身不使用 index。 * 来源任务的版本 metadata 会自动继承;如需区分速度价格,可配置 `midjourney@low_variation-fast` / `midjourney@low_variation-turbo`。 ## 返回 提交成功返回新的本地 `task_id`,请轮询 `GET /v1/tasks/{task_id}` 查询结果。 ### Reroll(重新生成) (#mj-reroll) # Reroll(重新生成) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 基于父任务 prompt 重新抽 4 张图(等价 🔄 重抽按钮),整网格重抽无需 index ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/reroll \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/reroll" payload = { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/reroll"; const payload = { task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK", speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/reroll" payload := map[string]interface{}{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/reroll"; String payload = """ { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQVZAPBW13W63DQNQZT7FCQK", "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/reroll") payload = { task_id: "task_01KQVZAPBW13W63DQNQZT7FCQK", speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/reroll")! let payload: [String: Any] = [ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/reroll"; var payload = @"{ ""task_id"": ""task_01KQVZAPBW13W63DQNQZT7FCQK"", ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/reroll"; const char *payload = "{" "\"task_id\":\"task_01KQVZAPBW13W63DQNQZT7FCQK\"," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/reroll"]; NSDictionary *payload = @{ @"task_id": @"task_01KQVZAPBW13W63DQNQZT7FCQK", @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/reroll" let payload = {|{ "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/reroll'); final payload = { 'task_id': 'task_01KQVZAPBW13W63DQNQZT7FCQK', 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/reroll" payload <- list( task_id = "task_01KQVZAPBW13W63DQNQZT7FCQK", speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 基于父任务的 prompt 重新抽 4 张图(等价 🔄 重抽按钮)。整个网格重抽,**无需 `index`**。 | 项目 | 内容 | | ------ | ----------------------------------- | | action | `REROLL` | | 计费 | `midjourney@reroll[-speed]` | | 必填 | `task_id`,或 `task_id` + `custom_id` | | 可选 | `speed`、`metadata` | ## 参数 | 字段 | 说明 | | ----------- | -------------------------- | | `task_id` | 本平台返回的原任务 ID | | `custom_id` | 可选,直接指定 reroll 对应操作的按钮 ID | | `speed` | `relax` / `fast` / `turbo` | | `metadata` | 可选,自定义元数据 | ## 自动匹配 服务端会从原任务 `buttons` 中匹配包含 `::reroll::` 的按钮,或匹配 reroll emoji。 ## 请求示例 ```json { "task_id": "task_01KQVZAPBW13W63DQNQZT7FCQK", "speed": "fast" } ``` ## 错误响应 | HTTP | code | description | | ----- | ---- | ---------------------------------- | | `400` | 4 | `task_id is required for reroll` | | `400` | 4 | `task ... is not in SUCCESS state` | | `404` | 3 | `task ... not found` | | `502` | 9 | 服务拒绝 | ## 返回 提交成功返回新的本地 `task_id`,请轮询 `GET /v1/tasks/{task_id}`,SUCCESS 后是**同 prompt 的全新四宫格**。 来源任务的 prompt / version / niji / 结构化参数会自动继承(种子可能不同,因此结果不同);如需区分速度价格,可配置 `midjourney@reroll-fast` / `midjourney@reroll-turbo`。 ## 注意 * 只能 reroll imagine 或自身 reroll 产生的网格任务;**不能 reroll 已做过 upscale / variation / pan 等二次操作的任务**。 * 父任务必须是 SUCCESS 状态。 ### Zoom(缩放扩展) (#mj-zoom) # Zoom(缩放扩展) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 对已 upscale 的单图执行 Zoom Out 扩图,原图保留向外补背景(Outpaint / CustomZoom) ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/zoom \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "zoom_ratio": 1.5, "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/zoom" payload = { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "zoom_ratio": 1.5, "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/zoom"; const payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", zoom_ratio: 1.5, speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/zoom" payload := map[string]interface{}{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "zoom_ratio": 1.5, "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/zoom"; String payload = """ { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "zoom_ratio": 1.5, "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "zoom_ratio" => 1.5, "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/zoom") payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", zoom_ratio: 1.5, speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/zoom")! let payload: [String: Any] = [ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "zoom_ratio": 1.5, "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/zoom"; var payload = @"{ ""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"", ""zoom_ratio"": 1.5, ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/zoom"; const char *payload = "{" "\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\"," "\"zoom_ratio\":1.5," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/zoom"]; NSDictionary *payload = @{ @"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", @"zoom_ratio": @1.5, @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/zoom" let payload = {|{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "zoom_ratio": 1.5, "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/zoom'); final payload = { 'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R', 'zoom_ratio': 1.5, 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/zoom" payload <- list( task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", zoom_ratio = 1.5, speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 对已 upscale 的单图执行 Zoom Out(扩图缩放):原图保留,向外补充更多背景。`zoom_ratio < 2` 走 Outpaint(1.5×),`≥ 2` 或未传走 CustomZoom(2×),两者均直接出图。 | 项目 | 内容 | | ------ | --------------------------------------- | | action | `ZOOM` | | 计费 | `midjourney@zoom[-speed]` | | 必填 | `task_id`,或 `task_id` + `custom_id` | | 可选 | `zoom_ratio`、`index`、`speed`、`metadata` | ## 参数 | 字段 | 说明 | | ------------ | ---------------------------------- | | `task_id` | 本平台返回的任务 ID(须为 Upscale 后的单图任务) | | `custom_id` | 可选,直接指定 Zoom 对应操作的按钮 ID | | `index` | 可选,选父任务第几张(`1`–`4`,默认 `1`);单图通常不用动 | | `zoom_ratio` | 可选,决定自动匹配的 Zoom Out 档位(见下表) | | `speed` | `relax` / `fast` / `turbo` | | `metadata` | 可选 | ## 自动匹配 | `zoom_ratio` | 匹配按钮 | | ------------ | --------------- | | 小于 `2` | `Zoom Out 1.5x` | | 未传或 `>= 2` | `Zoom Out 2x` | ## 请求示例 ```json { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "zoom_ratio": 1.5, "speed": "fast" } ``` ## 注意 * **父任务必须是已 upscale 的单图**且为 SUCCESS;传四宫格会返回 `This action requires an upscaled task...`,需先调用 `upscale`。 * Outpaint / CustomZoom 均直接出图,无需 mask,**不进 MODAL**(只有 Inpaint 走 MODAL)。 * 来源任务的版本 metadata 会自动继承;如需区分速度价格,可配置 `midjourney@zoom-fast` / `midjourney@zoom-turbo`。 ## 返回 提交成功返回新的本地 `task_id`,请轮询 `GET /v1/tasks/{task_id}` 查询结果。 ### Pan(平移扩展) (#mj-pan) # Pan(平移扩展) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 对已 upscale 的单图向指定方向接图扩展,可连续 pan 拼全景(仅 v6/v6.1/v7/v8.1/v8.2/niji6) ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/pan \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "direction": "right", "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/pan" payload = { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "direction": "right", "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/pan"; const payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", direction: "right", speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/pan" payload := map[string]interface{}{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "direction": "right", "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/pan"; String payload = """ { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "direction": "right", "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "direction" => "right", "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/pan") payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", direction: "right", speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/pan")! let payload: [String: Any] = [ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "direction": "right", "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/pan"; var payload = @"{ ""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"", ""direction"": ""right"", ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/pan"; const char *payload = "{" "\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\"," "\"direction\":\"right\"," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/pan"]; NSDictionary *payload = @{ @"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", @"direction": @"right", @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/pan" let payload = {|{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "direction": "right", "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/pan'); final payload = { 'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R', 'direction': 'right', 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/pan" payload <- list( task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", direction = "right", speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 对已 upscale 的单图向指定方向"接图"扩展:原图保留在边缘,新方向区域补全。可连续 pan(向右后继续向右),适合拼全景图。 | 项目 | 内容 | | ------ | ------------------------------------------------- | | action | `PAN` | | 计费 | `midjourney@pan[-speed]` | | 必填 | `task_id` + `direction`,或 `task_id` + `custom_id` | | 可选 | `index`、`speed`、`metadata` | ## 参数 | 字段 | 说明 | | ----------- | ------------------------------------------ | | `task_id` | 本平台返回的任务 ID(须为 Upscale 后的单图任务) | | `direction` | `left` / `right` / `up` / `down` | | `custom_id` | 可选,直接指定 Pan 对应操作的按钮 ID;指定后不必再传 `direction` | | `index` | 可选(`1`–`4`),backend 自动转 0-based | | `speed` | `relax` / `fast` / `turbo` | | `metadata` | 可选 | 自动匹配按 `customId` 子串:`pan_left`、`pan_right`、`pan_up`、`pan_down`。 ## 请求示例 ```json { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "direction": "right", "speed": "fast" } ``` ## 注意 * **版本限制**:pan 仅适用于 **v6 / v6.1 / v7 / v8.1 / v8.2 / niji 6**;v5.2 及更早会 FAILURE(MJ engine 跑不出)。 * 如果返回 `This action requires an upscaled task...`,说明传入的是四宫格任务,需要先调用 `upscale`。 * `direction` 必须是 `left` / `right` / `up` / `down` 之一。 * 来源任务的版本 metadata 会自动继承;如需区分速度价格,可配置 `midjourney@pan-fast` / `midjourney@pan-turbo`。 ## 返回 提交成功返回新的本地 `task_id`,请轮询 `GET /v1/tasks/{task_id}` 查询结果。 ### Inpaint(局部重绘) (#mj-inpaint) # Inpaint(局部重绘) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 局部重绘入口(等价 Vary (Region)),提交后进 MODAL,需再调 modal 上传 mask + prompt ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/inpaint \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/inpaint" payload = { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/inpaint"; const payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/inpaint" payload := map[string]interface{}{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/inpaint"; String payload = """ { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/inpaint") payload = { task_id: "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/inpaint")! let payload: [String: Any] = [ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/inpaint"; var payload = @"{ ""task_id"": ""task_01KQW0D3WJ2QYJP9E3H7GZ4D2R"", ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/inpaint"; const char *payload = "{" "\"task_id\":\"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R\"," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/inpaint"]; NSDictionary *payload = @{ @"task_id": @"task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/inpaint" let payload = {|{ "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/inpaint'); final payload = { 'task_id': 'task_01KQW0D3WJ2QYJP9E3H7GZ4D2R', 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/inpaint" payload <- list( task_id = "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 422, "message": "图片或提示词未通过内容审核,已自动退款", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 局部重绘入口(等价 `Vary (Region)`)。**提交后任务进 `MODAL` 状态**,需再调 [modal](#mj-modal) 上传 mask + prompt 才能完成。 | 项目 | 内容 | | ------ | -------------------------------------- | | action | `INPAINT` | | 计费 | `midjourney@inpaint[-version][-speed]` | | 必填 | `task_id`,或 `task_id` + `custom_id` | | 可选 | `index`、`speed`、`metadata` | ## 参数 | 字段 | 说明 | | ----------- | ---------------------------------- | | `task_id` | 原任务 ID(一般为 Upscale 后的单图任务) | | `custom_id` | 可选,直接指定 `Vary (Region)` 对应操作的按钮 ID | | `index` | 可选,选父任务第几张(`1`–`4`,默认 `1`);单图通常不用动 | | `speed` | `relax` / `fast` / `turbo` | | `metadata` | 可选 | ## 自动匹配 服务端从原任务 `buttons` 中匹配 `Vary (Region)`。 ## 请求示例 ```json { "task_id": "task_01KQW0D3WJ2QYJP9E3H7GZ4D2R", "speed": "fast" } ``` ## 后续流程 提交成功后返回 `status: "modal"`——这是**合法非终态**,不是错误。请用 [modal](#mj-modal) 接口继续:其中 **`task_id` 为上一步 inpaint 返回的本地任务 ID**,并提交 **`prompt`** 以及可选 **`mask_url`**。 ```json { "task_id": "task_03_inpaint...", "status": "modal", "model": "midjourney" } ``` ## 注意 * **父任务必须是 SUCCESS 的 upscale 单图**;四宫格直接 inpaint 会报错,需先 `upscale`。 * 进入 MODAL 后 **30 分钟内必须调 modal 补参**,否则后台自动 CANCEL + 退款。 * 来源任务的版本 metadata 会自动继承;如需区分速度价格,可配置 `midjourney@inpaint-fast` / `midjourney@inpaint-turbo`。 ### Modal(提交补充参数) (#mj-modal) # Modal(提交补充参数) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 给 MODAL 状态的局部重绘任务补充 mask + prompt 完成重绘 ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/modal \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C", "prompt": "replace the selected area with a red leather sofa", "mask_url": "https://example.com/mask.png", "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/modal" payload = { "task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C", "prompt": "replace the selected area with a red leather sofa", "mask_url": "https://example.com/mask.png", "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/modal"; const payload = { task_id: "task_01KQW1N9T6E3AHW6QZFDEK8M5C", prompt: "replace the selected area with a red leather sofa", mask_url: "https://example.com/mask.png", speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/modal" payload := map[string]interface{}{ "task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C", "prompt": "replace the selected area with a red leather sofa", "mask_url": "https://example.com/mask.png", "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/modal"; String payload = """ { "task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C", "prompt": "replace the selected area with a red leather sofa", "mask_url": "https://example.com/mask.png", "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_01KQW1N9T6E3AHW6QZFDEK8M5C", "prompt" => "replace the selected area with a red leather sofa", "mask_url" => "https://example.com/mask.png", "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/modal") payload = { task_id: "task_01KQW1N9T6E3AHW6QZFDEK8M5C", prompt: "replace the selected area with a red leather sofa", mask_url: "https://example.com/mask.png", speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/modal")! let payload: [String: Any] = [ "task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C", "prompt": "replace the selected area with a red leather sofa", "mask_url": "https://example.com/mask.png", "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/modal"; var payload = @"{ ""task_id"": ""task_01KQW1N9T6E3AHW6QZFDEK8M5C"", ""prompt"": ""replace the selected area with a red leather sofa"", ""mask_url"": ""https://example.com/mask.png"", ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/modal"; const char *payload = "{" "\"task_id\":\"task_01KQW1N9T6E3AHW6QZFDEK8M5C\"," "\"prompt\":\"replace the selected area with a red leather sofa\"," "\"mask_url\":\"https://example.com/mask.png\"," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/modal"]; NSDictionary *payload = @{ @"task_id": @"task_01KQW1N9T6E3AHW6QZFDEK8M5C", @"prompt": @"replace the selected area with a red leather sofa", @"mask_url": @"https://example.com/mask.png", @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/modal" let payload = {|{ "task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C", "prompt": "replace the selected area with a red leather sofa", "mask_url": "https://example.com/mask.png", "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/modal'); final payload = { 'task_id': 'task_01KQW1N9T6E3AHW6QZFDEK8M5C', 'prompt': 'replace the selected area with a red leather sofa', 'mask_url': 'https://example.com/mask.png', 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/modal" payload <- list( task_id = "task_01KQW1N9T6E3AHW6QZFDEK8M5C", prompt = "replace the selected area with a red leather sofa", mask_url = "https://example.com/mask.png", speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 422, "message": "图片或提示词未通过内容审核,已自动退款", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 给 MODAL 状态的局部重绘任务补充 mask + prompt 完成重绘。系统按 `mask_url` 是否存在自动判断模式:**有 `mask_url` → 局部重绘;无 → 外扩**。 | 项目 | 内容 | | ------ | -------------------------------------- | | action | `MODAL` | | 计费 | `midjourney@modal[-speed]` | | 必填 | `task_id` | | 可选 | `prompt`、`mask_url`、`speed`、`metadata` | ## 参数 | 字段 | 说明 | | ---------- | -------------------------------------------------- | | `task_id` | [inpaint](#mj-inpaint) 步骤返回的本地任务 ID(须为 MODAL 状态) | | `prompt` | 局部重绘提示词;留空则继承父任务 prompt | | `mask_url` | 遮罩图 URL 或 base64;**局部重绘时必填**。透明区域=要重绘的位置,白色区域=保留原图 | | `speed` | `relax` / `fast` / `turbo` | | `metadata` | 可选 | ## mask 要求 | 项 | 建议 | | ---- | ----------------------------------------- | | 格式 | PNG 透明背景(也支持 `data:image/png;base64,...`) | | 分辨率 | 建议与父图同分辨率(系统也会自动 resize) | | 透明区域 | 要重绘的位置;白色区域保留原图 | | 大小 | 单图 ≤ 12 MiB | | URL | 必须公网可达(私网会被 SSRF 拦截) | ## 请求示例 ```json { "task_id": "task_01KQW1N9T6E3AHW6QZFDEK8M5C", "prompt": "replace the selected area with a red leather sofa", "mask_url": "https://example.com/mask.png", "speed": "fast" } ``` ## 返回 `task_id` 不变(同一任务),status 从 `MODAL` → `SUBMITTED`。轮询 `GET /v1/tasks/{task_id}`,SUCCESS 后 `image_urls` 含 4 张局部重绘候选。计费在本接口 SUCCESS 时结算,与 inpaint 阶段不重复扣费。 如需区分速度价格,可配置 `midjourney@modal-fast` / `midjourney@modal-turbo`。 ### Video(图生视频) (#mj-video) # Video(图生视频) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > Midjourney 图生视频(i2v),固定 FAST,不支持 t2v,时长约 5 秒 ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/video \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "prompt": "the cat slowly turns its head to the camera", "image_urls": [ "https://example.com/cat.png" ], "motion": "high", "batch_size": 4 }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/video" payload = { "prompt": "the cat slowly turns its head to the camera", "image_urls": [ "https://example.com/cat.png" ], "motion": "high", "batch_size": 4 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/video"; const payload = { prompt: "the cat slowly turns its head to the camera", image_urls: [ "https://example.com/cat.png" ], motion: "high", batch_size: 4 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/video" payload := map[string]interface{}{ "prompt": "the cat slowly turns its head to the camera", "image_urls": []string{ "https://example.com/cat.png", }, "motion": "high", "batch_size": 4, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/video"; String payload = """ { "prompt": "the cat slowly turns its head to the camera", "image_urls": [ "https://example.com/cat.png" ], "motion": "high", "batch_size": 4 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "the cat slowly turns its head to the camera", "image_urls" => [ "https://example.com/cat.png", ], "motion" => "high", "batch_size" => 4, ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/video") payload = { prompt: "the cat slowly turns its head to the camera", image_urls: [ "https://example.com/cat.png", ], motion: "high", batch_size: 4, } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/video")! let payload: [String: Any] = [ "prompt": "the cat slowly turns its head to the camera", "image_urls": [ "https://example.com/cat.png", ], "motion": "high", "batch_size": 4, ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/video"; var payload = @"{ ""prompt"": ""the cat slowly turns its head to the camera"", ""image_urls"": [ ""https://example.com/cat.png"" ], ""motion"": ""high"", ""batch_size"": 4 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/video"; const char *payload = "{" "\"prompt\":\"the cat slowly turns its head to the camera\"," "\"image_urls\":[\"https://example.com/cat.png\"]," "\"motion\":\"high\"," "\"batch_size\":4" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/video"]; NSDictionary *payload = @{ @"prompt": @"the cat slowly turns its head to the camera", @"image_urls": @[ @"https://example.com/cat.png", ], @"motion": @"high", @"batch_size": @4, }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/video" let payload = {|{ "prompt": "the cat slowly turns its head to the camera", "image_urls": [ "https://example.com/cat.png" ], "motion": "high", "batch_size": 4 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/video'); final payload = { 'prompt': 'the cat slowly turns its head to the camera', 'image_urls': [ 'https://example.com/cat.png', ], 'motion': 'high', 'batch_size': 4, }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/video" payload <- list( prompt = "the cat slowly turns its head to the camera", image_urls = list( "https://example.com/cat.png" ), motion = "high", batch_size = 4 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 422, "message": "图片或提示词未通过内容审核,已自动退款", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 图生视频(i2v)。**固定 FAST 模式,无 speed 维度**;**不支持纯文生视频(t2v)**,必须给首帧。时长固定约 5 秒。 | 项目 | 内容 | | ------ | ----------------------------------------------------------------------- | | action | `VIDEO` | | 计费 | `midjourney@video` / `midjourney@video-720p`,**实扣 = 单价 × `batch_size`** | | 必填 | `image_urls`(首帧)或 `task_id`(复用 imagine SUCCESS) | ## 参数 | 字段 | 类型 | 必填 | 默认 | 说明 | | -------------- | --------- | -- | ----------------- | ------------------------------------------------ | | `prompt` | string | 否 | (继承父任务) | 视频提示词;为空时必须有 `task_id` | | `image_urls` | string\[] | △ | — | 起始帧(1 张,≤ 12 MiB);与 `task_id` 二选一 | | `task_id` | string | △ | — | 复用已有 imagine SUCCESS;与 `image_urls` 二选一 | | `index` | int | 否 | — | 从 imagine 4 张图选哪张作首帧(`0`–`3`,配合 `task_id`) | | `video_type` | string | 否 | `vid_1.1_i2v_480` | 分辨率档(见下表);含 `720` → 走 `@video-720p` 计费 | | `animate_mode` | string | 否 | `manual` | `manual` / `auto`;`auto` 必须给 `task_id` + `index` | | `motion` | string | 否 | `high` | `low` / `high`;运动幅度,**不影响计费** | | `batch_size` | int | 否 | `1` | 必须 `1` / `2` / `4`,其他值视为 1;**计费 × N** | | `end_url` | string | 否 | — | 结束帧;设了后 `video_type` 自动升级为 `start_end_*` | ## video\_type 合法值 | 值 | 分辨率 | 模式 | 命中价格 | | --------------------------- | ---- | ---------------------- | ----------------------- | | `vid_1.1_i2v_480` | 480p | 基础 i2v(默认) | `midjourney@video` | | `vid_1.1_i2v_720` | 720p | 基础 i2v | `midjourney@video-720p` | | `vid_1.1_i2v_start_end_480` | 480p | 起止帧(传 `end_url` 时自动升级) | `midjourney@video` | | `vid_1.1_i2v_start_end_720` | 720p | 起止帧(传 `end_url` 时自动升级) | `midjourney@video-720p` | > 不接受带 `extend` 的取值;仅支持上表列出的 `video_type`。 ## 请求示例 简单 i2v(自带首帧,batch 4): ```json { "prompt": "the cat slowly turns its head to the camera", "image_urls": ["https://example.com/cat.png"], "motion": "high", "batch_size": 4 } ``` 起止帧 transition(传 `end_url` 自动升级为 `start_end`): ```json { "prompt": "transition smoothly from sunrise to sunset", "image_urls": ["https://example.com/sunrise.jpg"], "end_url": "https://example.com/sunset.jpg", "video_type": "vid_1.1_i2v_720" } ``` ## 响应 提交返回 `task_id`,轮询 `GET /v1/tasks/{task_id}`。SUCCESS 后含 `video_url`(首个)+ `video_urls`(`length === batch_size`,batch=1 时也是 1 个元素): ```json { "id": "task_xxx", "status": "SUCCESS", "action": "VIDEO", "mode": "FAST", "video_url": "https://r2.example.com/video-0.mp4", "video_urls": [ "https://r2.example.com/video-0.mp4", "https://r2.example.com/video-1.mp4" ] } ``` ## 注意 * **不支持纯文生视频(t2v)**:必须给 `image_urls` 或 `task_id`,否则返回 `400`;两者不能同时传。 * **固定 FAST 模式**,无 speed 维度(计费表里 `@video-fast` / `@video-turbo` 永不命中)。 * `batch_size` 严格校验为 `1` / `2` / `4`;**batch=4 实扣 4 倍,预算敏感时用 batch=1**。 * `animate_mode=auto` 必须同时给 `task_id` + `index`。 * 首帧 / 结束帧单图 ≤ 12 MiB。 ### Remix(重塑) (#mj-remix) # Remix(重塑,仅 v8.1 / v8.2) > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > v8 操作面板的重塑(reshape),把父图重新生成可改 prompt,分强 / 弱两档 ```bash curl --request POST \ --url https://api.seedance.nz/v1/midjourney/generations/remix-strong \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "task_id": "task_", "index": 1, "speed": "fast" }' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/generations/remix-strong" payload = { "task_id": "task_", "index": 1, "speed": "fast" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/generations/remix-strong"; const payload = { task_id: "task_", index: 1, speed: "fast" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/generations/remix-strong" payload := map[string]interface{}{ "task_id": "task_", "index": 1, "speed": "fast", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/generations/remix-strong"; String payload = """ { "task_id": "task_", "index": 1, "speed": "fast" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "task_", "index" => 1, "speed" => "fast", ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/generations/remix-strong") payload = { task_id: "task_", index: 1, speed: "fast", } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/generations/remix-strong")! let payload: [String: Any] = [ "task_id": "task_", "index": 1, "speed": "fast", ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/generations/remix-strong"; var payload = @"{ ""task_id"": ""task_"", ""index"": 1, ""speed"": ""fast"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/generations/remix-strong"; const char *payload = "{" "\"task_id\":\"task_\"," "\"index\":1," "\"speed\":\"fast\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/generations/remix-strong"]; NSDictionary *payload = @{ @"task_id": @"task_", @"index": @1, @"speed": @"fast", }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/generations/remix-strong" let payload = {|{ "task_id": "task_", "index": 1, "speed": "fast" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/generations/remix-strong'); final payload = { 'task_id': 'task_', 'index': 1, 'speed': 'fast', }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/midjourney/generations/remix-strong" payload <- list( task_id = "task_", index = 1, speed = "fast" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KV52C0TEJSYZMCG0NCS4YWKK" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 422, "message": "图片或提示词未通过内容审核,已自动退款", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` v8 操作面板新增的"重塑"(reshape):把父图重新生成,可改 prompt。**仅 v8.1 / v8.2 父任务可用**;v7 / v6 父图请改用 [Variation](#mj-variation) / [High Variation](#mj-high-variation)。 ``` POST /v1/midjourney/generations/remix-strong POST /v1/midjourney/generations/remix-subtle ``` > v8 操作面板移除了 U1-U4 / zoom / outpaint / inpaint。对应替代:变化 → Variation / High Variation;重塑 → 本接口;重新生成 → Reroll。 | 项目 | 内容 | | ------ | --------------------------------------------------------------------- | | action | `REMIX_STRONG` / `REMIX_SUBTLE` | | 计费 | `midjourney@remix_strong[-speed]` / `midjourney@remix_subtle[-speed]` | | 必填 | `task_id` + `index` | ## 参数 | 字段 | 类型 | 必填 | 默认 | 说明 | | --------- | ------ | -- | ------- | ------------------------------------ | | `task_id` | string | 是 | — | 父任务(**v8.1 / v8.2 imagine SUCCESS**) | | `index` | int | 是 | — | 选父图第几张做重塑(`1`–`4`) | | `prompt` | string | 否 | (继承父任务) | 重塑用的新 prompt;空则用父图 prompt | | `speed` | string | 否 | `relax` | `relax` / `fast` / `turbo` | ## 力度对比 | 接口 | op | 改动幅度 | 类比 | | --------------- | ------------- | ---------------- | ---------------------- | | `/remix-strong` | `remixStrong` | 大幅改动,构图 / 风格都可能变 | 类似 High Variation(强变体) | | `/remix-subtle` | `remixSubtle` | 小幅改动,保持主体 / 色调 | 类似 Variation(弱变体) | ## 请求示例 强烈重塑: ```json { "task_id": "task_", "index": 1, "speed": "fast" } ``` 自定义 prompt 透传生效,可改风格 / 添加细节。 ## 响应 提交返回新的本地 `task_id`,轮询 `GET /v1/tasks/{task_id}`,SUCCESS 后含 4 张重塑图。 ## 注意 * **仅 v8.1 / v8.2 父图可用**;父任务非 v8 系列返回 `400`。 * v7 / v6 父图请用 Variation / High Variation / Low Variation。 ### 任务查询 (#mj-query) # 任务查询 > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > 查询 Midjourney 任务状态与结果。统一任务接口 /v1/tasks/{task_id} 与 MJ 风格接口 /v1/midjourney/{task_id} ```bash curl --request GET \ --url https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK \ --header 'Authorization: Bearer ' ``` ```python import requests url = "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK" headers = { "Authorization": "Bearer " } response = requests.get(url, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"; const headers = { "Authorization": "Bearer " }; fetch(url, { method: "GET", headers: headers }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK" req, _ := http.NewRequest("GET", url, nil) req.Header.Set("Authorization", "Bearer ") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .GET() .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php " ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["Authorization"] = "Bearer " response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK")! var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var response = await client.GetAsync(url); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"GET"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK" let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " in let response = Client.get ~headers (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK'); final response = await http.get( url, headers: { 'Authorization': 'Bearer ', }, ); print(response.body); } ``` ```r library(httr) url <- "https://api.seedance.nz/v1/midjourney/task_01KV52C0TEJSYZMCG0NCS4YWKK" response <- GET( url, add_headers( Authorization = "Bearer " ) ) cat(content(response, "text")) ``` ```json { "id": "task_01KV52C0TEJSYZMCG0NCS4YWKK", "status": "SUCCESS", "action": "IMAGINE", "progress": "100%", "grid_image_url": "https://cdn.example.com/mj_xxxx.png", "image_urls": [ "https://cdn.example.com/mj_xxxx_0.png", "https://cdn.example.com/mj_xxxx_1.png", "https://cdn.example.com/mj_xxxx_2.png", "https://cdn.example.com/mj_xxxx_3.png" ], "buttons": [ {"customId": "MJ::JOB::upsample::1::abc123def456", "label": "U1"}, {"customId": "MJ::JOB::variation::1::abc123def456", "label": "V1"} ], "prompt": "a beautiful sunset over mountains" } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 404, "message": "任务不存在", "type": "not_found_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` 推荐业务侧轮询统一任务接口: ``` GET /v1/tasks/{task_id} ``` 统一任务状态为 `pending` / `processing` / `completed` / `failed`,成功结果位于 `result.images[].url`。 需要读取 `buttons[].customId` 做二次操作时,使用 MJ 风格查询: ``` GET /v1/midjourney/{task_id} ``` ## 任务状态流转 ``` SUBMITTED → IN_PROGRESS → SUCCESS → FAILURE → MODAL(需补充参数,见局部重绘) ``` ## 响应示例 ```json { "id": "task_01JWXXXX", "status": "SUCCESS", "action": "IMAGINE", "progress": "100%", "grid_image_url": "https://cdn.example.com/mj_xxxx.png", "image_urls": [ "https://cdn.example.com/mj_xxxx_0.png", "https://cdn.example.com/mj_xxxx_1.png", "https://cdn.example.com/mj_xxxx_2.png", "https://cdn.example.com/mj_xxxx_3.png" ], "buttons": [ {"customId": "MJ::JOB::upsample::1::abc123def456", "label": "U1"}, {"customId": "MJ::JOB::variation::1::abc123def456", "label": "V1"} ], "prompt": "a beautiful sunset over mountains" } ``` > `grid_image_url` 是四宫格合成大图,`image_urls` 是裁剪后的 4 张单图 URL 数组。 **字段差异提醒** * `/v1/tasks/{task_id}` 返回统一 `pending` / `processing` / `completed` / `failed` 状态。 * `/v1/midjourney/{task_id}` 返回 MJ 风格字段,如 `grid_image_url`、`image_urls`、`buttons`。 **关于 `buttons`:** 大部分二次操作可传 `index`、`direction` 或 `zoom_ratio`,系统会自动匹配对应 `customId`;如自动匹配失败,可直接传 `custom_id`。 ## 状态字段总览 | status | 含义 | 终态 | | ------------- | ---------------------------------------- | -- | | `NOT_START` | 已建行,系统未确认(瞬时态) | 否 | | `SUBMITTED` | 系统接受,排队中 | 否 | | `IN_PROGRESS` | 系统处理中 | 否 | | `MODAL` | 等待调 `/modal` 补参(见局部重绘) | 否 | | `SUCCESS` | 完成 | ✓ | | `FAILURE` | 失败 → 自动退款(`quota` 归 0,`fail_reason` 含原因) | ✓ | ## 查询说明 * 查询接口**不单独计费**,但建议合理控制频率(推荐 3–5s 轮询一次)。 * 普通用户只能查自己的任务;查他人任务返回 `403`。 * 任务默认保留 **3 天**,过后查询返回 `404`,但**生成的图片 / 视频 URL 仍可访问**。 ## 高级:使用 custom\_id 直接操作 读取 `buttons[].customId` 后,可直接传给二次操作接口的 `custom_id` 字段,绕过自动匹配: ```json { "task_id": "task_01JWXXXX", "custom_id": "MJ::JOB::upsample::1::abc123def456" } ``` ### 最佳实践 (#mj-best-practices) # 最佳实践 > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > Midjourney 接入的轮询模式、Prompt 设计、垫图、错误重试策略、并发与排错建议 整合常见问题、性能优化、错误处理的最佳实践,**接入前建议通读**。 ## 任务提交与轮询 提交接口都是异步任务:提交后返回 `task_id`,再周期性查询 `GET /v1/midjourney/{task_id}` 拿状态,直到 `SUCCESS` / `FAILURE`。 ```python import time, httpx def wait_task(task_id, timeout=300): deadline = time.time() + timeout while time.time() < deadline: resp = httpx.get(f"{HOST}/v1/midjourney/{task_id}", headers={"Authorization": f"Bearer {API_KEY}"}).json() if resp["status"] in ("SUCCESS", "FAILURE"): return resp if resp["status"] == "MODAL": raise RuntimeError(f"task {task_id} 需要调 /modal 补参完成") time.sleep(3) raise TimeoutError(task_id) ``` * **轮询节奏**:建议 3–5s 一次,更高频无意义且浪费配额。 * **不要在 web 请求里同步阻塞**等任务完成 —— 提交后立即返回 `task_id`,让前端异步轮询。 ## Prompt 设计 **好的 prompt:** ```text a serene mountain lake at sunrise, photorealistic, soft golden light, mist rising from water, snow-capped peaks in distance --ar 16:9 --v 8.1 --s 100 ``` * **主体在前**:先主体,再描述场景,最后修饰词。 * **结构化参数显式**:用 `--ar` / `--v` / `--s`(或对应 body 字段)比依赖默认值更可控。 * **避免歧义词**:`photorealistic` 比 `realistic` 更明确。 **避免:** 过于抽象("make it good")、主体散乱(多个并列对象不分主次)、给词加引号(会被当字面值)。 **Niji 动漫:** 传 `niji: true` + `version: "7"`,平台归一化为 `--niji 7`,计费走 `midjourney@imagine-niji7`。 ## 垫图最佳实践 | 来源 | 推荐做法 | 注意 | | ---------- | ------------------------- | ------------------------- | | 用户上传 | 先存自己的 OSS / CDN,提交时传该 URL | 不要直接传 base64(浪费带宽) | | 公开 URL | 直接传 | 注意 SSRF(须公网可达)与 12 MiB 限制 | | 第三方 / 其他产物 | 先转存到自己的 OSS | 第三方 URL 可能过期 | * **压缩到 \< 5 MiB**:平台上限 12 MiB,但小图传输 / 处理都更快。 * 格式 PNG / JPG / WebP 均可,推荐高质量 JPG。 * 分辨率 1024–2048 px 已足够,更高浪费。 * 垫图权重 `iw`(0–3,默认 1):>1 更贴原图,\<1 更自由。 ## 错误处理与重试策略 | code | 含义 | 重试策略 | | --------------------- | -------------------- | --------------------------- | | `1` / `200` | 成功 | ✅ | | `4` VALIDATION\_ERROR | 参数错 | ❌ 不要重试,修正参数 | | `3` NOT\_FOUND | 无可用实例 / task\_id 不存在 | 实例不可用可稍后重试;task\_id 不存在不要重试 | | `9` FAILURE | 服务拒绝 / 内部错误 | ⏳ 可重试,指数退避(1s, 4s, 16s) | | `21` MODAL | 非终态 | ✅ 继续调 `/modal` | | `24` BANNED\_PROMPT | 敏感词 | ❌ 不要重试,改 prompt;**已自动退款** | | `429` | 限流 | ⏳ 指数退避 + jitter | | `5xx` / 网络错 | 服务端 / 网络 | ⏳ 指数退避,网络错可立即重试 1 次 | ```python import time, random, httpx def submit_with_retry(payload, max_attempts=5): for attempt in range(max_attempts): try: r = httpx.post(f"{HOST}/v1/midjourney/generations/imagine", json=payload, headers={"Authorization": f"Bearer {API_KEY}"}, timeout=30) data = r.json() if r.status_code == 200 and data["code"] in (1, 200): return data if data["code"] in (4, 24): raise ValueError(data["description"]) # 不可重试 if data["code"] == 3 and "task" in data["description"]: raise ValueError(data["description"]) # task_id 不存在 # 其余(9 / 429 / 5xx)可重试 except httpx.RequestError: pass time.sleep((4 ** attempt) + random.uniform(0, 1)) # 1s / 4s / 16s ... raise RuntimeError(f"达到最大重试次数 {max_attempts}") ``` ## 二次操作流程 ```python # imagine → 轮询 → upscale imagine_id = submit({"prompt": "a cat"})["data"][0]["task_id"] result = wait_task(imagine_id) # grid_image_url + 4 张 image_urls + buttons upscale_id = submit_to("/upscale", {"task_id": imagine_id, "index": 2})["data"][0]["task_id"] final = wait_task(upscale_id) # upscale 本地合成,1–2s single_image = final["image_urls"][0] ``` 局部重绘(inpaint → modal 两步): ```python imagine_id = submit({"prompt": "a portrait"})["data"][0]["task_id"]; wait_task(imagine_id) upscale_id = submit_to("/upscale", {"task_id": imagine_id, "index": 1})["data"][0]["task_id"]; wait_task(upscale_id) inpaint_id = submit_to("/inpaint", {"task_id": upscale_id})["data"][0]["task_id"] # status=modal # 前端画 mask(透明=重绘区),上传到自己的 OSS 拿 mask_url final = submit_to("/modal", { "task_id": inpaint_id, "prompt": "replace the eyes with cybernetic blue eyes", "mask_url": "https://your-oss.com/mask.png" }) wait_task(final["data"][0]["task_id"]) ``` > ⚠️ inpaint 进 MODAL 后 **30 分钟内**必须调 `/modal`,否则后台自动 CANCEL + 退款。 ## video 计费控制 * 单段:`batch_size: 1` → 扣 1 × `midjourney@video` * 批量 4 段:`batch_size: 4` → 扣 4 × `midjourney@video` * 高清单段:`video_type: "vid_1.1_i2v_720"` + `batch_size: 1` → 扣 1 × `midjourney@video-720p` **建议**:出片只要 1 段就用 `batch_size=1`,批量比稿才用 4,不要默认开 4(成本翻 N 倍)。 ## 并发与吞吐 ```python import asyncio sem = asyncio.Semaphore(10) # 客户端最多 10 个并发提交 async def submit_one(prompt): async with sem: return await submit({"prompt": prompt}) ``` * 平台对每分钟提交数有上限,超出返回 `429`,需退避重试。 * 实际生成并发由系统容量决定,超出会排队;任务长时间停在 `SUBMITTED` 通常是排队中。 * 轮询务必带 `sleep`,不要无 sleep 死循环。 ## 监控建议 | 指标 | 参考阈值 | 含义 | | ------------------ | ------ | ------------------- | | 任务 SUCCESS 率(近 1h) | > 95% | 偏低说明服务 / 网络异常 | | 平均完成耗时 | \< 90s | 偏高说明排队 | | MODAL 停留任务数 | 接近 0 | 偏多说明客户端没调 `/modal` | | `code=24` 比例 | \< 5% | 偏高说明 prompt 频繁触发敏感词 | ## 排错清单 | 现象 | 排查方向 | | ------------------ | ------------------------------------ | | 任务长时间 `SUBMITTED` | 系统排队中,稍后再查 | | 任务长时间 `NOT_START` | 平台稍后会自动超时退款,无需手动处理 | | 任务 `MODAL` 超 30 分钟 | 客户端没调 `/modal`,已被自动 CANCEL + 退款 | | `prompt` 字段为空 | describe 任务的文字结果在 `description` 字段 | | `image_urls` 少一张 | 内容审核拦了部分图,看 `fail_reason` | | 计费超预期 | 看 `quota` 字段;video 记得 × `batch_size` | ### 完整工作流示例 (#mj-workflow) # 完整工作流示例 > **计费说明**:按路径模型名计费(如 `midjourney-imagine`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询推荐 `GET /v1/midjourney/tasks/{task_id}`(兼容 `GET /v1/midjourney/{task_id}`)。 > imagine → upscale → inpaint → video 等端到端 curl 走查,附 bash / Python / TS 客户端封装 把多接口串起来的端到端示例。所有命令把 `$KEY` 换成你的 API token,`$HOST` 换成实际平台域名。 ```bash export KEY="sk-your-api-key" export HOST="https://api.seedance.nz" ``` ## 流程 A:基础文生图(imagine → upscale) ```bash # 1. imagine 出 4 张图 curl -sS -X POST "$HOST/v1/midjourney/generations/imagine" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{ "prompt": "a futuristic city at sunset, photorealistic, cinematic lighting", "version": "8.1", "size": "16:9", "speed": "fast", "stylize": 250 }' # → {"code":200,"data":[{"task_id":"task_01KQVZAPBW...","status":"submitted"}]} # 2. 轮询查询直到 SUCCESS(约 30–60s) curl -sS "$HOST/v1/midjourney/task_01KQVZAPBW..." -H "Authorization: Bearer $KEY" # → SUCCESS,含 grid_image_url + 4 张 image_urls + buttons(U1-U4 / V1-V4 / 🔄) # 3. upscale 选第 2 张(本地合成,毫秒级 SUCCESS) curl -sS -X POST "$HOST/v1/midjourney/generations/upscale" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"task_id": "task_01KQVZAPBW...", "index": 2}' # → 查询拿单图 image_urls[0] ``` ## 流程 B:垫图 → 强变体 → 放大 ```bash # 1. 垫图 imagine curl -sS -X POST "$HOST/v1/midjourney/generations/imagine" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{ "prompt": "turn this product into a luxury studio photo", "image_urls": ["https://your-cdn.example.com/product.png"], "iw": 1.5, "size": "1:1" }' # 2. 对结果做强变体 curl -sS -X POST "$HOST/v1/midjourney/generations/high-variation" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"task_id": "task_01XXX...", "index": 1, "speed": "fast"}' # 3. 对变体的某张 upscale curl -sS -X POST "$HOST/v1/midjourney/generations/upscale" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"task_id": "task_02_variant...", "index": 3}' ``` ## 流程 C:局部重绘(inpaint + modal 两步) 前提:先 imagine + upscale 拿到单图任务(见流程 A)。 ```bash # 1. 提交 inpaint → 进 MODAL curl -sS -X POST "$HOST/v1/midjourney/generations/inpaint" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"task_id": "task_02_upscaled..."}' # → {"data":[{"task_id":"task_03_inpaint...","status":"modal"}]} # 注意 status=modal,任务等你补 mask;30 分钟超时自动 CANCEL + 退款 # 2. 前端画 mask(透明=重绘区,白色=保留),上传到自己的 OSS 拿 mask_url(须公网可达) # 3. 提交 modal 完成 curl -sS -X POST "$HOST/v1/midjourney/generations/modal" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{ "task_id": "task_03_inpaint...", "prompt": "replace the selected area with a red leather sofa", "mask_url": "https://your-oss.example.com/mask-abc.png" }' # → 同 task_id,status 转 submitted;4. 轮询 60–90s 后 SUCCESS,含 4 张局部重绘候选 ``` ## 流程 D:扩图(Zoom Out) ```bash # 直接出图,无需 mask(Outpaint / CustomZoom 都不进 MODAL) curl -sS -X POST "$HOST/v1/midjourney/generations/zoom" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{"task_id": "task_02_upscaled...", "zoom_ratio": 1.5, "speed": "fast"}' ``` ## 流程 E:图生视频(i2v) ```bash # 720p 高清 + batch=4(4 倍计费) curl -sS -X POST "$HOST/v1/midjourney/generations/video" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{ "prompt": "city traffic at night, neon reflections, slow camera dolly", "image_urls": ["https://your-cdn.example.com/city.jpg"], "video_type": "vid_1.1_i2v_720", "batch_size": 4 }' # 实扣 = midjourney@video-720p × 4 # 起止帧 transition(end_url 自动升级为 start_end) curl -sS -X POST "$HOST/v1/midjourney/generations/video" \ -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \ -d '{ "prompt": "transition smoothly from sunrise to sunset", "image_urls": ["https://your-cdn.example.com/sunrise.jpg"], "end_url": "https://your-cdn.example.com/sunset.jpg", "video_type": "vid_1.1_i2v_720" }' ``` ## 通用工具:Python 客户端封装 ```python import time import httpx API_KEY = "sk-..." HOST = "https://api.seedance.nz" class MjClient: def __init__(self): self.client = httpx.Client( base_url=HOST, headers={"Authorization": f"Bearer {API_KEY}"}, timeout=30, ) def imagine(self, prompt, **params): r = self.client.post("/v1/midjourney/generations/imagine", json={"prompt": prompt, **params}) return r.json()["data"][0]["task_id"] def upscale(self, task_id, index): r = self.client.post("/v1/midjourney/generations/upscale", json={"task_id": task_id, "index": index}) return r.json()["data"][0]["task_id"] def query(self, task_id): return self.client.get(f"/v1/midjourney/{task_id}").json() def wait(self, task_id, timeout=180): deadline = time.time() + timeout while time.time() < deadline: t = self.query(task_id) if t["status"] in ("SUCCESS", "FAILURE"): return t if t["status"] == "MODAL": raise RuntimeError(f"task {task_id} 需要调 /modal") time.sleep(3) raise TimeoutError(task_id) mj = MjClient() imagine_id = mj.imagine("a cat", version="8.1", speed="fast", size="16:9") mj.wait(imagine_id) upscale_id = mj.upscale(imagine_id, 2) print(mj.wait(upscale_id)["image_urls"][0]) ``` ## 通用工具:TypeScript 封装 ```ts const API_KEY = "sk-..."; const HOST = "https://api.seedance.nz"; async function mj(path: string, body: any) { const r = await fetch(`${HOST}${path}`, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify(body), }); return r.json(); } async function query(id: string) { const r = await fetch(`${HOST}/v1/midjourney/${id}`, { headers: { "Authorization": `Bearer ${API_KEY}` }, }); return r.json(); } async function waitTask(id: string, timeoutMs = 180_000) { const deadline = Date.now() + timeoutMs; while (Date.now() < deadline) { const t = await query(id); if (t.status === "SUCCESS" || t.status === "FAILURE") return t; if (t.status === "MODAL") throw new Error(`需要调 /modal: ${id}`); await new Promise((r) => setTimeout(r, 3000)); } throw new Error(`超时: ${id}`); } const r = await mj("/v1/midjourney/generations/imagine", { prompt: "a cat", version: "8.1", speed: "fast" }); const result = await waitTask(r.data[0].task_id); console.log(result.image_urls); ``` ## 状态机 ```text submit → NOT_START(0%) → SUBMITTED(5-30%) → IN_PROGRESS(~99%) → SUCCESS(100%) ↘ FAILURE(100%) → 自动退款 inpaint / CustomZoom → MODAL(15%) ──POST /modal {mask_url, prompt}──▶ SUBMITTED → ... └ 30min 超时 → CANCEL + 退款 ``` ## SUNO ### 创建自定义模型 (#suno-create-model) # 创建自定义模型 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 使用 6–24 条参考音频创建可用于 Suno V6 生成的自定义模型 创建模型是异步任务。提交后先取得训练 `task_id`,轮询任务完成后再从 `data.result.model_id` 读取自定义模型 ID。 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/create-model \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "suno", "name": "温暖民谣模型", "audio_urls": [ "https://example.com/ref-01.mp3", "https://example.com/ref-02.mp3", "https://example.com/ref-03.wav", "https://example.com/ref-04.m4a", "https://example.com/ref-05.mp3", "https://example.com/ref-06.mp3" ] }' ``` ```python import requests response = requests.post( "https://api.seedance.nz/v1/music/generations/create-model", headers={"Authorization": "Bearer "}, json={ "model": "suno", "name": "温暖民谣模型", "audio_urls": [ "https://example.com/ref-01.mp3", "https://example.com/ref-02.mp3", "https://example.com/ref-03.wav", "https://example.com/ref-04.m4a", "https://example.com/ref-05.mp3", "https://example.com/ref-06.mp3", ], }, ) print(response.json()) ``` ```javascript const response = await fetch("https://api.seedance.nz/v1/music/generations/create-model", { method: "POST", headers: { "Authorization": "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ model: "suno", name: "温暖民谣模型", audio_urls: [ "https://example.com/ref-01.mp3", "https://example.com/ref-02.mp3", "https://example.com/ref-03.wav", "https://example.com/ref-04.m4a", "https://example.com/ref-05.mp3", "https://example.com/ref-06.mp3" ] }) }); console.log(await response.json()); ``` ## Authorizations Bearer Token。登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key。 ## Body 固定使用 `suno`。 自定义模型名称。去掉首尾空白后不能为空。 6–24 条公网可访问的 HTTP(S) 音频直链,建议使用 MP3、WAV 或 M4A。每条 URL 都应直接返回音频文件,不能是需要登录的网页。 无效素材可能导致整个创建任务失败。本地文件请先使用项目的上传能力获得公网 URL;不要传本地路径或 `blob:` URL。 ## Response 响应状态码。提交结果。读取 `data[0].task_id`,再通过 `GET /v1/music/tasks/{task_id}` 查询训练状态。 ```json { "code": 200, "data": [ {"status": "submitted", "task_id": "task_01M24YMN4EV04M84R5QYM77R1E"} ] } ``` ```json { "code": 200, "data": { "id": "task_01M24YMN4EV04M84R5QYM77R1E", "status": "completed", "progress": 100, "result": { "model_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "name": "温暖民谣模型" } } } ``` ## 使用创建的模型 完成后保存 `result.model_id`,后续在支持自定义模型的操作中作为 `custom_model_id` 使用,并省略 `version` 和 `persona_id`: ```json { "model": "suno", "custom_model_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "custom": true, "instrumental": false, "prompt": "[Verse]\n旧木吉他弹起新的旅程", "style": "acoustic folk, warm vocals", "max_mode": true, "audio_format": "mp3" } ``` 创建模型可能需要数分钟,最长约 20 分钟。自定义模型的实际可用时间可能变化,界面不应承诺固定的精确到期时间。创建模型与后续每次生成分别计费。 ### 上传音频翻唱 (#suno-upload-cover) # 上传音频并翻唱 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 上传公网音频 URL,并使用 Suno V6 生成翻唱版本 本接口直接使用公开音频 URL 生成翻唱,无需先调用 `uploadTask`。提交后返回 `task_id`,通过 `GET /v1/music/tasks/{task_id}` 查询结果。 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/upload-cover \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "suno", "version": "v6", "audio_url": "https://example.com/reference.mp3", "custom": true, "instrumental": true, "tags": "piano, ambient", "duration_s": 120, "variety": "normal", "audio_format": "m4a" }' ``` ```python import requests response = requests.post( "https://api.seedance.nz/v1/music/generations/upload-cover", headers={"Authorization": "Bearer "}, json={ "model": "suno", "version": "v6", "audio_url": "https://example.com/reference.mp3", "custom": True, "instrumental": True, "tags": "piano, ambient", "duration_s": 120, "audio_format": "m4a", }, ) print(response.json()) ``` ```javascript const response = await fetch("https://api.seedance.nz/v1/music/generations/upload-cover", { method: "POST", headers: { "Authorization": "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ model: "suno", version: "v6", audio_url: "https://example.com/reference.mp3", custom: true, instrumental: true, tags: "piano, ambient", duration_s: 120, audio_format: "m4a" }) }); console.log(await response.json()); ``` ## Authorizations Bearer Token。登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key。 ## Body 固定使用 `suno`。 公网可访问的 HTTP(S) 音频直链,建议原音频不超过 8 分钟。本地路径、`blob:` URL 和需要登录的页面链接不可用。 公共版本:`v6` / `v6-wild` / `v6-mini`。使用 `custom_model_id` 时省略。 创建模型任务返回的完整 UUID。与 `version`、`persona_id` 互斥。 建议显式发送。`false` 使用 `gpt_description`;`true` 使用歌词和风格字段。 是否生成纯音乐。`custom=true` 且本字段为 `false` 时,`prompt` 必填。 灵感描述,`custom=false` 时必填,不超过 3000 个字符。 自定义模式歌词,不超过 5000 个字符。 风格描述,不超过 1000 个字符。 标题,不超过 80 个字符。 不希望出现的风格。 风格权重,范围 0–1。 创意度权重,范围 0–1。 音频权重,范围 0–1。 是否对输入歌词进行二次创作。 人声性别:`Male` / `Female`。 Persona ID,与 `custom_model_id` 互斥。 目标生成时长,范围 10–360 秒,仅自定义模式可用。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。 是否启用 Max 模式。启用时要求自定义模式,并按普通售价的 2 倍计费。 输出格式:`mp3` / `m4a` / `wav`。 ## Response 响应状态码。提交结果,读取 `data[0].task_id` 并轮询任务查询接口。 ```json { "code": 200, "data": [ {"status": "submitted", "task_id": "task_01M24YMN4EV04M84R5QYM77R1E"} ] } ``` ### 上传音频续写 (#suno-upload-extend) # 上传音频并延伸 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 上传公网音频 URL,并从指定位置使用 Suno V6 延伸歌曲 本接口直接延伸公开音频 URL,无需先调用 `uploadTask`。接口固定使用自定义模式,不要发送 `custom`、`instrumental` 或 `gpt_description`。 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/upload-extend \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "suno", "version": "v6-mini", "audio_url": "https://example.com/reference.wav", "continue_at": 30, "prompt": "[Outro]\n下一段旅途,我们一起走", "tags": "acoustic pop", "duration_s": 60, "max_mode": true, "audio_format": "mp3" }' ``` ```python import requests response = requests.post( "https://api.seedance.nz/v1/music/generations/upload-extend", headers={"Authorization": "Bearer "}, json={ "model": "suno", "version": "v6-mini", "audio_url": "https://example.com/reference.wav", "continue_at": 30, "prompt": "[Outro]\n下一段旅途,我们一起走", "tags": "acoustic pop", "duration_s": 60, "max_mode": True, "audio_format": "mp3", }, ) print(response.json()) ``` ```javascript const response = await fetch("https://api.seedance.nz/v1/music/generations/upload-extend", { method: "POST", headers: { "Authorization": "Bearer ", "Content-Type": "application/json" }, body: JSON.stringify({ model: "suno", version: "v6-mini", audio_url: "https://example.com/reference.wav", continue_at: 30, prompt: "[Outro]\n下一段旅途,我们一起走", tags: "acoustic pop", duration_s: 60, max_mode: true, audio_format: "mp3" }) }); console.log(await response.json()); ``` ## Authorizations Bearer Token。登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key。 ## Body 固定使用 `suno`。公网可访问的 HTTP(S) 音频直链,建议不超过 8 分钟。本地路径与 `blob:` URL 不可用。 延伸起点,必须大于等于 1 秒,并严格小于源音频实际时长。 公共版本:`v6` / `v6-wild` / `v6-mini`。使用 `custom_model_id` 时省略。 创建模型任务返回的完整 UUID。与 `version`、`persona_id` 互斥。 延伸段歌词,不超过 5000 个字符;省略时按纯音乐延伸语义使用。 风格描述,不超过 1000 个字符。标题,不超过 80 个字符。不希望出现的风格。风格权重,范围 0–1。创意度权重,范围 0–1。音频权重,范围 0–1。是否对输入歌词进行二次创作。人声性别:`Male` / `Female`。Persona ID,与 `custom_model_id` 互斥。目标生成时长,范围 10–360 秒。实际成品时长以任务结果为准。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。 是否启用 Max 模式;启用后按普通售价的 2 倍计费。 输出格式:`mp3` / `m4a` / `wav`。## Response 响应状态码。提交结果,读取 `data[0].task_id` 并轮询任务查询接口。 ```json { "code": 200, "data": [ {"status": "submitted", "task_id": "task_01M24YMN4EV04M84R5QYM77R1E"} ] } ``` ### Suno 概览与任务查询 (#suno-overview) # Suno V6 通用约定与任务查询 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Suno V6 的版本选择、自定义模型、异步任务生命周期、源音轨引用和结果结构 所有 Suno 生成、编辑和工具接口都采用异步任务:提交操作后取得 `task_id`,再通过本页接口查询结果。 ## 认证 使用 Bearer Token 认证:`Authorization: Bearer <你的 API Key>`。 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key。 ## V6 版本与模型选择 公共模型只支持以下版本: * `v6` * `v6-wild` * `v6-mini` 主生成接口必须提供 `version`,或提供创建模型任务返回的 `custom_model_id`。支持版本的编辑操作省略 `version` 时默认使用 `v6`。公共 `version` 与 `custom_model_id` 不能同时发送。 `custom: true` 表示自定义歌词模式,`custom_model_id` 表示使用已训练的自定义模型,两者不是同一个概念。使用自定义歌词模式不会自动切换到自定义模型价格档。 ### 通用 V6 生成选项 仅在具体端点列出时发送以下字段: | 字段 | 说明 | | ------------------------- | -------------------------------------------------- | | `variety` | 风格变化程度:`off` / `normal` / `high` / `extra` / `max` | | `max_mode` | Max 模式,默认 `false`;支持时按普通售价的 2 倍计费 | | `audio_format` | 输出格式:`mp3` / `m4a` / `wav` | | `duration` / `duration_s` | 目标生成时长,10–360 秒整数,仅指定生成操作支持 | 不支持某字段的操作应完全省略该字段;不要向所有操作统一发送 `max_mode: false`。`variety` 与 Max 模式相互独立,选择 `variety: "max"` 不会自动开启 Max 计费。 ### 文本与权重限制 | 内容 | 字段 | 限制 | | ---- | --------------------------------------------- | ------------- | | 灵感描述 | `prompt`(主生成)/ `gpt_description`(操作接口) | 不超过 3000 个字符 | | 歌词 | `prompt`(自定义模式) | 不超过 5000 个字符 | | 风格 | `style`(主生成)/ `tags`(操作接口) | 不超过 1000 个字符 | | 标题 | `title` | 不超过 80 个字符 | | 权重 | `style_weight` / `weirdness` / `audio_weight` | 0–1;数值 `0` 有效 | 操作接口的新请求使用 `weirdness`;`weirdness_constraint` 是兼容别名。主生成仍使用 `weirdness_constraint`。文本长度按 Unicode 字符数计算。 ## 引用源音轨 基于已有作品的操作使用: * `task_id`:产出源音轨的 任务 ID。 * `audio_index`:源任务查询响应的 `data.result.music[]` 中的原始位置,从 1 开始,默认 `1`。 返回多少首就按实际数组展示,不要把结果数量固定为 2。即使页面调整了展示顺序,后续操作仍须使用音轨在原始结果中的索引。 新请求统一使用 `task_id + audio_index` 引用源音轨,不能用 `audio_id`、`music_id` 或 `audio_url` 替代。无法解析源任务或索引越界时会返回 `400`。 ## 提交响应 ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01M24YMN4EV04M84R5QYM77R1E" } ] } ``` 从 `data[0].task_id` 读取任务 ID。`submitted` 只表示任务已受理,不表示已有最终音频或其它产物。 ## 查询任务 `GET /v1/music/tasks/{task_id}` 可附加 `?language=zh` 获取适用的失败信息翻译。该参数不会改变歌曲或歌词语言。 提交接口返回的任务 ID。 建议首次等待约 3 秒,之后每 5–10 秒查询一次,直到 `data.status` 为 `completed` 或 `failed`。页面刷新后可继续使用同一个任务 ID 查询;不要因网络超时自动重发收费的 POST 请求。 ## 查询响应 响应状态码。 任务信息。 本平台任务 ID。 `pending` / `processing` / `completed` / `failed` / `unknown`。 任务进度,通常为 0–100。是否完成应以 `status` 为准。 创建时间,Unix 秒。 预计耗时(秒),仅供参考,并非倒计时承诺。 任务金额(美元)。 任务消耗的积分值,请直接使用接口返回值展示。 完成后的结果,结构随操作不同。 失败信息,常见字段为 `message` / `type` / `code` / `param`。 ```json { "code": 200, "data": { "id": "task_01M24YMN4EV04M84R5QYM77R1E", "status": "completed", "progress": 100, "created": 1789041600, "cost": 0.12, "credits_cost": 1.2, "result": { "music": [ { "audio_id": "example-track-id", "status": "complete", "title": "沿着灯光", "lyrics": "[Verse]\n晚风吹过熟悉街道", "tags": "pop, acoustic", "display_tags": "Pop, Acoustic", "negative_tags": "harsh vocals", "style_weight": 0.7, "weirdness_constraint": 0, "audio_weight": 0.4, "duration": 119.8, "audio_url": "https://example.com/result.mp3", "image_url": "https://example.com/cover.jpg", "image_large_url": "https://example.com/cover-large.jpg" } ] } } } ``` ```json { "code": 200, "data": { "id": "task_01M24YMN4EV04M84R5QYM77R1E", "status": "failed", "progress": 0, "cost": 0, "credits_cost": 0, "error": { "message": "任务失败原因", "type": "task_failed", "code": "task_failed", "param": "" } } } ``` ## 结果处理 * 音乐类结果通常位于 `data.result.music[]`,但下载、歌词、MIDI、Persona 和自定义模型等操作有各自的结果结构。 * `duration` 是实际时长,允许小数;输入目标时长不保证与成品完全相同。 * 权重返回值 `0` 是有效值,不能因为 JavaScript falsy 判断而隐藏。 * `audio_url` 不保证使用 `.mp3` 后缀,请按接口返回的实际 URL 播放或下载。 * `status="unknown"` 时保留任务 ID 并允许手动刷新,不要自动创建新任务。 `AbortController` 只能停止浏览器请求和轮询,不会取消服务器任务。当前接口没有取消已提交 Suno 任务的端点。 ### Generate music(文生曲) (#suno-generation) # 生成音乐 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 从提示词生成歌曲:`custom=false` 为灵感模式(`prompt` 作灵感提示词),`=true` 为自定义模式(`prompt` 作歌词)。 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 `custom` 决定文本字段是否生效:`custom=true`(自定义)时 `prompt` 作歌词,`title`、`style`、`negative_tags`、`auto_lyrics` 和 `persona_id` 生效;`custom=false`(灵感)时 `prompt` 作灵感描述,上述自定义字段被忽略。`style_weight`、`weirdness_constraint`、`audio_weight` 和 `vocal_gender` 在两种模式下都会校验并生效。 本端点的字段名与其他端点略有不同:使用 `style`,而不是 `tags`。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "custom": false, "version": "v6", "prompt": "深夜城市 lo-fi 钢琴配雨声" }' ``` ```bash curl -X POST https://api.seedance.nz/v1/music/generations \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "version": "v6", "custom": true, "instrumental": false, "prompt": "[Verse]\n雨夜霓虹灯下的街道", "title": "深夜驾驶", "style": "synthwave, female vocal, cinematic", "negative_tags": "metal, screaming", "auto_lyrics": false, "vocal_gender": "Female", "style_weight": 0.6, "weirdness_constraint": 0.3, "audio_weight": 0.5 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations" payload = { "model": "suno", "custom": False, "version": "v6", "prompt": "深夜城市 lo-fi 钢琴配雨声" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations"; const payload = { model: "suno", custom: false, version: "v6", prompt: "深夜城市 lo-fi 钢琴配雨声" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations" payload := map[string]interface{}{ "model": "suno", "custom": false, "version": "v6", "prompt": "深夜城市 lo-fi 钢琴配雨声", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations"; String payload = """ { "model": "suno", "custom": false, "version": "v6", "prompt": "深夜城市 lo-fi 钢琴配雨声" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "custom" => false, "version" => "v6", "prompt" => "深夜城市 lo-fi 钢琴配雨声" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations") payload = { model: "suno", custom: false, version: "v6", prompt: "深夜城市 lo-fi 钢琴配雨声" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations")! let payload: [String: Any] = [ "model": "suno", "custom": false, "version": "v6", "prompt": "深夜城市 lo-fi 钢琴配雨声" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations"; var payload = @"{ ""model"": ""suno"", ""custom"": false, ""version"": ""v6"", ""prompt"": ""深夜城市 lo-fi 钢琴配雨声"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations"; const char *payload = "{" "\"model\":\"suno\"," "\"custom\":false," "\"version\":\"v6\"," "\"prompt\":\"深夜城市 lo-fi 钢琴配雨声\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations"]; NSDictionary *payload = @{ @"model": @"suno", @"custom": @NO, @"version": @"v6", @"prompt": @"深夜城市 lo-fi 钢琴配雨声" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations" let payload = {|{ "model": "suno", "custom": false, "version": "v6", "prompt": "深夜城市 lo-fi 钢琴配雨声" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations'); final payload = { 'model': 'suno', 'custom': false, 'version': 'v6', 'prompt': '深夜城市 lo-fi 钢琴配雨声' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations" payload <- list( model = "suno", custom = FALSE, version = "v6", prompt = "深夜城市 lo-fi 钢琴配雨声" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 `false`=灵感模式;`true`=自定义模式(`prompt` 作歌词)。默认 `false`。 `true`=纯音乐、无人声。默认 `false`。 公共版本:`v6` / `v6-wild` / `v6-mini`。与 `custom_model_id` 至少提供一个;使用自定义模型时省略本字段。 创建自定义模型任务返回的完整 UUID。与 `version`、`persona_id` 互斥;提供本字段后按自定义模型价格档计费。 灵感提示词 / 歌词。**`custom=false` 时必填**且不超过 3000 个字符;`custom=true` 且 `instrumental=false` 时**必填**且不超过 5000 个字符;自定义纯音乐可省略。 标题(自定义模式),不超过 80 个字符。**`custom=false`(灵感模式)时忽略**。 风格标签(自定义模式),不超过 1000 个字符。**`custom=false`(灵感模式)时忽略**。 负向风格标签(不希望出现的风格)。**仅 `custom=true` 时生效**。 `true`=对输入歌词进行二次创作。**仅 `custom=true` 时生效**。 Persona 风格 ID。**仅 `custom=true` 时生效**,与 `custom_model_id` 互斥。 人声性别:`Male` / `Female`(也接受 `m` / `f` / `male` / `female`,后端自动归一)。**两种模式均生效**。 风格权重,`0.00`–`1.00`。两种模式下都会校验并生效。 创意度,`0.00`–`1.00`。两种模式下都会校验并生效。 音频权重,`0.00`–`1.00`。两种模式下都会校验并生效。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。可省略,没有固定默认值。 是否启用 Max 模式。启用时要求 `custom=true`,并按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。省略时由服务自动选择。 目标生成时长,范围 10–360 秒,仅 `custom=true` 时可用。实际成品时长以任务结果为准。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后在 `data.result.music[]` 取 `audio_url`(另有 `image_url` / `video_url` / `title` / `duration` 等)。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Generate lyrics(生成歌词) (#suno-lyrics) # 生成歌词 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 根据主题生成歌词文本。 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 本端点**无版本维度**:不要传 `version`,传了会被丢弃,也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/lyrics \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "prompt": "一首关于重逢的抒情歌" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/lyrics" payload = { "model": "suno", "prompt": "一首关于重逢的抒情歌" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/lyrics"; const payload = { model: "suno", prompt: "一首关于重逢的抒情歌" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/lyrics" payload := map[string]interface{}{ "model": "suno", "prompt": "一首关于重逢的抒情歌", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/lyrics"; String payload = """ { "model": "suno", "prompt": "一首关于重逢的抒情歌" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "prompt" => "一首关于重逢的抒情歌" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/lyrics") payload = { model: "suno", prompt: "一首关于重逢的抒情歌" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/lyrics")! let payload: [String: Any] = [ "model": "suno", "prompt": "一首关于重逢的抒情歌" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/lyrics"; var payload = @"{ ""model"": ""suno"", ""prompt"": ""一首关于重逢的抒情歌"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/lyrics"; const char *payload = "{" "\"model\":\"suno\"," "\"prompt\":\"一首关于重逢的抒情歌\\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/lyrics"]; NSDictionary *payload = @{ @"model": @"suno", @"prompt": @"一首关于重逢的抒情歌" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/lyrics" let payload = {|{ "model": "suno", "prompt": "一首关于重逢的抒情歌" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/lyrics'); final payload = { 'model': 'suno', 'prompt': '一首关于重逢的抒情歌' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/lyrics" payload <- list( model = "suno", prompt = "一首关于重逢的抒情歌" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 想生成什么歌词的描述,去掉首尾空白后不能为空。 歌词模型:`classic` / `remi`。不传时使用服务默认设置。 **获取结果**:提交后轮询 `GET /v1/music/tasks/{task_id}`。优先读取 `result.lyrics[]` 中的 `text`、`title` 和 `tags`;同时兼容 `result.text`、字符串形式的 `result.lyrics` 以及历史数组结构。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Extend(续写) (#suno-extend) # 续写延长 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 在已有歌曲的某个时间点之后续写延长。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 extend 的 `custom` 为可选参数,省略时默认 `true`。`custom=true` 时按 `prompt`(歌词)续写;只有显式传入 `custom=false` 时,才使用 `gpt_description`(灵感描述)引导续写方向。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/extend \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "continue_at": 120, "version": "v6", "prompt": "续写歌词…" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/extend" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "continue_at": 120, "version": "v6", "prompt": "续写歌词…" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/extend"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, continue_at: 120, version: "v6", prompt: "续写歌词…" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/extend" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "continue_at": 120, "version": "v6", "prompt": "续写歌词…", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/extend"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "continue_at": 120, "version": "v6", "prompt": "续写歌词…" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "continue_at" => 120, "version" => "v6", "prompt" => "续写歌词…" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/extend") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, continue_at: 120, version: "v6", prompt: "续写歌词…" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/extend")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "continue_at": 120, "version": "v6", "prompt": "续写歌词…" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/extend"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""continue_at"": 120, ""version"": ""v6"", ""prompt"": ""续写歌词…"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/extend"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"continue_at\":120," "\"version\":\"v6\"," "\"prompt\":\"续写歌词…\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/extend"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"continue_at": @120, @"version": @"v6", @"prompt": @"续写歌词…" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/extend" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "continue_at": 120, "version": "v6", "prompt": "续写歌词…" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/extend'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'continue_at': 120, 'version': 'v6', 'prompt': '续写歌词…' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/extend" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, continue_at = 120, version = "v6", prompt = "续写歌词…" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`;缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 从第几秒开始续写,必须大于等于 1 且小于源音轨实际时长。支持小数秒。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID。与 `version`、`persona_id` 互斥。 `true`=按 `prompt` 歌词续写;`false`=灵感续写。省略时默认 `true`。 续写歌词,`custom=true` 时生效。 灵感提示词,仅在显式传入 `custom=false` 时生效,用于引导续写方向。 标题。**仅 `custom=true` 时生效**。 风格标签。**仅 `custom=true` 时生效**。 排除的风格标签。**仅 `custom=true` 时生效**。 人声性别:`Male` / `Female`。**两种模式均生效**。 风格权重,`0.00`–`1.00`(超出范围提交期直接返回 `400`)。**仅 `custom=true` 时生效**。 创意度权重,`0.00`–`1.00`。兼容旧名 `weirdness_constraint`;新请求请使用 `weirdness`。 音频权重,`0.00`–`1.00`。**仅 `custom=true` 时生效**。 `true`=对输入歌词进行二次创作。**仅 `custom=true` 时生效**。 Persona 风格 ID。**仅 `custom=true` 时生效**,与 `custom_model_id` 互斥。 目标生成时长,范围 10–360 秒,仅 `custom=true` 时可用。实际时长以结果为准。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。可省略。 是否启用 Max 模式。启用时要求 `custom=true`,并按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后在 `data.result.music[]` 取延长后的 `audio_url`。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Upload audio(上传音频) (#suno-upload) # 上传音频 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 把一段公网音频导入,得到可供后续(翻唱 / 续写等)引用的音轨;完成后本任务 `task_id` 即可作源(`audio_index=1`)。 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 本端点只接收 JSON,不上传二进制文件。请先上传音频并获得公网 URL,再将其填入 `audioFilePath`。不要发送 `version`、`audio_format` 或本文未列出的参数。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/upload \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "audioFilePath": "https://example.com/my.mp3" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/upload" payload = { "audioFilePath": "https://example.com/my.mp3" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/upload"; const payload = { audioFilePath: "https://example.com/my.mp3" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/upload" payload := map[string]interface{}{ "audioFilePath": "https://example.com/my.mp3", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/upload"; String payload = """ { "audioFilePath": "https://example.com/my.mp3" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "https://example.com/my.mp3" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/upload") payload = { audioFilePath: "https://example.com/my.mp3" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/upload")! let payload: [String: Any] = [ "audioFilePath": "https://example.com/my.mp3" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/upload"; var payload = @"{ ""audioFilePath"": ""https://example.com/my.mp3"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/upload"; const char *payload = "{" "\"audioFilePath\":\"https://example.com/my.mp3\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/upload"]; NSDictionary *payload = @{ @"audioFilePath": @"https://example.com/my.mp3" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/upload" let payload = {|{ "audioFilePath": "https://example.com/my.mp3" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/upload'); final payload = { 'audioFilePath': 'https://example.com/my.mp3' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/upload" payload <- list( audioFilePath = "https://example.com/my.mp3" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 已上传到对象存储、可公开读取的音频 HTTP(S) 直链。本机路径与 `blob:` URL 不可用。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,轮询 `GET /v1/music/tasks/{task_id}`。完成后使用本任务 `task_id` + `audio_index=1` 作为其它操作的源;上传结果可能只有 `audio_id`,不保证返回可播放的 `audio_url`。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Cover song(风格翻唱) (#suno-cover-song) # 风格翻唱 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 以另一种风格翻唱已有歌曲。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 `custom` 决定字段是否生效;无论字段是否在当前模式生效,已提交字段仍须满足类型、范围和长度要求。`custom=true` 时 `prompt`(歌词)、`title`、`tags`、`negative_tags`、`style_weight`、`weirdness`、`audio_weight`、`persona_id` 生效,`gpt_description` 被忽略;`custom=false` 时只认 `gpt_description`(此时**必填**,缺了提交期直接 400)。`vocal_gender` 两种模式都生效。不传 `custom` 时后端按此顺序推断:有 `prompt` → `true`;无 `prompt` 但有 `gpt_description` → `false`;否则有 `tags`/`title` → `true`。 ## 用法 **用法 A —— 指定风格翻唱(最常用,推荐)** 给源歌曲 + 目标风格 `tags`,不用管 `custom`(系统看到 `tags` 会自动按 `custom=true` 处理): ```json { "model": "suno", "task_id": "task_xxx", // 源歌曲:一个已完成的音乐任务 "audio_index": 1, // 源任务里第几首(1-based,默认 1) "version": "v6", "tags": "jazz, slow" // 目标风格 → 自动 custom=true } ``` 想更精确可以再加 `prompt`(歌词)/ `title`。 **用法 B —— 灵感模式(`custom=false`)** 不指定具体风格,让模型自己发挥,但必须给 `gpt_description` 描述你想要的效果: ```json { "model": "suno", "task_id": "task_xxx", "audio_index": 1, "version": "v6", "custom": false, "gpt_description": "把这首歌翻唱成慢速爵士风格" // custom=false 时必填 } ``` 两种用法二选一,别只传 `custom=false` 却不给 `gpt_description`(会提交期直接 400)。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/cover-song \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "jazz, slow" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/cover-song" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "jazz, slow" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/cover-song"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, version: "v6", tags: "jazz, slow" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/cover-song" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "jazz, slow", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/cover-song"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "jazz, slow" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "version" => "v6", "tags" => "jazz, slow" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/cover-song") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, version: "v6", tags: "jazz, slow" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/cover-song")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "jazz, slow" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/cover-song"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""version"": ""v6"", ""tags"": ""jazz, slow"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/cover-song"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"version\":\"v6\"," "\"tags\":\"jazz, slow\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/cover-song"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"version": @"v6", @"tags": @"jazz, slow" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/cover-song" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "jazz, slow" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/cover-song'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'version': 'v6', 'tags': 'jazz, slow' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/cover-song" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, version = "v6", tags = "jazz, slow" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`;缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based:1=第 1 首;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID。与 `version`、`persona_id` 互斥。 `true`=自定义模式(用 `prompt` 作歌词);`false`=灵感模式(用 `gpt_description`);不传时按内容推断(见上方 Warning)。 歌词,`custom=true` 时生效(灵感模式下会被忽略)。 灵感提示词,`custom=false` 时**必填**(缺了提交期直接 400、不扣费)。 标题。**仅 `custom=true` 时生效**。 目标风格标签。**仅 `custom=true` 时生效**。 排除的风格标签。**仅 `custom=true` 时生效**。 风格权重,`0.00`–`1.00`(超出范围提交期直接返回 `400`)。**仅 `custom=true` 时生效**。 创意度权重,`0.00`–`1.00`。兼容旧名 `weirdness_constraint`;新请求请使用 `weirdness`。 音频权重,`0.00`–`1.00`。**仅 `custom=true` 时生效**。 人声性别:`Male` / `Female`。**两种模式均生效**。 Persona 风格 ID。**仅 `custom=true` 时生效**,与 `custom_model_id` 互斥。 目标生成时长,范围 10–360 秒,仅 `custom=true` 时可用。实际时长以结果为准。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。可省略。 是否启用 Max 模式。启用时要求自定义模式,并按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后在 `data.result.music[]` 取 `audio_url`。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Concat(合成整曲) (#suno-concat) # 完整歌曲合成 / 拼接 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 把片段合成为完整歌曲。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 **前提**:`concat` 只能拼接 **extend(续写)产生的分段结果**。若源不是 extend 产物(如普通一次性生成的整首歌),提交期直接返回 `400`。 歌曲合成本身免费。生成前置续写片段所调用的 `extend` 接口会按其价格单独计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/concat \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/concat" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/concat"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/concat" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/concat"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/concat") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/concat")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/concat"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/concat"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/concat"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/concat" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/concat'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/concat" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 源任务的 `task_id`——**必须是 extend(续写)产生的分段**(见上方 Warning)。缺失、非 extend 产物或无法解析源时,提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 输出音频格式:`mp3` / `m4a` / `wav`。 源任务必须是 `extend` 或 `extendMusic` 的续写结果。本接口用于合成一条续写链,不是任意两首歌曲的拼接工具。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取完整歌曲 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Stems(分轨提取) (#suno-stems) # 分轨提取 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 从歌曲分离出指定轨(如人声)。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`,传了会被丢弃,也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/stems \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "stem_type": "lead_vocal" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/stems" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "stem_type": "lead_vocal" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/stems"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, stem_type: "lead_vocal" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/stems" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "stem_type": "lead_vocal", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/stems"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "stem_type": "lead_vocal" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "stem_type" => "lead_vocal" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/stems") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, stem_type: "lead_vocal" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/stems")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "stem_type": "lead_vocal" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/stems"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""stem_type"": ""lead_vocal"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/stems"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"stem_type\":\"lead_vocal\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/stems"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"stem_type": @"lead_vocal" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/stems" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "stem_type": "lead_vocal" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/stems'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'stem_type': 'lead_vocal' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/stems" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, stem_type = "lead_vocal" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`;缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 要提取的分轨类型。省略时默认使用 `lead_vocal`。常用值包括 `lead_vocal`、`backing_vocals`、`drum_kit`、`bass`、`piano` 和 `electric_guitar`。 ```text lead_vocal drum_kit bass backing_vocals piano electric_guitar percussion string_section synth acoustic_guitar sound_effects synth_pad synth_bass guitar brass_section organ electronic_drum_kit lead_electric_guitar synth_keys rhythm_electric_guitar electric_piano upright_bass keyboards distorted_electric_guitar kick snare risers synth_strings synth_lead woodwinds flute harp tambourine trumpet arpeggiator accordion fiddle pedal_steel_guitar synth_voice violin digital_piano synth_brass mandolin choir banjo bells clarinet tenor_saxophone trombone shaker french_horn glockenspiel electric_bass cello timpani harmonica marimba vibraphone lap_steel_guitar saxophone orchestra horns cymbals hand_clap oboe celesta congas drone alto_saxophone double_bass ukulele harpsichord baritone_saxophone xylophone tuba bass_guitar whistle lead_guitar rhodes 808 bongos bassoon cowbell viola sitar steel_drums piccolo theremin bagpipes hi_hat music_box melodica tabla koto djembe taiko didgeridoo ``` `808` 必须作为字符串发送,例如 `"stem_type": "808"`。 输出音频格式:`mp3` / `m4a` / `wav`。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后结果里含分离出的轨 URL。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Stems all(全部分轨) (#suno-stems-all) # 全量分轨 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 多轨全分离。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`,传了会被丢弃,也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/stems-all \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/stems-all" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/stems-all"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/stems-all" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/stems-all"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/stems-all") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/stems-all")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/stems-all"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/stems-all"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/stems-all"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/stems-all" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/stems-all'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/stems-all" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`;缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 输出音频格式:`mp3` / `m4a` / `wav`。本接口不发送 `stem_type`、`version` 或 Max 字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后结果里含各分轨 URL。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Add vocals(加唱) (#suno-add-vocals) # 添加人声 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 给现有(伴奏 / 音轨)叠加人声。 - 使用 `task_id` + `audio_index` 引用 `uploadTask` 上传任务中的音轨 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:源音轨必须来自 `POST /v1/music/generations/upload` 创建的上传任务。传入该任务的 `task_id`,并用 `audio_index` 指定 `data.result.music[]` 中的音轨(1-based,默认 `1`)。普通生成任务不能作为本接口的源任务。 `custom` 决定字段是否生效;无论字段是否在当前模式生效,已提交字段仍须满足类型、范围和长度要求。`custom=true` 时 `prompt`(歌词)、`title`、`tags`、`negative_tags`、`style_weight`、`weirdness`、`audio_weight` 生效,`gpt_description` 被忽略;`custom=false` 时只认 `gpt_description`(此时**必填**,缺了提交期直接 400)。`vocal_gender` 两种模式都生效。不传 `custom` 时后端按此顺序推断:有 `prompt` → `true`;无 `prompt` 但有 `gpt_description` → `false`;否则有 `tags`/`title` → `true`。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/add-vocals \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": true, "prompt": "…歌词…" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/add-vocals" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": True, "prompt": "…歌词…" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/add-vocals"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, version: "v6", custom: true, prompt: "…歌词…" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/add-vocals" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": true, "prompt": "…歌词…", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/add-vocals"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": true, "prompt": "…歌词…" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "version" => "v6", "custom" => true, "prompt" => "…歌词…" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/add-vocals") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, version: "v6", custom: true, prompt: "…歌词…" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/add-vocals")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": true, "prompt": "…歌词…" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/add-vocals"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""version"": ""v6"", ""custom"": true, ""prompt"": ""…歌词…"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/add-vocals"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"version\":\"v6\"," "\"custom\":true," "\"prompt\":\"…歌词…\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/add-vocals"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"version": @"v6", @"custom": @YES, @"prompt": @"…歌词…" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/add-vocals" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": true, "prompt": "…歌词…" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/add-vocals'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'version': 'v6', 'custom': true, 'prompt': '…歌词…' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/add-vocals" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, version = "v6", custom = TRUE, prompt = "…歌词…" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 `POST /v1/music/generations/upload` 返回的上传任务 ID。普通生成任务不能使用;缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID,与 `version` 互斥。 `true`=自定义模式(用 `prompt` 作歌词);`false`=灵感模式(用 `gpt_description`);不传时按内容推断(见上方 Warning)。 歌词,`custom=true` 时生效(灵感模式下会被忽略)。 灵感提示词,`custom=false` 时**必填**(缺了提交期直接 400、不扣费)。 标题。**仅 `custom=true` 时生效**。 风格标签。**仅 `custom=true` 时生效**。 排除的风格标签。**仅 `custom=true` 时生效**。 风格权重,`0.00`–`1.00`(超出范围提交期直接返回 `400`)。**仅 `custom=true` 时生效**。 创意度权重,`0.00`–`1.00`。兼容旧名 `weirdness_constraint`;新请求请使用 `weirdness`。 音频权重,`0.00`–`1.00`。**仅 `custom=true` 时生效**。 人声性别:`Male` / `Female`。**两种模式均生效**。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。 是否启用 Max 模式。启用时要求自定义模式,并按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。本接口不支持目标时长字段。 本接口不支持 `auto_lyrics`、`persona_id`、`instrumental` 或目标时长字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后在 `data.result.music[]` 取 `audio_url`。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Add instrumental(加伴奏) (#suno-add-instrumental) # 添加伴奏 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 给现有(人声 / 音轨)叠加伴奏。 - 使用 `task_id` + `audio_index` 引用 `uploadTask` 上传任务中的音轨 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:源音轨必须来自 `POST /v1/music/generations/upload` 创建的上传任务。传入该任务的 `task_id`,并用 `audio_index` 指定 `data.result.music[]` 中的音轨(1-based,默认 `1`)。普通生成任务不能作为本接口的源任务。 `custom` 决定哪些字段生效;无论字段是否在当前模式生效,已提交字段仍须满足类型、范围和长度要求。`custom=true` 时 `prompt`(歌词)、`title`、`tags`、`negative_tags`、`style_weight`、`weirdness`、`audio_weight` 生效,`gpt_description` 被忽略;`custom=false` 时只读 `gpt_description`(此时**必填**,缺了提交期直接返回 400)。`vocal_gender` 两种模式都生效。不传 `custom` 时后端按此顺序推断:有 `prompt` → `true`;无 `prompt` 但有 `gpt_description` → `false`;否则有 `tags`/`title` → `true`。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/add-instrumental \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "lo-fi" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/add-instrumental" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "lo-fi" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/add-instrumental"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, version: "v6", tags: "lo-fi" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/add-instrumental" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "lo-fi", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/add-instrumental"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "lo-fi" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "version" => "v6", "tags" => "lo-fi" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/add-instrumental") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, version: "v6", tags: "lo-fi" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/add-instrumental")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "lo-fi" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/add-instrumental"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""version"": ""v6"", ""tags"": ""lo-fi"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/add-instrumental"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"version\":\"v6\"," "\"tags\":\"lo-fi\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/add-instrumental"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"version": @"v6", @"tags": @"lo-fi" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/add-instrumental" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "tags": "lo-fi" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/add-instrumental'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'version': 'v6', 'tags': 'lo-fi' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/add-instrumental" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, version = "v6", tags = "lo-fi" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 `POST /v1/music/generations/upload` 返回的上传任务 ID。普通生成任务不能使用;缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID,与 `version` 互斥。 `true`=自定义模式(用 `prompt` 作歌词);`false`=灵感模式(用 `gpt_description`);不传时按内容推断(见上方 Warning)。 歌词,`custom=true` 时生效(灵感模式下会被忽略)。 灵感提示词,`custom=false` 时**必填**(缺了提交期直接 400、不扣费)。 标题。**仅 `custom=true` 时生效**。 风格标签。**仅 `custom=true` 时生效**。 要排除的风格标签。**仅 `custom=true` 时生效**。 风格权重,`0.00`–`1.00`(越界提交期直接返回 `400`)。**仅 `custom=true` 时生效**。 创意权重,`0.00`–`1.00`。兼容旧名 `weirdness_constraint`;新请求请使用 `weirdness`。 音频权重,`0.00`–`1.00`。**仅 `custom=true` 时生效**。 人声性别:`Male` / `Female`。**两种模式都生效**。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。 是否启用 Max 模式。启用时要求自定义模式,并按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。本接口不支持目标时长字段。 本接口不支持 `auto_lyrics`、`persona_id`、`instrumental` 或目标时长字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Add stem(加音轨) (#suno-add-stem) # 添加音轨 (add stem) > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 在现有音轨上叠加一条 stem。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 `custom` 决定哪些字段生效;无论字段是否在当前模式生效,已提交字段仍须满足类型、范围和长度要求。`custom=true` 时 `prompt`(歌词)、`title`、`tags`、`negative_tags`、`style_weight`、`weirdness`、`audio_weight` 生效,`gpt_description` 被忽略;`custom=false` 时只读 `gpt_description`(此时**必填**,缺了提交期直接返回 400)。不传 `custom` 时后端按此顺序推断:有 `prompt` → `true`;无 `prompt` 但有 `gpt_description` → `false`;否则有 `tags`/`title` → `true`。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/add-stem \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": false, "gpt_description": "加入温暖的弦乐声部" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/add-stem" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": False, "gpt_description": "加入温暖的弦乐声部" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/add-stem"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, version: "v6", custom: false, gpt_description: "加入温暖的弦乐声部" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/add-stem" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": false, "gpt_description": "加入温暖的弦乐声部", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/add-stem"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": false, "gpt_description": "加入温暖的弦乐声部" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "version" => "v6", "custom" => false, "gpt_description" => "加入温暖的弦乐声部" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/add-stem") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, version: "v6", custom: false, gpt_description: "加入温暖的弦乐声部" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/add-stem")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": false, "gpt_description": "加入温暖的弦乐声部" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/add-stem"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""version"": ""v6"", ""custom"": false, ""gpt_description"": ""加入温暖的弦乐声部"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/add-stem"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"version\":\"v6\"," "\"custom\":false," "\"gpt_description\":\"加入温暖的弦乐声部\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/add-stem"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"version": @"v6", @"custom": @NO, @"gpt_description": @"加入温暖的弦乐声部" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/add-stem" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "version": "v6", "custom": false, "gpt_description": "加入温暖的弦乐声部" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/add-stem'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'version': 'v6', 'custom': false, 'gpt_description': '加入温暖的弦乐声部' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/add-stem" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, version = "v6", custom = FALSE, gpt_description = "加入温暖的弦乐声部" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID,与 `version` 互斥。 `true`=自定义模式(用 `prompt` 作歌词);`false`=灵感模式(用 `gpt_description`);不传时按内容推断(见上方 Warning)。 歌词,`custom=true` 时生效(灵感模式下会被忽略)。 灵感提示词,`custom=false` 时**必填**(缺了提交期直接 400、不扣费)。 标题。**仅 `custom=true` 时生效**。 风格标签。**仅 `custom=true` 时生效**。 要排除的风格标签。**仅 `custom=true` 时生效**。 风格权重,`0.00`–`1.00`(越界提交期直接返回 `400`)。**仅 `custom=true` 时生效**。 创意权重,`0.00`–`1.00`。兼容旧名 `weirdness_constraint`;新请求请使用 `weirdness`。 音频权重,`0.00`–`1.00`。**仅 `custom=true` 时生效**。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。 是否启用 Max 模式。启用时要求自定义模式,并按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。本接口不支持目标时长字段。 本接口不支持 `auto_lyrics`、`persona_id`、`instrumental`、`vocal_gender` 或目标时长字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Replace music(段落替换) (#suno-replace-music) # 段落替换 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 替换歌曲的某一段(infill)。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/replace-music \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45, "infill_lyrics": "新的一段歌词" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/replace-music" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45, "infill_lyrics": "新的一段歌词" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/replace-music"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, start_s: 30, end_s: 45, infill_lyrics: "新的一段歌词" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/replace-music" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45, "infill_lyrics": "新的一段歌词", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/replace-music"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45, "infill_lyrics": "新的一段歌词" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "start_s" => 30, "end_s" => 45, "infill_lyrics" => "新的一段歌词" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/replace-music") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, start_s: 30, end_s: 45, infill_lyrics: "新的一段歌词" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/replace-music")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45, "infill_lyrics": "新的一段歌词" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/replace-music"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""start_s"": 30, ""end_s"": 45, ""infill_lyrics"": ""新的一段歌词"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/replace-music"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"start_s\":30," "\"end_s\":45," "\"infill_lyrics\":\"新的一段歌词\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/replace-music"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"start_s": @30, @"end_s": @45, @"infill_lyrics": @"新的一段歌词" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/replace-music" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45, "infill_lyrics": "新的一段歌词" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/replace-music'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'start_s': 30, 'end_s': 45, 'infill_lyrics': '新的一段歌词' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/replace-music" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, start_s = 30, end_s = 45, infill_lyrics = "新的一段歌词" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 替换段歌词。 替换起点(秒)。缺失直接返回 `400`。 替换终点(秒)。必须满足 `0 ≤ start_s < end_s`;源时长已知时不能越界。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID,与 `version` 互斥。 上下文歌词。 标题。 风格标签。 要排除的风格标签。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。可省略。 是否启用 Max 模式;启用后按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。本接口不支持目标时长字段。 `prompt` 是原歌词上下文,`infill_lyrics` 是替换片段的新歌词。不要发送 `custom`、`instrumental`、`auto_lyrics` 或旧编辑会话字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取替换后的 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Remove section(删除段落) (#suno-remove-section) # 删除片段 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 删除歌曲的某个时间区间。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/remove-section \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/remove-section" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/remove-section"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, start_s: 30, end_s: 45 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/remove-section" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/remove-section"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "start_s" => 30, "end_s" => 45 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/remove-section") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, start_s: 30, end_s: 45 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/remove-section")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/remove-section"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""start_s"": 30, ""end_s"": 45 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/remove-section"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"start_s\":30," "\"end_s\":45" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/remove-section"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"start_s": @30, @"end_s": @45 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/remove-section" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 30, "end_s": 45 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/remove-section'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'start_s': 30, 'end_s': 45 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/remove-section" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, start_s = 30, end_s = 45 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 删除起点(秒),必须大于等于 0;支持小数秒。 删除终点(秒)。必须大于 `start_s`,且不能超过已知源时长;支持小数秒。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取处理后的 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Crop(裁剪) (#suno-crop) # 裁剪音频 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 裁剪保留指定区间。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/crop \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 10, "end_s": 40 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/crop" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 10, "end_s": 40 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/crop"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, start_s: 10, end_s: 40 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/crop" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 10, "end_s": 40, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/crop"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 10, "end_s": 40 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "start_s" => 10, "end_s" => 40 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/crop") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, start_s: 10, end_s: 40 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/crop")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 10, "end_s": 40 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/crop"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""start_s"": 10, ""end_s"": 40 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/crop"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"start_s\":10," "\"end_s\":40" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/crop"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"start_s": @10, @"end_s": @40 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/crop" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 10, "end_s": 40 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/crop'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'start_s': 10, 'end_s': 40 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/crop" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, start_s = 10, end_s = 40 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 裁剪起点(秒),必须大于等于 0;支持小数秒。 裁剪终点(秒)。必须大于 `start_s`,且不能超过已知源时长;支持小数秒。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取裁剪后的 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Fade in(淡入) (#suno-fade-in) # 淡入 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 开头淡入。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/fade-in \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/fade-in" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/fade-in"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, duration_s: 3 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/fade-in" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/fade-in"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "duration_s" => 3 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/fade-in") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, duration_s: 3 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/fade-in")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/fade-in"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""duration_s"": 3 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/fade-in"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"duration_s\":3" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/fade-in"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"duration_s": @3 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/fade-in" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/fade-in'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'duration_s': 3 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/fade-in" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, duration_s = 3 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 淡入时长(秒)。必须大于 0,且不能超过已知源时长;支持小数秒。 标题(默认 `Untitled`)。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取处理后的 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Fade out(淡出) (#suno-fade-out) # 淡出 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 结尾淡出。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/fade-out \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/fade-out" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/fade-out"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, duration_s: 3 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/fade-out" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/fade-out"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "duration_s" => 3 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/fade-out") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, duration_s: 3 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/fade-out")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/fade-out"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""duration_s"": 3 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/fade-out"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"duration_s\":3" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/fade-out"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"duration_s": @3 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/fade-out" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "duration_s": 3 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/fade-out'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'duration_s': 3 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/fade-out" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, duration_s = 3 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 淡出时长(秒)。必须大于 0,且不能超过已知源时长;支持小数秒。 标题(默认 `Untitled`)。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取处理后的 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Adjust speed(变速) (#suno-adjust-speed) # 调整速度 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 变速(不改音高)。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/adjust-speed \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "speed": 1.25 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/adjust-speed" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "speed": 1.25 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/adjust-speed"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, speed: 1.25 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/adjust-speed" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "speed": 1.25, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/adjust-speed"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "speed": 1.25 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "speed" => 1.25 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/adjust-speed") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, speed: 1.25 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/adjust-speed")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "speed": 1.25 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/adjust-speed"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""speed"": 1.25 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/adjust-speed"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"speed\":1.25" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/adjust-speed"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"speed": @1.25 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/adjust-speed" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "speed": 1.25 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/adjust-speed'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'speed': 1.25 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/adjust-speed" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, speed = 1.25 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 倍速,范围 `0.25`~`4`,如 `1.25`。缺失或越界提交期直接返回 `400`。 变速时是否保持原音高(默认 `true`)。 标题(默认 `Untitled`)。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取处理后的 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Remaster(母带) (#suno-remaster) # 母带优化 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 对已生成歌曲做母带优化,提升音质、清晰度与整体质感。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点没有版本参数,请勿传入 `version`。任务按 `suno@remaster` 计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/remaster \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/remaster" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/remaster"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/remaster" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/remaster"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/remaster") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/remaster")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/remaster"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/remaster"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/remaster"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/remaster" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/remaster'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/remaster" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`;缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 改编强度:`subtle` / `normal` / `high`。 输出音频格式:`mp3` / `m4a` / `wav`。 本接口不支持 `custom_model_id`、`max_mode`、`variety` 或目标时长字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后在 `data.result.music[]` 取优化后的 `audio_url`。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Generate MP4(MV) (#suno-generate-mp4) # 生成音乐视频 (MV) > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 为歌曲生成 MV 视频。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/generate-mp4 \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/generate-mp4" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/generate-mp4"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/generate-mp4" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/generate-mp4"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/generate-mp4") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/generate-mp4")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/generate-mp4"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/generate-mp4"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/generate-mp4"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/generate-mp4" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/generate-mp4'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/generate-mp4" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 **获取结果**:提交后轮询 `GET /v1/music/tasks/{task_id}`。完成后优先读取 `data.result.videoUrl`,并兼容历史 `result.videos[]` 或 `result.music[].video_url`。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Export WAV (#suno-wav) # 下载音频文件 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 将 Suno 歌曲下载为 MP3、M4A 或 WAV 文件 - 支持一次请求多个格式,返回对应的文件 URL - 使用源任务 task_id 和 audio_index 指定要下载的歌曲 - 异步提交任务,通过音乐任务查询接口获取结果 原 `POST /v1/music/generations/wav` 接口已弃用。旧接口暂时兼容,等价于调用新接口并传入 `formats: ["wav"]`;新代码请统一使用 `POST /v1/music/generations/download`。 **指定源歌曲:** 传入生成源音轨时获得的 `task_id`,并用 `audio_index` 指定结果 `data.result.music[]` 中的第几首歌曲。`audio_index` 从 1 开始,默认值为 1。 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/download \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01JGXXXXXXXXXXXX", "audio_index": 1, "formats": ["mp3", "wav"] }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/download" payload = { "model": "suno", "task_id": "task_01JGXXXXXXXXXXXX", "audio_index": 1, "formats": ["mp3", "wav"], } headers = { "Authorization": "Bearer ", "Content-Type": "application/json", } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const response = await fetch( "https://api.seedance.nz/v1/music/generations/download", { method: "POST", headers: { Authorization: "Bearer ", "Content-Type": "application/json", }, body: JSON.stringify({ model: "suno", task_id: "task_01JGXXXXXXXXXXXX", audio_index: 1, formats: ["mp3", "wav"], }), }, ); console.log(await response.json()); ``` ```go 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.seedance.nz/v1/music/generations/download", bytes.NewBuffer(body), ) req.Header.Set("Authorization", "Bearer ") 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)) } ``` ```java 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.seedance.nz/v1/music/generations/download")) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = HttpClient.newHttpClient().send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println(response.body()); } } ``` ```php "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 ", "Content-Type: application/json" ]); echo curl_exec($ch); curl_close($ch); ?> ``` ```ruby require "net/http" require "json" uri = URI("https://api.seedance.nz/v1/music/generations/download") request = Net::HTTP::Post.new(uri) request["Authorization"] = "Bearer " 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 ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/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 ", 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() ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01JHXXXXXXXXXXXX" } ] } ``` ```json { "error": { "message": "`formats` contains unsupported format `flac`. Supported: mp3 / m4a / wav", "type": "invalid_request_error", "code": "invalid_source_reference" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的 API 密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": "model_price_not_configured", "message": "模型价格未配置", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ## 认证 所有接口均使用 Bearer Token 认证。登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key。 ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称。当前填写 `suno`;省略时默认为 `suno`。 生成源歌曲时返回的任务 ID。 源任务必须: * 属于当前账户 * 已完成 * 包含可下载的音轨 音乐生成、延长、翻唱、分轨等音频任务均可作为来源;歌词、BPM 等仅返回文本的任务无法下载。 要下载源任务结果 `data.result.music[]` 中的第几首歌曲。 * 从 `1` 开始计数 * 默认:`1` * 不得超过源任务实际包含的歌曲数量 要下载的文件格式数组,至少包含一项。 可选值: * `mp3` * `m4a` * `wav` 支持同时请求多个格式;格式名大小写不敏感,重复值会自动去重。结果顺序与请求顺序一致。 只下载一种格式时,可使用此字段代替 `formats`。 示例:`"format": "mp3"` `formats` 和 `format` 选择一种写法即可。两者均未提供或格式列表为空时,请求会返回 HTTP 400。 ## 提交响应 成功提交后返回下载任务自己的 `task_id`: ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01JHXXXXXXXXXXXX" } ] } ``` 返回的 `data` 是数组,请读取 `data[0].task_id`。它是新建的下载任务 ID,与请求中的源歌曲 `task_id` 不同。 ## 查询下载结果 使用提交响应中的下载任务 ID 查询: ```http GET /v1/music/tasks/{task_id} ``` 文件通常已在提交阶段准备完成,因此提交后可以立即查询一次。如果状态不是 `completed` 或 `failed`,再每 2 秒轮询一次,最多等待 60 秒。 ### 下载完成 ```json { "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.api.seedance.nz/audio/example.mp3" }, { "format": "wav", "url": "https://assets.api.seedance.nz/audio/example.wav" } ], "wavUrl": "https://assets.api.seedance.nz/audio/example.wav" } } } ``` 读取 `result.files[]` 获取下载文件: | 字段 | 类型 | 说明 | | -------- | ------ | -------------------------- | | `format` | string | 文件格式:`mp3` / `m4a` / `wav` | | `url` | string | 文件下载地址 | `result.wavUrl` 仅用于兼容旧 WAV 接口。新代码请统一读取 `result.files[]`。 ### 处理中 ```json { "code": 200, "data": { "id": "task_01JHXXXXXXXXXXXX", "status": "processing", "progress": 50, "created": 1756800000 } } ``` 此时没有 `result` 字段,请继续轮询。 ### 下载失败 ```json { "code": 200, "data": { "id": "task_01JHXXXXXXXXXXXX", "status": "failed", "progress": 100, "cost": 0, "error": { "message": "文件处理失败" } } } ``` 失败任务会自动退款,`cost` 为 `0`。可向用户显示 `error.message` 并提供重试操作。 ## 文件 URL 下载结果通常使用 文件域名。返回的文件 URL 可能存在有效期,请在任务完成后及时下载并保存。 请在获得 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` | 源任务未完成或对应歌曲没有音频 | HTTP 403 且错误码为 `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 响应状态码,成功时为 200 提交响应数据。 初始状态为 `submitted` 下载任务 ID,用于轮询 `GET /v1/music/tasks/{task_id}` ### Generate MIDI (#suno-midi) # 生成 MIDI > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 从歌曲生成 MIDI。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/midi \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/midi" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/midi"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/midi" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/midi"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/midi") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/midi")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/midi"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/midi"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/midi"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/midi" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/midi'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/midi" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 **获取结果**:提交后轮询 `GET /v1/music/tasks/{task_id}`。完成结果通常包含 `result.state` 和 `result.instruments[]`,每个乐器的 `notes[]` 提供音符数据;当前不保证直接返回 `.mid` 文件 URL。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### BPM analysis (#suno-bpm) # BPM 分析 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 分析歌曲 BPM。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/bpm \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/bpm" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/bpm"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/bpm" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/bpm"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/bpm") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/bpm")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/bpm"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/bpm"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/bpm"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/bpm" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/bpm'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/bpm" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 **获取结果**:提交后轮询 `GET /v1/music/tasks/{task_id}`。完成后读取 `result.avg_bpm`、`result.min_bpm` 和 `result.max_bpm`;字段可能为字符串或数字,转换后应检查是否为有限数值。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Aligned lyrics(歌词时间轴) (#suno-aligned-lyrics) # 歌词时间轴 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 生成逐句对齐的歌词时间轴。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/aligned-lyrics \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/aligned-lyrics" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/aligned-lyrics"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/aligned-lyrics" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/aligned-lyrics"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/aligned-lyrics") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/aligned-lyrics")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/aligned-lyrics"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/aligned-lyrics"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/aligned-lyrics"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/aligned-lyrics" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/aligned-lyrics'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/aligned-lyrics" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 **获取结果**:提交后轮询 `GET /v1/music/tasks/{task_id}`。优先读取 `result.alignment[]` 与 `result.waveform_data`;历史任务也可能在 `music[]` 中返回 `aligned_words`、`aligned_lyrics` 或 `waveform_data`。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Upsample tags(标签增强) (#suno-upsample-tags) # 标签增强 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 优化 / 扩写风格标签,提升 prompt 质量。 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果。 本端点**无版本维度**:不要传 `version`,传了会被丢弃,也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/upsample-tags \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "tags": "pop" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/upsample-tags" payload = { "model": "suno", "tags": "pop" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/upsample-tags"; const payload = { model: "suno", tags: "pop" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/upsample-tags" payload := map[string]interface{}{ "model": "suno", "tags": "pop", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/upsample-tags"; String payload = """ { "model": "suno", "tags": "pop" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "tags" => "pop" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/upsample-tags") payload = { model: "suno", tags: "pop" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/upsample-tags")! let payload: [String: Any] = [ "model": "suno", "tags": "pop" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/upsample-tags"; var payload = @"{ ""model"": ""suno"", ""tags"": ""pop"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/upsample-tags"; const char *payload = "{" "\"model\":\"suno\"," "\"tags\":\"pop\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/upsample-tags"]; NSDictionary *payload = @{ @"model": @"suno", @"tags": @"pop" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/upsample-tags" let payload = {|{ "model": "suno", "tags": "pop" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/upsample-tags'); final payload = { 'model': 'suno', 'tags': 'pop' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/upsample-tags" payload <- list( model = "suno", tags = "pop" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 待增强的风格标签;缺失时提交期直接返回 `400`(不扣费)。 **获取结果**:提交后读取 `data[0].task_id`,再查询 `GET /v1/music/tasks/{task_id}`。完成后从 `data.result.upsampled_tags` 读取优化后的标签。无论任务多快完成,都需要通过任务查询接口获取结果。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Sounds(音效) (#suno-sounds) # 音效生成 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 根据描述生成音效。 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/sounds \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "prompt": "雷雨与远处的钟声" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/sounds" payload = { "model": "suno", "prompt": "雷雨与远处的钟声" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/sounds"; const payload = { model: "suno", prompt: "雷雨与远处的钟声" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/sounds" payload := map[string]interface{}{ "model": "suno", "prompt": "雷雨与远处的钟声", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/sounds"; String payload = """ { "model": "suno", "prompt": "雷雨与远处的钟声" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "prompt" => "雷雨与远处的钟声" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/sounds") payload = { model: "suno", prompt: "雷雨与远处的钟声" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/sounds")! let payload: [String: Any] = [ "model": "suno", "prompt": "雷雨与远处的钟声" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/sounds"; var payload = @"{ ""model"": ""suno"", ""prompt"": ""雷雨与远处的钟声"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/sounds"; const char *payload = "{" "\"model\":\"suno\"," "\"prompt\":\"雷雨与远处的钟声\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/sounds"]; NSDictionary *payload = @{ @"model": @"suno", @"prompt": @"雷雨与远处的钟声" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/sounds" let payload = {|{ "model": "suno", "prompt": "雷雨与远处的钟声" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/sounds'); final payload = { 'model': 'suno', 'prompt': '雷雨与远处的钟声' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/sounds" payload <- list( model = "suno", prompt = "雷雨与远处的钟声" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。 音效文本描述;缺失时提交期直接返回 `400`(不扣费)。建议尽量使用英文提示词,效果更佳。 音效类型:`one-shot`(默认,单次)/ `loop`(可循环)。 速度,`1`–`300`;超出范围提交期直接返回 `400`。 调性枚举:大调 `C` / `C#` / `D` / `D#` / `E` / `F` / `F#` / `G` / `G#` / `A` / `A#` / `B`;小调在后面加 `m`(`Cm` / `C#m` / … / `Bm`)。仅支持升号(`#`)写法,降号(`Db` / `Eb` 等)与 `B#` 会返回 `400`(key param error)。 输出音频格式:`mp3` / `m4a` / `wav`。 本接口不支持自定义模型、Max、`variety` 或目标时长字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后在 `data.result.music[]` 取 `audio_url`。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Inspo(灵感生成) (#suno-inspo) # 灵感生成 (inspo) > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 用 1–4 段公网音频作为灵感参考生成新歌(直接给音频 URL,不走 task_id)。 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/inspo \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "audio_urls": [ "https://a/1.mp3", "https://a/2.mp3" ], "version": "v6", "tags": "dreamy pop" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/inspo" payload = { "model": "suno", "audio_urls": ["https://a/1.mp3", "https://a/2.mp3"], "version": "v6", "tags": "dreamy pop" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/inspo"; const payload = { model: "suno", audio_urls: ["https://a/1.mp3", "https://a/2.mp3"], version: "v6", tags: "dreamy pop" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/inspo" payload := map[string]interface{}{ "model": "suno", "audio_urls": []string{"https://a/1.mp3", "https://a/2.mp3"}, "version": "v6", "tags": "dreamy pop", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/inspo"; String payload = """ { "model": "suno", "audio_urls": [ "https://a/1.mp3", "https://a/2.mp3" ], "version": "v6", "tags": "dreamy pop" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "audio_urls" => ["https://a/1.mp3", "https://a/2.mp3"], "version" => "v6", "tags" => "dreamy pop" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/inspo") payload = { model: "suno", audio_urls: ["https://a/1.mp3", "https://a/2.mp3"], version: "v6", tags: "dreamy pop" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/inspo")! let payload: [String: Any] = [ "model": "suno", "audio_urls": ["https://a/1.mp3", "https://a/2.mp3"], "version": "v6", "tags": "dreamy pop" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/inspo"; var payload = @"{ ""model"": ""suno"", ""audio_urls"": [ ""https://a/1.mp3"", ""https://a/2.mp3"" ], ""version"": ""v6"", ""tags"": ""dreamy pop"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/inspo"; const char *payload = "{" "\"model\":\"suno\"," "\"audio_urls\":[\"https://a/1.mp3\",\"https://a/2.mp3\"]," "\"version\":\"v6\"," "\"tags\":\"dreamy pop\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/inspo"]; NSDictionary *payload = @{ @"model": @"suno", @"audio_urls": @[@"https://a/1.mp3", @"https://a/2.mp3"], @"version": @"v6", @"tags": @"dreamy pop" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/inspo" let payload = {|{ "model": "suno", "audio_urls": [ "https://a/1.mp3", "https://a/2.mp3" ], "version": "v6", "tags": "dreamy pop" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/inspo'); final payload = { 'model': 'suno', 'audio_urls': ['https://a/1.mp3', 'https://a/2.mp3'], 'version': 'v6', 'tags': 'dreamy pop' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/inspo" payload <- list( model = "suno", audio_urls = c("https://a/1.mp3", "https://a/2.mp3"), version = "v6", tags = "dreamy pop" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 1–4 个可公开访问的音频 URL 数组。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID,与 `version` 互斥。 歌词 / 内容。 标题。 风格标签。 排除的风格标签。 风格权重,`0.00`–`1.00`。 创意度权重,`0.00`–`1.00`。兼容旧名 `weirdness_constraint`;新请求请使用 `weirdness`。 音频权重,`0.00`–`1.00`。 人声性别:`Male` / `Female`。 `true`=对输入歌词进行二次创作。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。可省略。 是否启用 Max 模式;启用后按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。 本接口接收 1–4 条公开音频直链,不发送 `custom`、`instrumental`、`gpt_description`、`persona_id` 或目标时长字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后在 `data.result.music[]` 取 `audio_url`。失败时 `data.error.message` 为原因,自动退回预扣额度。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Sample(采样成曲) (#suno-sample) # 样本转歌曲 (sample) > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 以样本为基础生成歌曲。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 `custom` 决定哪些字段生效;无论字段是否在当前模式生效,已提交字段仍须满足类型、范围和长度要求。`custom=true` 时 `prompt`(歌词)、`title`、`tags`、`negative_tags`、`auto_lyrics`、`style_weight`、`weirdness`、`audio_weight` 生效,`gpt_description` 被忽略;`custom=false` 时只读 `gpt_description`(此时**必填**,缺了提交期直接返回 400)。`vocal_gender` 两种模式都生效。不传 `custom` 时后端按此顺序推断:有 `prompt` → `true`;无 `prompt` 但有 `gpt_description` → `false`;否则有 `tags`/`title` → `true`。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/sample \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 0, "end_s": 8, "instrumental": false, "prompt": "沿着夜色继续歌唱", "version": "v6", "tags": "upbeat pop" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/sample" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 0, "end_s": 8, "instrumental": False, "prompt": "沿着夜色继续歌唱", "version": "v6", "tags": "upbeat pop" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/sample"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, start_s: 0, end_s: 8, instrumental: false, prompt: "沿着夜色继续歌唱", version: "v6", tags: "upbeat pop" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/sample" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 0, "end_s": 8, "instrumental": false, "prompt": "沿着夜色继续歌唱", "version": "v6", "tags": "upbeat pop", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/sample"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 0, "end_s": 8, "instrumental": false, "prompt": "沿着夜色继续歌唱", "version": "v6", "tags": "upbeat pop" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "start_s" => 0, "end_s" => 8, "instrumental" => false, "prompt" => "沿着夜色继续歌唱", "version" => "v6", "tags" => "upbeat pop" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/sample") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, start_s: 0, end_s: 8, instrumental: false, prompt: "沿着夜色继续歌唱", version: "v6", tags: "upbeat pop" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/sample")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 0, "end_s": 8, "instrumental": false, "prompt": "沿着夜色继续歌唱", "version": "v6", "tags": "upbeat pop" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/sample"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""start_s"": 0, ""end_s"": 8, ""instrumental"": false, ""prompt"": ""沿着夜色继续歌唱"", ""version"": ""v6"", ""tags"": ""upbeat pop"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/sample"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"start_s\":0," "\"end_s\":8," "\"instrumental\":false," "\"prompt\":\"沿着夜色继续歌唱\"," "\"version\":\"v6\"," "\"tags\":\"upbeat pop\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/sample"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"start_s": @0, @"end_s": @8, @"instrumental": @NO, @"prompt": @"沿着夜色继续歌唱", @"version": @"v6", @"tags": @"upbeat pop" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/sample" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "start_s": 0, "end_s": 8, "instrumental": false, "prompt": "沿着夜色继续歌唱", "version": "v6", "tags": "upbeat pop" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/sample'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'start_s': 0, 'end_s': 8, 'instrumental': false, 'prompt': '沿着夜色继续歌唱', 'version': 'v6', 'tags': 'upbeat pop' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/sample" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, start_s = 0, end_s = 8, instrumental = FALSE, prompt = "沿着夜色继续歌唱", version = "v6", tags = "upbeat pop" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`,必须为 `uploadTask` 上传任务。缺失、不是上传任务或无法解析源时,提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based:1=第 1 首;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 采样起点(秒)。缺失直接返回 `400`。 采样终点(秒)。必须满足 `0 ≤ start_s < end_s`;源时长已知时不能越界。 是否纯器乐(`true`=无人声);不传默认 `false`(要人声)。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID,与 `version` 互斥。 `true`=自定义模式(用 `prompt` 作歌词);`false`=灵感模式(用 `gpt_description`);不传时按内容推断(见上方 Warning)。 **条件必填**:`custom=true && instrumental=false` 时必须提供歌词;灵感模式下不生效,但已提交值仍须满足长度要求。 灵感提示词,`custom=false` 时**必填**(缺了提交期直接 400、不扣费)。 标题。**仅 `custom=true` 时生效**。 风格标签。**仅 `custom=true` 时生效**。 要排除的风格标签。**仅 `custom=true` 时生效**。 `true`=对输入歌词进行二次创作。**仅 `custom=true` 时生效**。 风格权重,`0.00`–`1.00`(越界提交期直接返回 `400`)。**仅 `custom=true` 时生效**。 创意权重,`0.00`–`1.00`。兼容旧名 `weirdness_constraint`;新请求请使用 `weirdness`。 音频权重,`0.00`–`1.00`。**仅 `custom=true` 时生效**。 人声性别:`Male` / `Female`。**两种模式都生效**。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。可省略。 是否启用 Max 模式。启用时要求自定义模式,并按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。本接口不支持目标时长字段。 源任务必须来自 `uploadTask` 上传结果;`start_s` 与 `end_s` 都是必填值,不会自动补成 0 或 60。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Mashup(混搭) (#suno-mashup) # 生成混搭 (mashup) > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 把歌曲做混搭再创作。 - 引用源音轨:需**恰好 2 个**,用 `task_ids`(长度 2 的数组)+ 可选 `audio_indexes` 指定 - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:mashup 需要**恰好 2 个源音轨**——用 `task_ids`(长度为 2 的 task\_id 数组)指定,可选 `audio_indexes`(与之平行的数组,指定各任务取 `music[]` 第几首,1-based,默认都取 `1`)。 `custom` 决定哪些字段生效;无论字段是否在当前模式生效,已提交字段仍须满足类型、范围和长度要求。`custom=true` 时 `prompt`(歌词)、`title`、`tags`、`negative_tags`、`auto_lyrics`、`style_weight`、`weirdness`、`audio_weight`、`persona_id` 生效,`gpt_description` 被忽略;`custom=false` 时只读 `gpt_description`(此时**必填**,缺了提交期直接返回 400)。`vocal_gender` 两种模式都生效。不传 `custom` 时后端按此顺序推断:有 `prompt` → `true`;无 `prompt` 但有 `gpt_description` → `false`;否则有 `tags`/`title` → `true`。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/mashup \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_ids": ["task_01ABC", "task_01DEF"], "audio_indexes": [1, 2], "custom": true, "prompt": "upbeat mashup of the two tracks" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/mashup" payload = { "model": "suno", "task_ids": ["task_01ABC", "task_01DEF"], "audio_indexes": [1, 2], "custom": True, "prompt": "upbeat mashup of the two tracks" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/mashup"; const payload = { model: "suno", task_ids: ["task_01ABC", "task_01DEF"], audio_indexes: [1, 2], custom: true, prompt: "upbeat mashup of the two tracks" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/mashup" payload := map[string]interface{}{ "model": "suno", "task_ids": []string{"task_01ABC", "task_01DEF"}, "audio_indexes": []int{1, 2}, "custom": true, "prompt": "upbeat mashup of the two tracks", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/mashup"; String payload = """ { "model": "suno", "task_ids": ["task_01ABC", "task_01DEF"], "audio_indexes": [1, 2], "custom": true, "prompt": "upbeat mashup of the two tracks" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_ids" => ["task_01ABC", "task_01DEF"], "audio_indexes" => [1, 2], "custom" => true, "prompt" => "upbeat mashup of the two tracks" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/mashup") payload = { model: "suno", task_ids: ["task_01ABC", "task_01DEF"], audio_indexes: [1, 2], custom: true, prompt: "upbeat mashup of the two tracks" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/mashup")! let payload: [String: Any] = [ "model": "suno", "task_ids": ["task_01ABC", "task_01DEF"], "audio_indexes": [1, 2], "custom": true, "prompt": "upbeat mashup of the two tracks" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/mashup"; var payload = @"{ ""model"": ""suno"", ""task_ids"": [""task_01ABC"", ""task_01DEF""], ""audio_indexes"": [1, 2], ""custom"": true, ""prompt"": ""upbeat mashup of the two tracks""" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/mashup"; const char *payload = "{" "\"model\":\"suno\"," "\"task_ids\":[\"task_01ABC\",\"task_01DEF\"]," "\"audio_indexes\":[1,2]," "\"custom\":true," "\"prompt\":\"upbeat mashup of the two tracks\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/mashup"]; NSDictionary *payload = @{ @"model": @"suno", @"task_ids": @[@"task_01ABC", @"task_01DEF"], @"audio_indexes": @[@1, @2], @"custom": @YES, @"prompt": @"upbeat mashup of the two tracks" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/mashup" let payload = {|{ "model": "suno", "task_ids": ["task_01ABC", "task_01DEF"], "audio_indexes": [1, 2], "custom": true, "prompt": "upbeat mashup of the two tracks" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/mashup'); final payload = { 'model': 'suno', 'task_ids': ['task_01ABC', 'task_01DEF'], 'audio_indexes': [1, 2], 'custom': true, 'prompt': 'upbeat mashup of the two tracks' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/mashup" payload <- list( model = "suno", task_ids = c("task_01ABC", "task_01DEF"), audio_indexes = c(1, 2), custom = TRUE, prompt = "upbeat mashup of the two tracks" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 2 个源音轨所属任务的 `task_id` 数组(须**恰好 2 个**;数量不对提交期直接返回 `400`)。 与 `task_ids` 平行的数组,指定各任务取结果 `data.result.music[]` 第几首(1-based,默认都取 `1`)。 是否纯器乐(`true`=无人声);不传默认 `false`(要人声)。 公共版本:`v6` / `v6-wild` / `v6-mini`;省略时默认 `v6`。使用 `custom_model_id` 时省略本字段。 创建模型任务返回的完整 UUID。与 `version`、`persona_id` 互斥。 `true`=自定义模式(用 `prompt` 作歌词);`false`=灵感模式(用 `gpt_description`);不传时按内容推断(见上方 Warning)。 **条件必填**:`custom=true && instrumental=false` 时必须提供歌词;灵感模式下不生效,但已提交值仍须满足长度要求。 灵感提示词,`custom=false` 时**必填**(缺了提交期直接 400、不扣费)。 标题。**仅 `custom=true` 时生效**。 风格标签。**仅 `custom=true` 时生效**。 要排除的风格标签。**仅 `custom=true` 时生效**。 `true`=对输入歌词进行二次创作。**仅 `custom=true` 时生效**。 风格权重,`0.00`–`1.00`(越界提交期直接返回 `400`)。**仅 `custom=true` 时生效**。 创意权重,`0.00`–`1.00`。兼容旧名 `weirdness_constraint`;新请求请使用 `weirdness`。 音频权重,`0.00`–`1.00`。**仅 `custom=true` 时生效**。 人声性别:`Male` / `Female`。**两种模式都生效**。 Persona 风格 ID。**仅 `custom=true` 时生效**,与 `custom_model_id` 互斥。 风格变化程度:`off` / `normal` / `high` / `extra` / `max`。可省略。 是否启用 Max 模式。启用时要求自定义模式,并按普通售价的 2 倍计费。 输出音频格式:`mp3` / `m4a` / `wav`。本接口不支持目标时长字段。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(音乐生成通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。完成后从 `data.result.music[]` 取 `audio_url`。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Create voice(创建音色) (#suno-create-voice) # 创建语音 > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 从音轨创建可复用音色。 - 引用源音轨:本端点**不走 `task_id` + `audio_index`**,直接给一个可公开访问的 `audio_url` - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:本端点**不走 `task_id` + `audio_index`**,需直接给一个可公开访问的 `audio_url`(系统据此提取音色)。缺失会返回 400 `audio_url cannot be empty`。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/create-voice \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "audio_url": "https://example.com/source.mp3" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/create-voice" payload = { "model": "suno", "audio_url": "https://example.com/source.mp3" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/create-voice"; const payload = { model: "suno", audio_url: "https://example.com/source.mp3" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/create-voice" payload := map[string]interface{}{ "model": "suno", "audio_url": "https://example.com/source.mp3", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/create-voice"; String payload = """ { "model": "suno", "audio_url": "https://example.com/source.mp3" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "audio_url" => "https://example.com/source.mp3" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/create-voice") payload = { model: "suno", audio_url: "https://example.com/source.mp3" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/create-voice")! let payload: [String: Any] = [ "model": "suno", "audio_url": "https://example.com/source.mp3" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/create-voice"; var payload = @"{ ""model"": ""suno"", ""audio_url"": ""https://example.com/source.mp3"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/create-voice"; const char *payload = "{" "\"model\":\"suno\"," "\"audio_url\":\"https://example.com/source.mp3\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/create-voice"]; NSDictionary *payload = @{ @"model": @"suno", @"audio_url": @"https://example.com/source.mp3" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/create-voice" let payload = {|{ "model": "suno", "audio_url": "https://example.com/source.mp3" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/create-voice'); final payload = { 'model': 'suno', 'audio_url': 'https://example.com/source.mp3' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/create-voice" payload <- list( model = "suno", audio_url = "https://example.com/source.mp3" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 源音轨的公网可访问 URL,系统据此提取音色。**仅接受 MP3 / WAV。** 缺失返回 400 `audio_url cannot be empty`。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,轮询 `GET /v1/music/tasks/{task_id}`。当前没有固定的 `result.voice_id` 响应约定,请按实际返回对象展示,不要把结果直接当作 `persona_id` 使用。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Persona(歌手人设) (#suno-persona) # Persona > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 基于已有歌曲直接创建可复用的歌手 Persona。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/persona \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "name": "My Persona", "styles": "pop" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/persona" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "name": "My Persona", "styles": "pop" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/persona"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, name: "My Persona", styles: "pop" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/persona" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "name": "My Persona", "styles": "pop", } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/persona"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "name": "My Persona", "styles": "pop" } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "name" => "My Persona", "styles" => "pop" ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/persona") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, name: "My Persona", styles: "pop" } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/persona")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "name": "My Persona", "styles": "pop" ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/persona"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""name"": ""My Persona"", ""styles"": ""pop"" }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/persona"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"name\":\"My Persona\"," "\"styles\":\"pop\"" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/persona"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"name": @"My Persona", @"styles": @"pop" }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/persona" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "name": "My Persona", "styles": "pop" }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/persona'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'name': 'My Persona', 'styles': 'pop' }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/persona" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, name = "My Persona", styles = "pop" ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 Persona 名称;缺失直接返回 `400`。 描述。 风格。 人声片段起点(秒),必须大于等于 0。建议与 `vocal_end_s` 成对提供。 人声片段终点(秒),必须大于起点且不能超过已知源时长。 完成后读取 `result.persona_id`。Persona ID 与自定义模型 ID 不同,不能作为 API 的 `model` 值使用;新流程无需先创建 Vox。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,按 3–5s 间隔轮询 `GET /v1/music/tasks/{task_id}`,直到 `status` 为 `completed` 或 `failed`(通常 30–120s;生成中 `status` 可能为 `pending` 或 `processing`,`progress` 为 0–100 的整数且不保证按固定节点变化)。结果里含 persona 信息。失败时 `data.error.message` 给出原因,且预扣额度自动退回。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ### Extract Vox (#suno-vox) # 提取 Vox(已弃用) > **计费说明**:按路径模型名计费(如 `suno-generation`);任务成功后按实际上游消耗结算(部分工具类按次),失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > - 兼容旧流程的人声片段提取接口;新接入请直接创建 Persona。 - 引用源音轨:`task_id` + `audio_index` 指定,无需记录任何额外 id - 异步任务:提交返回 `task_id`,轮询 `GET /v1/music/tasks/:task_id` 获取结果 **引用源音轨**:基于已有歌曲的操作无需记任何额外 id,只需传 `task_id`(产出源音轨那次任务的 task\_id)+ `audio_index`(结果 `data.result.music[]` 里第几首,1-based,默认 `1`)。 本端点**无版本维度**:不要传 `version`——传了会被丢弃、也不影响计费。 ```bash curl -X POST https://api.seedance.nz/v1/music/generations/vox \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ --data '{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "vocal_start_s": 10, "vocal_end_s": 30 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/vox" payload = { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "vocal_start_s": 10, "vocal_end_s": 30 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/vox"; const payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, vocal_start_s: 10, vocal_end_s: 30 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```go package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.seedance.nz/v1/music/generations/vox" payload := map[string]interface{}{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "vocal_start_s": 10, "vocal_end_s": 30, } jsonData, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) req.Header.Set("Authorization", "Bearer ") req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } ``` ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; public class Main { public static void main(String[] args) throws Exception { String url = "https://api.seedance.nz/v1/music/generations/vox"; String payload = """ { "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "vocal_start_s": 10, "vocal_end_s": 30 } """; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer ") .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(payload)) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } } ``` ```php "suno", "task_id" => "task_01ABC", "audio_index" => 1, "vocal_start_s" => 10, "vocal_end_s" => 30 ]; $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 ", "Content-Type: application/json" ]); $response = curl_exec($ch); curl_close($ch); echo $response; ?> ``` ```ruby require 'net/http' require 'json' require 'uri' url = URI("https://api.seedance.nz/v1/music/generations/vox") payload = { model: "suno", task_id: "task_01ABC", audio_index: 1, vocal_start_s: 10, vocal_end_s: 30 } http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = "Bearer " request["Content-Type"] = "application/json" request.body = payload.to_json response = http.request(request) puts response.body ``` ```swift import Foundation let url = URL(string: "https://api.seedance.nz/v1/music/generations/vox")! let payload: [String: Any] = [ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "vocal_start_s": 10, "vocal_end_s": 30 ] var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer ", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = try? JSONSerialization.data(withJSONObject: payload) let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("Error: \(error)") return } if let data = data, let responseString = String(data: data, encoding: .utf8) { print(responseString) } } task.resume() ``` ```csharp using System; using System.Net.Http; using System.Text; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { var url = "https://api.seedance.nz/v1/music/generations/vox"; var payload = @"{ ""model"": ""suno"", ""task_id"": ""task_01ABC"", ""audio_index"": 1, ""vocal_start_s"": 10, ""vocal_end_s"": 30 }"; using var client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer "); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response = await client.PostAsync(url, content); var result = await response.Content.ReadAsStringAsync(); Console.WriteLine(result); } } ``` ```c #include #include int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { const char *url = "https://api.seedance.nz/v1/music/generations/vox"; const char *payload = "{" "\"model\":\"suno\"," "\"task_id\":\"task_01ABC\"," "\"audio_index\":1," "\"vocal_start_s\":10," "\"vocal_end_s\":30" "}"; struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer "); headers = curl_slist_append(headers, "Content-Type: application/json"); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_slist_free_all(headers); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; } ``` ```objectivec #import int main(int argc, const char * argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"https://api.seedance.nz/v1/music/generations/vox"]; NSDictionary *payload = @{ @"model": @"suno", @"task_id": @"task_01ABC", @"audio_index": @1, @"vocal_start_s": @10, @"vocal_end_s": @30 }; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload options:0 error:&error]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setValue:@"Bearer " forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:jsonData]; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"Error: %@", error); return; } NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@", result); }]; [task resume]; [[NSRunLoop mainRunLoop] run]; } return 0; } ``` ```ocaml (* Requires cohttp and yojson libraries *) open Lwt open Cohttp open Cohttp_lwt_unix let url = "https://api.seedance.nz/v1/music/generations/vox" let payload = {|{ "model": "suno", "task_id": "task_01ABC", "audio_index": 1, "vocal_start_s": 10, "vocal_end_s": 30 }|} let () = let headers = Header.init () |> fun h -> Header.add h "Authorization" "Bearer " |> fun h -> Header.add h "Content-Type" "application/json" in let body = Cohttp_lwt.Body.of_string payload in let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) -> body |> Cohttp_lwt.Body.to_string >|= fun body_str -> print_endline body_str in Lwt_main.run response ``` ```dart import 'dart:convert'; import 'package:http/http.dart' as http; void main() async { final url = Uri.parse('https://api.seedance.nz/v1/music/generations/vox'); final payload = { 'model': 'suno', 'task_id': 'task_01ABC', 'audio_index': 1, 'vocal_start_s': 10, 'vocal_end_s': 30 }; final response = await http.post( url, headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, body: jsonEncode(payload), ); print(response.body); } ``` ```r library(httr) library(jsonlite) url <- "https://api.seedance.nz/v1/music/generations/vox" payload <- list( model = "suno", task_id = "task_01ABC", audio_index = 1, vocal_start_s = 10, vocal_end_s = 30 ) response <- POST( url, add_headers( Authorization = "Bearer ", `Content-Type` = "application/json" ), body = toJSON(payload, auto_unbox = TRUE), encode = "raw" ) cat(content(response, "text")) ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8SGYNNNVBQTXNR4MM964S7K" } ] } ``` ```json { "error": { "code": 400, "message": "请求参数无效", "type": "invalid_request_error" } } ``` ```json { "error": { "code": 401, "message": "身份验证失败,请检查您的API密钥", "type": "authentication_error" } } ``` ```json { "error": { "code": 402, "message": "账户余额不足,请充值后再试", "type": "payment_required" } } ``` ```json { "error": { "code": 403, "message": "访问被禁止,您没有权限访问此资源", "type": "permission_error" } } ``` ```json { "error": { "code": 429, "message": "请求过于频繁,请稍后再试", "type": "rate_limit_error" } } ``` ```json { "error": { "code": 500, "message": "服务器内部错误,请稍后重试", "type": "server_error" } } ``` ```json { "error": { "code": 502, "message": "网关错误,服务器暂时不可用", "type": "bad_gateway" } } ``` ## Authorizations 所有接口均需要使用Bearer Token进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## Body 音频模型。当前传 `suno`(不传默认 `suno`)。 产出源音轨那次任务的 `task_id`。缺失或无法解析源时提交期直接返回 `400`。 引用源任务结果 `data.result.music[]` 中的第几首(1-based;默认 `1`;一次生成通常 2 首:索引 1 与 2)。 截取起点(秒)。 截取终点(秒)。 该功能已弃用。新接入请直接使用 Persona 页面创建 Persona;`vox_audio_id` 不再作为新流程的必填项。 **获取结果**:本接口为异步任务。提交后拿到 `task_id`,轮询 `GET /v1/music/tasks/{task_id}` 直到 `status` 为 `completed` 或 `failed`。新 Persona 流程不依赖该结果。 ## Response 响应状态码 返回数据数组 任务状态 * `submitted` - 已提交 任务唯一标识符(用于轮询 `GET /v1/music/tasks/{task_id}` 获取结果) ## FLOWMUSIC ### 生成音乐 (#flowmusic-music) # 生成音乐 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Flow Music 文字生成音乐。支持风格提示词 / 歌词 / BPM / 时长控制,每次请求生成一首音乐 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "title": "My Song", "sound_prompt": "upbeat pop music with piano", "bpm": "120", "length": 60 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations" payload = { "model": "flowmusic", "title": "My Song", "sound_prompt": "upbeat pop music with piano", "bpm": "120", "length": 60 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations"; const payload = { model: "flowmusic", title: "My Song", sound_prompt: "upbeat pop music with piano", bpm: "120", length: 60 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8AYYM6R03TGZ3Q2P0TZVNPX" } ] } ``` ```json { "error": { "message": "sound_prompt and lyrics cannot both be empty", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 音乐风格或声音描述提示词 示例:`"upbeat pop music with piano"` `sound_prompt` 与 `lyrics` **不可同时为空**(至少传一个)。每次请求仅生成一首音乐。 歌词文本,可先用[生成歌词](#flowmusic-lyrics)接口获得后回填 示例:`"[Verse 1]\n黑夜再长也会天亮\n..."` 生成音乐标题 BPM(每分钟节拍数),必须 ≥ 1 示例:`"120"` 生成时长(秒) 支持范围:`1` \~ `240` 秒 随机种子,用于复现结果 相同的请求下传相同的 seed 值,会生成类似的结果,但不保证完全一致。 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:纯风格提示词生成 ```json { "model": "flowmusic", "title": "My Song", "sound_prompt": "upbeat pop music with piano", "bpm": "120", "length": 60 } ``` ### 场景 2:歌词 + 风格成曲 ```json { "model": "flowmusic", "title": "坚持", "lyrics": "[Verse 1]\n黑夜再长也会天亮\n...", "sound_prompt": "energetic rock with electric guitar", "length": 120 } ``` **查询任务结果** 音乐生成为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVB61E28THHFBSYXWA4FAJ", "status": "completed", "progress": 100, "created": 1783413184, "completed": 1783413236, "actual_time": 52, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c", "title": "Regression Song", "duration_seconds": "181.70666667", "create_time": "2026-07-07T08:33:32.854073Z", "lyrics": "[Verse 1]\nWaking up to the morning light,\n...", "lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1", "lyrics_timing_markers": [[10, 12], [212, 36]], "audio_url": "https://cdn.example.com/audio/flowmusic_a41aade4.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_a41aade4.wav", "image_url": "https://cdn.example.com/image/flowmusic_a41aade4_cover.jpg" } ] } } } ``` ### 生成音乐(Lyria 3.5) (#flowmusic-music-lyria-3-5) # Lyria 3.5 生成音乐 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 使用 Lyria 3.5 进行 Flow Music 文字生成音乐,支持风格提示词、歌词、BPM 和时长控制 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "version": "lyria-3.5", "title": "My Song", "sound_prompt": "upbeat pop music with piano", "bpm": "120", "length": 60 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations" payload = { "model": "flowmusic", "version": "lyria-3.5", "title": "My Song", "sound_prompt": "upbeat pop music with piano", "bpm": "120", "length": 60 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations"; const payload = { model: "flowmusic", version: "lyria-3.5", title: "My Song", sound_prompt: "upbeat pop music with piano", bpm: "120", length: 60 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01K8AYYM6R03TGZ3Q2P0TZVNPX" } ] } ``` ```json { "error": { "message": "sound_prompt and lyrics cannot both be empty", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 模型版本,固定传 `"lyria-3.5"` Lyria 3.5 仍使用 `flowmusic` 作为模型名,不要将 `model` 改为 `lyria-3.5` 或 `flowmusic-lyria-3.5`。 音乐风格或声音描述提示词 示例:`"upbeat pop music with piano"` `sound_prompt` 与 `lyrics` **不可同时为空**(至少传一个)。每次请求仅生成一首音乐。 歌词文本,可先用[生成歌词](#flowmusic-lyrics)接口获得后回填 示例:`"[Verse 1]\n黑夜再长也会天亮\n..."` 生成音乐标题 BPM(每分钟节拍数),必须 ≥ 1 示例:`"120"` 生成时长(秒) 支持范围:`1` \~ `240` 秒 随机种子,用于复现结果 相同的请求下传相同的 seed 值,会生成类似的结果,但不保证完全一致。 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:纯风格提示词生成 ```json { "model": "flowmusic", "version": "lyria-3.5", "title": "My Song", "sound_prompt": "upbeat pop music with piano", "bpm": "120", "length": 60 } ``` ### 场景 2:歌词 + 风格成曲 ```json { "model": "flowmusic", "version": "lyria-3.5", "title": "坚持", "lyrics": "[Verse 1]\n黑夜再长也会天亮\n...", "sound_prompt": "energetic rock with electric guitar", "length": 120 } ``` **查询任务结果** 音乐生成为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVB61E28THHFBSYXWA4FAJ", "status": "completed", "progress": 100, "created": 1783413184, "completed": 1783413236, "actual_time": 52, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c", "title": "Regression Song", "duration_seconds": "181.70666667", "create_time": "2026-07-07T08:33:32.854073Z", "lyrics": "[Verse 1]\nWaking up to the morning light,\n...", "lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1", "lyrics_timing_markers": [[10, 12], [212, 36]], "audio_url": "https://cdn.example.com/audio/flowmusic_a41aade4.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_a41aade4.wav", "image_url": "https://cdn.example.com/image/flowmusic_a41aade4_cover.jpg" } ] } } } ``` ### 生成歌词 (#flowmusic-lyrics) # 生成歌词 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Flow Music 根据提示词生成歌词。结果可回填到生成音乐接口的 lyrics 字段 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/lyrics \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "prompt": "一首关于坚持的摇滚歌曲" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/lyrics" payload = { "model": "flowmusic", "prompt": "一首关于坚持的摇滚歌曲" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/lyrics"; const payload = { model: "flowmusic", prompt: "一首关于坚持的摇滚歌曲" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVCX91HYHSTHZ0NC1SRFW1" } ] } ``` ```json { "error": { "message": "model is required", "type": "invalid_request", "param": "", "code": "model_required" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 生成歌词的提示词,**≤ 3000 字符** 建议描述歌曲主题、风格、情绪等,以获得更贴合的歌词 示例:`"一首关于坚持的摇滚歌曲"` ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:按主题生成歌词 ```json { "model": "flowmusic", "prompt": "一首关于坚持的摇滚歌曲" } ``` ### 场景 2:歌词回填成曲 先生成歌词,完成后取 `result.lyrics[0]` 的 `title` 和 `lyrics`,回填到[生成音乐](#flowmusic-music)接口: ```json { "model": "flowmusic", "title": "坚持", "lyrics": "[Verse 1]\n黑夜再长也会天亮\n...", "sound_prompt": "energetic rock with electric guitar" } ``` **查询任务结果** 歌词生成为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVCX91HYHSTHZ0NC1SRFW1", "status": "completed", "progress": 100, "created": 1783413241, "completed": 1783413284, "actual_time": 43, "cost": 0.016, "credits_cost": 0.16, "result": { "lyrics": [ { "title": "Bleached", "lyrics": "[Intro]\n(Check)\n(One two)\n\n[Verse 1]\nThe birds are..." } ] } } } ``` ### 续写音乐 (#flowmusic-extend) # 音乐延伸 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Flow Music 对已生成的音频续写。从指定时间点开始,按编辑指令延伸音乐 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/extend \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "clip_id": "abc123-def456", "extend_from_s": 30, "extend_s": 60, "instruction": "延续主歌旋律,加入弦乐" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/extend" payload = { "model": "flowmusic", "clip_id": "abc123-def456", "extend_from_s": 30, "extend_s": 60, "instruction": "延续主歌旋律,加入弦乐" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/extend"; const payload = { model: "flowmusic", clip_id: "abc123-def456", extend_from_s: 30, extend_s: 60, instruction: "延续主歌旋律,加入弦乐" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVCYB70YJ1WY9X22RVYRNP" } ] } ``` ```json { "error": { "message": "clip_id is required", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 源音乐 clip\_id,来自已成功任务的 `result.music[].clip_id` 源任务必须已成功。外部音频可先通过[上传音频](#flowmusic-upload-audio)导入换取 clip\_id。 开始续写的时间点(秒) 不能超过源 clip 时长 续写时长(秒) 最大值:`164` 秒 续写音乐的编辑指令 示例:`"延续主歌旋律,加入弦乐"` 续写后音乐标题 随机种子,用于复现结果 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:从副歌处续写 60 秒 ```json { "model": "flowmusic", "clip_id": "abc123-def456", "extend_from_s": 30, "extend_s": 60, "instruction": "延续主歌旋律,加入弦乐" } ``` **查询任务结果** 音乐延伸为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。延伸产物是**新的** `clip_id`,后续操作请使用新 clip\_id。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVCYB70YJ1WY9X22RVYRNP", "status": "completed", "progress": 100, "created": 1783413242, "completed": 1783413292, "actual_time": 50, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "d2f589ea-5390-4e83-8e2f-4517420408fa", "title": "Untitled (Extended)", "duration_seconds": "39.95733333", "create_time": "2026-07-07T08:34:33.240020Z", "lyrics": "waking up to the morning light,\n...", "lyrics_id": "0452451b-9e54-5d9f-8437-8bff97c7bbc8", "lyrics_timing_markers": [[0, 12], [129, 20]], "audio_url": "https://cdn.example.com/audio/flowmusic_d2f589ea.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_d2f589ea.wav", "image_url": "https://cdn.example.com/image/flowmusic_d2f589ea_cover.jpg" } ] } } } ``` ### 续写音乐(Lyria 3.5) (#flowmusic-extend-lyria-3-5) # Lyria 3.5 音乐延伸 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 使用 Lyria 3.5 从指定时间点延伸已生成的音乐 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/extend \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "extend_from_s": 30, "extend_s": 60, "instruction": "延续主歌旋律,加入弦乐" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/extend" payload = { "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "extend_from_s": 30, "extend_s": 60, "instruction": "延续主歌旋律,加入弦乐" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/extend"; const payload = { model: "flowmusic", version: "lyria-3.5", clip_id: "abc123-def456", extend_from_s: 30, extend_s: 60, instruction: "延续主歌旋律,加入弦乐" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVCYB70YJ1WY9X22RVYRNP" } ] } ``` ```json { "error": { "message": "clip_id is required", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 模型版本,固定传 `"lyria-3.5"` Lyria 3.5 仍使用 `flowmusic` 作为模型名,不要将 `model` 改为 `lyria-3.5` 或 `flowmusic-lyria-3.5`。 源音乐 clip\_id,来自已成功任务的 `result.music[].clip_id` 源任务必须已成功。外部音频可先通过[上传音频](#flowmusic-upload-audio)导入换取 clip\_id。 开始续写的时间点(秒) 不能超过源 clip 时长 续写时长(秒) 最大值:`164` 秒 续写音乐的编辑指令 示例:`"延续主歌旋律,加入弦乐"` 续写后音乐标题 随机种子,用于复现结果 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:从副歌处续写 60 秒 ```json { "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "extend_from_s": 30, "extend_s": 60, "instruction": "延续主歌旋律,加入弦乐" } ``` **查询任务结果** 音乐延伸为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。延伸产物是**新的** `clip_id`,后续操作请使用新 clip\_id。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVCYB70YJ1WY9X22RVYRNP", "status": "completed", "progress": 100, "created": 1783413242, "completed": 1783413292, "actual_time": 50, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "d2f589ea-5390-4e83-8e2f-4517420408fa", "title": "Untitled (Extended)", "duration_seconds": "39.95733333", "create_time": "2026-07-07T08:34:33.240020Z", "lyrics": "waking up to the morning light,\n...", "lyrics_id": "0452451b-9e54-5d9f-8437-8bff97c7bbc8", "lyrics_timing_markers": [[0, 12], [129, 20]], "audio_url": "https://cdn.example.com/audio/flowmusic_d2f589ea.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_d2f589ea.wav", "image_url": "https://cdn.example.com/image/flowmusic_d2f589ea_cover.jpg" } ] } } } ``` ### 替换片段 (#flowmusic-replace) # 片段替换 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Flow Music 替换已生成音频中的某一段。按编辑指令重新生成 start_s 到 end_s 之间的片段 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/replace \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "clip_id": "abc123-def456", "start_s": 10, "end_s": 20, "instruction": "替换为钢琴版本" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/replace" payload = { "model": "flowmusic", "clip_id": "abc123-def456", "start_s": 10, "end_s": 20, "instruction": "替换为钢琴版本" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/replace"; const payload = { model: "flowmusic", clip_id: "abc123-def456", start_s: 10, end_s: 20, instruction: "替换为钢琴版本" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVHGTG5JM33S8FG1K90YQ6" } ] } ``` ```json { "error": { "message": "end_s must be greater than start_s", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 源音乐 clip\_id,来自已成功任务的 `result.music[].clip_id` 替换开始时间(秒) 替换结束时间(秒) `end_s` 必须大于 `start_s`,且不能超过源 clip 时长。 替换片段的编辑指令 示例:`"替换为钢琴版本"` 替换后音乐标题 随机种子,用于复现或控制生成结果 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:把 10-20 秒替换为钢琴版本 ```json { "model": "flowmusic", "clip_id": "abc123-def456", "start_s": 10, "end_s": 20, "instruction": "替换为钢琴版本" } ``` **查询任务结果** 片段替换为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。替换产物是**新的** `clip_id`(整首歌重新输出,其中指定区间已被替换),后续操作请使用新 clip\_id。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVHGTG5JM33S8FG1K90YQ6", "status": "completed", "progress": 100, "created": 1783413392, "completed": 1783413454, "actual_time": 62, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "9508d1fe-633e-464b-8a40-c6368e5464fa", "title": "Untitled (Replaced)", "duration_seconds": "181.58933333", "create_time": "2026-07-07T08:37:13.864452Z", "lyrics": "[Verse 1]\nWaking up to the morning light,\n...", "lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1", "lyrics_timing_markers": [[10, 12], [71, 15]], "audio_url": "https://cdn.example.com/audio/flowmusic_9508d1fe.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_9508d1fe.wav", "image_url": "https://cdn.example.com/image/flowmusic_9508d1fe_cover.jpg" } ] } } } ``` ### 替换片段(Lyria 3.5) (#flowmusic-replace-lyria-3-5) # Lyria 3.5 片段替换 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 使用 Lyria 3.5 替换已生成音频中的指定片段 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/replace \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "start_s": 10, "end_s": 20, "instruction": "替换为钢琴版本" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/replace" payload = { "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "start_s": 10, "end_s": 20, "instruction": "替换为钢琴版本" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/replace"; const payload = { model: "flowmusic", version: "lyria-3.5", clip_id: "abc123-def456", start_s: 10, end_s: 20, instruction: "替换为钢琴版本" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVHGTG5JM33S8FG1K90YQ6" } ] } ``` ```json { "error": { "message": "end_s must be greater than start_s", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 模型版本,固定传 `"lyria-3.5"` Lyria 3.5 仍使用 `flowmusic` 作为模型名,不要将 `model` 改为 `lyria-3.5` 或 `flowmusic-lyria-3.5`。 源音乐 clip\_id,来自已成功任务的 `result.music[].clip_id` 替换开始时间(秒) 替换结束时间(秒) `end_s` 必须大于 `start_s`,且不能超过源 clip 时长。 替换片段的编辑指令 示例:`"替换为钢琴版本"` 替换后音乐标题 随机种子,用于复现或控制生成结果 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:把 10-20 秒替换为钢琴版本 ```json { "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "start_s": 10, "end_s": 20, "instruction": "替换为钢琴版本" } ``` **查询任务结果** 片段替换为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。替换产物是**新的** `clip_id`(整首歌重新输出,其中指定区间已被替换),后续操作请使用新 clip\_id。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVHGTG5JM33S8FG1K90YQ6", "status": "completed", "progress": 100, "created": 1783413392, "completed": 1783413454, "actual_time": 62, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "9508d1fe-633e-464b-8a40-c6368e5464fa", "title": "Untitled (Replaced)", "duration_seconds": "181.58933333", "create_time": "2026-07-07T08:37:13.864452Z", "lyrics": "[Verse 1]\nWaking up to the morning light,\n...", "lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1", "lyrics_timing_markers": [[10, 12], [71, 15]], "audio_url": "https://cdn.example.com/audio/flowmusic_9508d1fe.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_9508d1fe.wav", "image_url": "https://cdn.example.com/image/flowmusic_9508d1fe_cover.jpg" } ] } } } ``` ### 整曲翻唱 (#flowmusic-cover) # Cover 改编 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Flow Music 对整首歌做风格改编(翻唱 / 改风格),strength 控制编辑强度 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/cover \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "clip_id": "abc123-def456", "instruction": "将这首歌曲改为爵士风格", "strength": 0.5 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/cover" payload = { "model": "flowmusic", "clip_id": "abc123-def456", "instruction": "将这首歌曲改为爵士风格", "strength": 0.5 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/cover"; const payload = { model: "flowmusic", clip_id: "abc123-def456", instruction: "将这首歌曲改为爵士风格", strength: 0.5 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVD0E653EZ9FWD2SD9NNB6" } ] } ``` ```json { "error": { "message": "strength must be between 0 and 1", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 源音乐的唯一标识符,来自已成功任务的 `result.music[].clip_id` Cover 编辑指令 示例:`"将这首歌曲改为爵士风格"` 编辑强度 取值范围:`0` \~ `1`,越大改动越大 Cover 后的音乐标题 随机种子,用于结果复现 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:整曲改为爵士风格 ```json { "model": "flowmusic", "clip_id": "abc123-def456", "instruction": "将这首歌曲改为爵士风格", "strength": 0.5 } ``` ### 场景 2:外部音频导入后改编 先通过[上传音频](#flowmusic-upload-audio)把外部音频导入换取 clip\_id,再做 Cover: ```json { "model": "flowmusic", "clip_id": "1db3a20f-4ddc-44e8-8c9c-6c9093c16ffe", "instruction": "改成爵士风格", "strength": 0.6 } ``` **查询任务结果** Cover 改编为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。Cover 产物是**新的** `clip_id`,后续操作请使用新 clip\_id。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVD0E653EZ9FWD2SD9NNB6", "status": "completed", "progress": 100, "created": 1783413244, "completed": 1783413315, "actual_time": 71, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "ef3d804e-fa97-402f-ba17-4ff08270159b", "title": "Untitled (Cover)", "duration_seconds": "178.03733333", "create_time": "2026-07-07T08:34:58.112190Z", "lyrics": "[Verse 1]\nWaking up to the morning light,\n...", "lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1", "lyrics_timing_markers": [[10, 12], [212, 36]], "audio_url": "https://cdn.example.com/audio/flowmusic_ef3d804e.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_ef3d804e.wav", "image_url": "https://cdn.example.com/image/flowmusic_ef3d804e_cover.jpg" } ] } } } ``` ### 整曲翻唱(Lyria 3.5) (#flowmusic-cover-lyria-3-5) # Lyria 3.5 Cover 改编 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 使用 Lyria 3.5 对整首音乐进行风格改编 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/cover \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "instruction": "将这首歌曲改为爵士风格", "strength": 0.5 }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/cover" payload = { "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "instruction": "将这首歌曲改为爵士风格", "strength": 0.5 } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/cover"; const payload = { model: "flowmusic", version: "lyria-3.5", clip_id: "abc123-def456", instruction: "将这首歌曲改为爵士风格", strength: 0.5 }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVD0E653EZ9FWD2SD9NNB6" } ] } ``` ```json { "error": { "message": "strength must be between 0 and 1", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 模型版本,固定传 `"lyria-3.5"` Lyria 3.5 仍使用 `flowmusic` 作为模型名,不要将 `model` 改为 `lyria-3.5` 或 `flowmusic-lyria-3.5`。 源音乐的唯一标识符,来自已成功任务的 `result.music[].clip_id` Cover 编辑指令 示例:`"将这首歌曲改为爵士风格"` 编辑强度 取值范围:`0` \~ `1`,越大改动越大 Cover 后的音乐标题 随机种子,用于结果复现 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:整曲改为爵士风格 ```json { "model": "flowmusic", "version": "lyria-3.5", "clip_id": "abc123-def456", "instruction": "将这首歌曲改为爵士风格", "strength": 0.5 } ``` ### 场景 2:外部音频导入后改编 先通过[上传音频](#flowmusic-upload-audio)把外部音频导入换取 clip\_id,再做 Cover: ```json { "model": "flowmusic", "version": "lyria-3.5", "clip_id": "1db3a20f-4ddc-44e8-8c9c-6c9093c16ffe", "instruction": "改成爵士风格", "strength": 0.6 } ``` **查询任务结果** Cover 改编为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。Cover 产物是**新的** `clip_id`,后续操作请使用新 clip\_id。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVD0E653EZ9FWD2SD9NNB6", "status": "completed", "progress": 100, "created": 1783413244, "completed": 1783413315, "actual_time": 71, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "ef3d804e-fa97-402f-ba17-4ff08270159b", "title": "Untitled (Cover)", "duration_seconds": "178.03733333", "create_time": "2026-07-07T08:34:58.112190Z", "lyrics": "[Verse 1]\nWaking up to the morning light,\n...", "lyrics_id": "c302d603-81b6-552f-8122-e512928d6aa1", "lyrics_timing_markers": [[10, 12], [212, 36]], "audio_url": "https://cdn.example.com/audio/flowmusic_ef3d804e.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_ef3d804e.wav", "image_url": "https://cdn.example.com/image/flowmusic_ef3d804e_cover.jpg" } ] } } } ``` ### 分离人声与伴奏 (#flowmusic-stems) # 词曲分离 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Flow Music 分离人声 / 伴奏音轨,结果为 zip 分轨包 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/stems \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "clip_id": "abc123-def456" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/stems" payload = { "model": "flowmusic", "clip_id": "abc123-def456" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/stems"; const payload = { model: "flowmusic", clip_id: "abc123-def456" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVD1EFXYEHDJ8M0XNJ65AR" } ] } ``` ```json { "error": { "message": "clip_id is required", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 需要分离音轨的音乐 clip\_id,来自已成功任务的 `result.music[].clip_id` ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:分离人声与伴奏 ```json { "model": "flowmusic", "clip_id": "abc123-def456" } ``` **查询任务结果** 词曲分离为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。分离结果是**一个 zip 打包文件**(`result.music[0].file_url`,约 20MB),内含人声 / 伴奏等分轨音频,提供下载即可。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVD1EFXYEHDJ8M0XNJ65AR", "status": "completed", "progress": 100, "created": 1783413245, "completed": 1783413331, "actual_time": 86, "cost": 0.048, "credits_cost": 0.48, "result": { "music": [ { "clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c", "file_url": "https://cdn.example.com/audio/flowmusic_a41aade4_stems.zip", "url": "https://cdn.example.com/audio/flowmusic_a41aade4_stems.zip", "mime_type": "application/zip", "size_bytes": 20323367 } ] } } } ``` ### 上传音频 (#flowmusic-upload-audio) # 上传音频 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 把外部音频导入 Flow Music,换取 clip_id 供后续延伸 / 替换 / Cover / 分离使用 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/upload-audio \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "audio_url": "https://example.com/audio.mp3" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/upload-audio" payload = { "model": "flowmusic", "audio_url": "https://example.com/audio.mp3" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/upload-audio"; const payload = { model: "flowmusic", audio_url: "https://example.com/audio.mp3" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVD2FC61SYZ5103Z4XCCS5" } ] } ``` ```json { "error": { "message": "audio_url is required", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 待上传音频文件地址,需公网可访问 仅支持常见音频文件后缀(如 `.mp3` / `.wav`)。 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:导入外部音频换取 clip\_id ```json { "model": "flowmusic", "audio_url": "https://example.com/audio.mp3" } ``` 完成后从 `result.music[0].clip_id` 取导入产物的 clip\_id,即可用于[延伸](#flowmusic-extend) / [替换](#flowmusic-replace) / [Cover](#flowmusic-cover) / [分离](#flowmusic-stems)。 **查询任务结果** 上传音频为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVD2FC61SYZ5103Z4XCCS5", "status": "completed", "progress": 100, "created": 1783413246, "completed": 1783413282, "actual_time": 36, "cost": 0.008, "credits_cost": 0.08, "result": { "music": [ { "clip_id": "1db3a20f-4ddc-44e8-8c9c-6c9093c16ffe", "audio_url": "https://cdn.example.com/audio/flowmusic_1db3a20f_upload_audio.wav", "url": "https://cdn.example.com/audio/flowmusic_1db3a20f_upload_audio.wav" } ] } } } ``` ### 下载音频 (#flowmusic-download-audio) # 下载音频 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Flow Music 将 clip 转出为指定格式(wav / mp3)的音频文件 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/download-audio \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "clip_id": "abc123-def456", "format": "wav" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/download-audio" payload = { "model": "flowmusic", "clip_id": "abc123-def456", "format": "wav" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/download-audio"; const payload = { model: "flowmusic", clip_id: "abc123-def456", format: "wav" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVD3FPYYQPJ2N87XXE5NQG" } ] } ``` ```json { "error": { "message": "format must be one of: wav, mp3", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 需要下载的音乐 clip\_id,来自已成功任务的 `result.music[].clip_id` 下载格式 可选值: * `mp3` - 有损压缩,体积小 * `wav` - 无损,适合后期制作 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:转出无损 wav ```json { "model": "flowmusic", "clip_id": "abc123-def456", "format": "wav" } ``` **查询任务结果** 下载音频为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。结果统一在 `result.music[0].audio_url`(`url` 同值),`format` / `mime_type` 字段标识实际格式。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVD3FPYYQPJ2N87XXE5NQG", "status": "completed", "progress": 100, "created": 1783413247, "completed": 1783413296, "actual_time": 49, "cost": 0.016, "credits_cost": 0.16, "result": { "music": [ { "clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c", "format": "wav", "mime_type": "audio/wav", "size_bytes": 34900726, "audio_url": "https://cdn.example.com/audio/flowmusic_a41aade4_download_audio.wav", "url": "https://cdn.example.com/audio/flowmusic_a41aade4_download_audio.wav" } ] } } } ``` ### 生成视频片段 (#flowmusic-video-clip) # 音乐视频渲染 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > Flow Music 按模板把音乐渲染成 mp4 视频,支持 simple / modern / player 三种预设 ```bash curl --request POST \ --url https://api.seedance.nz/v1/music/generations/video-clip \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "flowmusic", "clip_id": "abc123-def456", "preset": "modern" }' ``` ```python import requests url = "https://api.seedance.nz/v1/music/generations/video-clip" payload = { "model": "flowmusic", "clip_id": "abc123-def456", "preset": "modern" } headers = { "Authorization": "Bearer ", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = "https://api.seedance.nz/v1/music/generations/video-clip"; const payload = { model: "flowmusic", clip_id: "abc123-def456", preset: "modern" }; const headers = { "Authorization": "Bearer ", "Content-Type": "application/json" }; fetch(url, { method: "POST", headers: headers, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ```json { "code": 200, "data": [ { "status": "submitted", "task_id": "task_01KWXVD4HQEEY7B5NJ31177Q1H" } ] } ``` ```json { "error": { "message": "clip_id is required", "type": "invalid_request", "param": "", "code": "invalid_request" } } ``` ```json { "error": { "message": "余额不足", "type": "invalid_request", "param": "", "code": "quota_not_enough" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 认证 所有接口均需要使用 Bearer Token 进行认证 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key 使用时在请求头中添加: ``` Authorization: Bearer YOUR_API_KEY ``` ## 请求参数 模型名称,**固定传 `"flowmusic"`**(大小写不敏感) 需要生成视频的音乐 clip\_id,来自已成功任务的 `result.music[].clip_id` 视频模板预设 可选值: * `simple` - 简洁模板 * `modern` - 现代风格模板 * `player` - 播放器风格模板 ## 响应 响应状态码,成功时为 200 返回数据数组 任务状态,初始提交时为 `submitted` 任务唯一标识符,用于查询任务状态和结果 ## 使用场景 ### 场景 1:用 modern 模板渲染音乐视频 ```json { "model": "flowmusic", "clip_id": "abc123-def456", "preset": "modern" } ``` **查询任务结果** 音乐视频渲染为异步任务,提交后会返回 `task_id`。使用 [获取任务状态](#flowmusic-query) 接口查询生成进度和结果。结果在 `result.music[0].video_url`。 ## 任务完成结果示例 **查询返回示例**(`GET /v1/music/tasks/{task_id}`): ```json { "code": 200, "data": { "id": "task_01KWXVD4HQEEY7B5NJ31177Q1H", "status": "completed", "progress": 100, "created": 1783413248, "completed": 1783413327, "actual_time": 79, "cost": 0.016, "credits_cost": 0.16, "result": { "music": [ { "clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c", "video_url": "https://cdn.example.com/video/flowmusic_a41aade4_video_clip.mp4", "url": "https://cdn.example.com/video/flowmusic_a41aade4_video_clip.mp4" } ] } } } ``` ### 任务查询 (#flowmusic-query) # 查询任务 > **计费说明**:按路径 SKU 计费(例如 `flowmusic-generation`);任务成功后按实际上游消耗结算,失败全额退款;金额以控制台预估 / 实扣为准。轮询 `GET /v1/music/tasks/{task_id}`。 > 查询 Flow Music 异步任务的执行状态、进度和生成结果 ```bash curl --request GET \ --url https://api.seedance.nz/v1/music/tasks/task_01K8AYYM6R03TGZ3Q2P0TZVNPX?language=zh \ --header 'Authorization: Bearer ' ``` ```python import requests task_id = "task_01K8AYYM6R03TGZ3Q2P0TZVNPX" url = f"https://api.seedance.nz/v1/music/tasks/{task_id}" headers = { "Authorization": "Bearer " } params = { "language": "zh" } response = requests.get(url, headers=headers, params=params) print(response.json()) ``` ```javascript const taskId = "task_01K8AYYM6R03TGZ3Q2P0TZVNPX"; const url = `https://api.seedance.nz/v1/music/tasks/${taskId}?language=zh`; const headers = { "Authorization": "Bearer " }; fetch(url, { method: "GET", headers: headers }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error("Error:", error)); ``` ```json { "code": 200, "data": { "id": "task_01K8AYYM6R03TGZ3Q2P0TZVNPX", "status": "completed", "progress": 100, "created": 1783413241, "completed": 1783413352, "actual_time": 111, "cost": 0.06, "credits_cost": 0.6, "result": { "music": [ { "clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c", "title": "My Song", "duration_seconds": "181.70666667", "audio_url": "https://cdn.example.com/audio/flowmusic_a41aade4.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_a41aade4.wav" } ] } } } ``` ```json { "error": { "message": "task not found", "type": "invalid_request", "param": "task_id", "code": "task_not_found" } } ``` ```json { "error": { "message": "当前分组容量饱和,请稍后重试", "type": "rate_limit_error", "param": "", "code": "rate_limit_error" } } ``` ## 鉴权 所有 Flow Music 接口都需要 Bearer Token 鉴权 获取 API Key: 登录 [控制台](https://api.seedance.nz) →「API 令牌」获取 API Key。 添加到请求头: ``` Authorization: Bearer YOUR_API_KEY ``` ## 路径参数 提交 Flow Music 任务后返回的任务 ID 任务 ID 来自提交接口响应中的 `data[0].task_id`。 ## 查询参数 错误信息和部分提示文案的语言 可选值:`zh`、`en`、`ja`、`ko` ## 响应字段 响应状态码,成功时为 200 任务详情 任务 ID 任务状态:`pending`、`processing`、`completed`、`failed` 任务进度,范围 0-100 实际扣费金额;任务失败时通常为 0 实际消耗的 credits 任务完成后的生成结果;不同 Flow Music 能力返回的字段不同 ## 结果结构 ### 音乐类任务 生成音乐、音乐延伸、片段替换、Cover 改编、词曲分离、上传音频、下载音频和视频渲染通常返回 `result.music` 数组。 ```json { "result": { "music": [ { "clip_id": "a41aade4-993e-4d28-b56f-d97e7ef7167c", "audio_url": "https://cdn.example.com/audio/flowmusic_a41aade4.m4a", "wav_url": "https://cdn.example.com/audio/flowmusic_a41aade4.wav", "video_url": "https://cdn.example.com/video/flowmusic_a41aade4.mp4", "file_url": "https://cdn.example.com/audio/flowmusic_a41aade4_stems.zip" } ] } } ``` ### 歌词任务 生成歌词返回 `result.lyrics` 数组。 ```json { "result": { "lyrics": [ { "title": "Bleached", "lyrics": "[Intro]\n(Check)\n(One two)\n..." } ] } } ``` ## 使用说明 Flow Music 提交接口都是异步任务。提交成功后先获取 `task_id`,再调用本接口轮询任务状态;当 `status` 为 `completed` 时,从 `result` 中读取生成结果。 # MiniMax-H3 API `MiniMax-H3` 使用 MiniMax V2 的请求和任务响应格式,提供视频生成能力。Base URL 为 `https://api.seedance.nz`,鉴权使用本站 API Key:`Authorization: Bearer `。从 MiniMax V2 客户端迁移时,替换 Base URL 和 API Key,并按下面的能力范围调整请求。 机器可读定义:[OpenAPI JSON](minimax-h3-openapi.json)。完整指南和接口定义可从 `/docs/minimax-h3-api.md` 和 `/docs/minimax-h3-openapi.json` 下载。 ## 能力与兼容范围 | 项目 | 本接口 | | --- | --- | | 模型名称 | `MiniMax-H3`,区分大小写 | | 文生视频 | 支持,至少一个非空 `text` 内容项;拼接后提示词最多 10000 字符 | | 参考素材视频 | 最多 9 张参考图片、3 条参考音频、3 条参考视频,可组合使用 | | 独立驱动音频 | 额外 1 条 `drive_audio`,与 3 条参考音频分开计数 | | 分辨率 | `480P` / `768P` / `1080P`,也接受小写 | | 时长 | 普通请求整数 4–15 秒;含驱动音频请求整数 4–60 秒 | | 输出 | 一个视频 URL;最终文件应由调用方及时保存 | | 首帧、尾帧、首尾帧 | 支持单独 `first_frame`、单独 `last_frame` 或同时提供两者,按专用关键帧模式执行 | | 混合关键帧与参考素材 | 支持关键帧与参考图、音频、视频或驱动音频组合;各类上限独立计数,属于本服务扩展 | | 2K、MiniMax-H3-Max、Context-IR、视频再生成 | 不属于此模型接口 | 官方当前 MiniMax-H3 的分辨率范围是 `768P` / `2K`、时长为 4–15 秒。本服务的 `480P`、`1080P`、`drive_audio`、`audio_control`、视频起始偏移、`2:3` / `3:2` 比例、混合关键帧与参考素材及长驱动音频任务属于扩展。参考站 H3 Gateway 的 `/v1/videos`、`target`、`conditions`、OSS 预签名 PUT 是另一套 SPI,不能直接作为本接口请求体。 ## 价格 按提交请求的输出时长计费,标准零售价如下。参考图片、音频、视频不另加输入费用。 | 分辨率 | 元/秒 | 5 秒 | 10 秒 | 15 秒 | 60 秒驱动音频 | | --- | ---: | ---: | ---: | ---: | ---: | | 480P | 0.15 | 0.75 | 1.50 | 2.25 | 9.00 | | 768P | 0.30 | 1.50 | 3.00 | 4.50 | 18.00 | | 1080P | 0.45 | 2.25 | 4.50 | 6.75 | 27.00 | 1080P 保留工作流原生对齐尺寸:16:9 输出 1920×1088,其他比例短边同样为 1088 像素。 提交时预扣,任务失败释放相应预扣额度。删除已完成任务的记录不会退款;取消请求返回错误时,原任务继续执行和结算。账户实际价格以控制台适用的分组及折扣为准。 ## 接口 | 方法 | 路径 | 成功响应 | | --- | --- | --- | | POST | `/v2/video_generation` | `{"task_id":"..."}` | | GET | `/v2/query/video_generation/{task_id}` | `{"task":{...}}` | | GET | `/v2/query/video_generation` | `{"items":[...],"total":1}` | | DELETE | `/v2/video_generation/{task_id}` | `{"task_id":"...","action":"deleted","status":"deleted"}` | | POST | `/v1/files/upload` | 本站通用素材上传接口,返回 URL 后填入内容项 | 所有任务操作都使用当前 API Key 对应的账户和租户权限。任务 ID 不等于访问授权。已有 `/v1/video/generations` 入口继续提供本站通用视频协议;MiniMax V2 客户端请使用本节的 `/v2/` 路径。 ## 创建任务 请求头:`Content-Type: application/json`。 | 字段 | 类型 | 要求 | | --- | --- | --- | | `model` | string | 必填,`MiniMax-H3` | | `content` | array | 必填,至少一个非空 `text` 项;多段文字按顺序拼接,总计不超过 10000 字符 | | `resolution` | string | 必填,`480P`、`768P` 或 `1080P` | | `duration` | integer | 必填,普通 4–15;有 `drive_audio` 时 4–60 | | `ratio` | string | 纯文本必填;参考请求省略时采用 `16:9`;关键帧请求可自适应,见下文 | | `audio_control` | object | 可选扩展,包含 `mode`、`denoise_strength`、`add_drive_as_reference` | | `callback_url` | string | 可选 HTTPS 地址,仅 443 端口;省略则通过查询接口轮询 | 支持的固定比例依次为 `1:1`、`2:3`、`3:2`、`3:4`、`4:3`、`9:16`、`16:9`、`21:9`,其中 `2:3`、`3:2` 是扩展比例。纯文本请求必须填写比例。参考请求省略时采用 `16:9`,显式传 `adaptive` 或 `auto` 会报错;这与官方参考模式默认 `adaptive` 不同。关键帧请求可指定固定比例,或省略/使用 `adaptive`(也接受扩展别名 `auto`)读取首帧图比例,仅有尾帧时读取尾帧,并选择 最接近的固定画幅;任务结果返回实际采用的比例。本服务会执行关键帧请求指定的固定比例,而官方会忽略它并使用自适应,因此这部分行为有差异。 内容项格式: ```json {"type":"text","text":"电影感镜头,人物向镜头挥手。"} ``` ```json {"type":"image_url","image_url":{"url":"https://example.com/person.jpg"},"role":"reference_image"} ``` ```json {"type":"video_url","video_url":{"url":"https://example.com/motion.mp4"},"role":"reference_video"} ``` ```json {"type":"audio_url","audio_url":{"url":"https://example.com/voice.wav"},"role":"reference_audio"} ``` ```json {"type":"audio_url","audio_url":{"url":"https://example.com/dialogue.wav"},"role":"drive_audio"} ``` 参考图片必须明确使用 `reference_image`。省略图片角色时按官方规则等同 `first_frame`;省略音频/视频角色时分别等同 `reference_audio` / `reference_video`。本服务允许首帧、尾帧与参考图片、参考音频、参考视频及驱动音频混用,按实际内容自动选择混合模式,无需填写 `task_type`。关键帧最多各 1 张,额外参考图最多 9 张,其他类别也按各自上限独立计数。这是本服务扩展;官方 V2 将关键帧与参考素材定义为互斥场景。 参考视频内容项还支持扩展字段 `start_time_seconds`(非负秒数,默认 0),放在 `role` 同级;服务按 24 FPS 换算起始帧。例如 2.5 秒对应跳过 60 帧。图片和音频不提供这个裁剪参数。 ### 文生视频 ```bash export API_KEY='YOUR_API_KEY' export BASE_URL='https://api.seedance.nz' curl "$BASE_URL/v2/video_generation" \ -H "Authorization: Bearer $API_KEY" \ -H 'Content-Type: application/json' \ -d '{ "model": "MiniMax-H3", "content": [{"type":"text","text":"航拍薄雾中的山谷,晨光穿过树梢,镜头平稳前进。"}], "resolution": "480P", "duration": 5, "ratio": "16:9" }' ``` HTTP 200 表示已接受任务,不表示视频已完成: ```json {"task_id":"task_example"} ``` ### 首帧、尾帧与首尾帧 ```json { "model":"MiniMax-H3", "content":[ {"type":"text","text":"人物从首帧姿态自然转身,平稳过渡至尾帧构图。"}, {"type":"image_url","image_url":{"url":"https://example.com/start.jpg"},"role":"first_frame"}, {"type":"image_url","image_url":{"url":"https://example.com/end.jpg"},"role":"last_frame"} ], "resolution":"768P", "duration":5, "ratio":"adaptive" } ``` 省略尾帧项即为首帧生成;省略首帧项即为尾帧生成。首帧和尾帧最多各一张,角色决定用途,不依赖它们在数组中的顺序。自适应会选择最接近输入图的固定比例,而不是保证任意比例的原尺寸输出。 ### 多模态参考 ```json { "model":"MiniMax-H3", "content":[ {"type":"text","text":"保持参考图人物的外貌,参考视频中的镜头运动,使用参考音频的声音风格。"}, {"type":"image_url","image_url":{"url":"https://example.com/person.jpg"},"role":"reference_image"}, {"type":"video_url","video_url":{"url":"https://example.com/motion.mp4"},"role":"reference_video"}, {"type":"audio_url","audio_url":{"url":"https://example.com/voice.wav"},"role":"reference_audio"} ], "resolution":"768P", "duration":10, "ratio":"16:9" } ``` ### 驱动音频与声音参考 `reference_audio` 提供声音参考;`drive_audio` 提供目标音频驱动。音色参考不等于强制按照音频逐字对口型。需要按台词生成时,在文字提示中同时写出明文台词。 ```json { "model":"MiniMax-H3", "content":[ {"type":"text","text":"参考图中的人物正对镜头,口型跟随