测试账号

接入联调期间,我们将为您提供一个测试账号。 它和正式账号跑的是同一套接口、同一批字段、同一套错误码、同一套计费逻辑, 唯一的区别是生成任务调用总是返回固定的视频—— 返回的内容来自我们对真实上游响应的录制。 所以你可以随便跑、反复跑、把失败分支挨个跑一遍,不产生任何费用,也不需要先充值。

和正式账号的差别,就这几条

测试账号正式账号
接口地址、请求体、响应字段完全相同
状态机、错误码、HTTP 状态码完全相同
计费档位、单价、计费秒数完全相同
账单金额cost.amount 恒为 "0.00",并带 cost.sandbox: true;不扣余额、不进账单按档位单价结算
余额不需要充值;余额为 0 也能提交(控制台的"余额低"提示可以忽略)提交前预检余额,不足返回 402
视频内容固定样片(每个模型一段 720p 短片)你的提示词生成的视频
可调模型seedance-2.0-custom · seedance-2.0-fast-custom · seedance-2.5-custom(用你的 key 调 GET /api/v1/models 看到的就是这三个)目录里的全部模型
参数组合模型支持的全部都能提交;画面不随之变化,字段随之变化模型支持的全部

正式使用时我们可以无缝切换到线上模式,你的代码、密钥、base_url 一个字都不用改。

三件必须先知道的事

1. 任务耗时是真的

一个任务从创建到 succeeded 要 3–4 分钟—— 因为这就是模型本身的真实耗时,我们把它原样回放。 中途会依次经过 queued 和 running, 所以你的轮询循环、超时设置、状态机会被真正地跑到。

注意 queued 和 running 阶段的响应没有 video_url、cost,succeeded 之前也没有 fps、seed—— 这也是真实行为,不要假设这些字段一直存在。

2. 字段是真的,画面是样例

无论你传什么分辨率、时长、参考图 / 参考视频 / 音频,只要参数通过校验, 任务都会受理并跑完;响应里的 resolution、duration、cost.tier、cost.unit_price、cost.quantity 都按你的请求计算(4k、30 秒、带参考视频就是 vin_4k × 30),所以各档位的账单字段都能在这里核对。 但 video_url 拿到的永远是该模型的固定样片:

模型样片耗时
seedance-2.0-custom720p · 5 秒约 3 分钟
seedance-2.0-fast-custom720p · 4 秒约 4 分钟
seedance-2.5-custom720p · 4 秒约 4 分钟

样片可以正常下载、正常播放、支持 Range 请求、带正常的 video_url_expires_at。 参数校验和正式账号是同一段代码,在回放之前执行: 给这些模型传 watermark、媒体 URL 不是公网地址、时长越界, 在测试账号上会得到和正式账号一模一样的拒绝。

3. 只能调视频接口

测试账号调 /v1/chat/completions 或 /v1/messages 会返回 403 ERR_SANDBOX_MODEL,消息里会列出这个账号能调的模型, 因为对话接口后面没有回放层。需要联调聊天类接口,请单独告诉我们。

主动构造失败链路

这是测试账号最有用的地方。失败分支是接入里最容易漏测的一半—— 正式环境下你没法要求上游"现在给我一个 400", 而在这里你可以点名要一条录制过的失败响应。

原生接口加一个字段 sandbox_scenario:

{
  "model": "seedance-2.0-fast-custom",
  "content": [{"type": "text", "text": "一只猫在跳舞"}],
  "resolution": "720p",
  "duration": 4,
  "sandbox_scenario": "rejected_ytfast_short_duration"
}

火山兼容接口没有这个字段,写在提示词里(和 --rs 这类参数一样的写法):

"一只猫在跳舞 --rs 720p --dur 4 --sandbox rejected_ytfast_short_duration"

可以点名的场景

以下每一条都是我们真实抓取的响应, 错误码和文案都是上游原值。

sandbox_scenario模型你会拿到用来测什么
(不填)三个都行正常成功链路默认行为,任何通过校验的请求都走这条
succeeded_yt20_720p_5s · succeeded_ytfast_720p_4s · succeeded_yt25_720p_4s各自的模型与不填等价一般不需要;写着是为了场景名齐全
rejected_ytfast_short_durationseedance-2.0-fast-custom400 · invalid_request · Invalid request parameters: HTTP 400上游在创建阶段就拒绝,没有任务 id、不计费—— 确认你处理了"提交就失败"这一分支。点名时任何合法请求都会拿到这条响应

失败场景只在点名时回放:不写 sandbox_scenario 的请求一律走成功链路。 场景名写错会返回 400 并把当前模型可用的场景列全,不用背。正式账号发这个参数会被拒绝(400)—— 我们不会悄悄忽略它,否则你会以为自己在测失败分支、实际拿到的是成功。

另外两条正式账号上也会遇到、测试账号上同样能触发的错误, 不需要点名:不支持的参数(400 ERR_UNSUPPORTED_PARAMETER, 消息指明是哪个参数)和取消被拒(下文)。

联调 checklist

下面这九条跑通,接入基本就没有暗雷了。 建议按顺序做,每条都在测试账号上真跑一次。

  1. 认证——用错误的 key 调一次,确认你能识别 401 ERR_AUTH_FAILED;确认 key 是从配置读的,没有硬编码。
  2. 创建任务——拿到 id(形如 vt_…),确认你把它持久化了。 任务是异步的,进程重启后你得能接着轮询。
  3. 轮询到终态——处理 queued / running 两个中间态, 确认你没有假设 video_url 或 cost 一直存在。建议轮询间隔 ≥ 10 秒,任务要跑 3–4 分钟。
  4. 下载视频——从 video_url 取到文件;确认你读了 video_url_expires_at 并在 24 小时内转存。我们不做长期托管。
  5. 失败分支——点名 rejected_ytfast_short_duration 跑一次创建期失败,再传一个不支持的参数跑一次 ERR_UNSUPPORTED_PARAMETER, 确认每一种你都能给最终用户一个说得清的提示,而不是"系统错误"。
  6. 取消——对一个已经在跑的任务调 DELETE,你会拿到 409 ERR_CANCEL_REFUSED。 这是真实行为:这三个模型不支持取消,任务照常跑完; 正式账号上照常计费,测试账号的消息会注明 test account: no charge。 确认你的逻辑按"取消可能不生效"设计,而不是点了就当没了。
  7. 账单字段——确认 cost 块只在任务结算后出现,且你读的是 cost.amount(人民币字符串) 而不是自己按单价乘一遍。测试账号下 cost.amount 恒为 "0.00" 并带 cost.sandbox: true;cost.tier、cost.unit_price、cost.quantity 与正式账号一致,可以拿来核对档位。计费接口和控制台的用量页会列出每一次调用,金额同样为 0。
  8. 列表与分页——按 filter.status 查一次,翻一页,确认你读的是 total 而不是靠 "返回条数 < page_size" 判断结尾。
  9. 重试安全——对同一个任务重复轮询、重复下载, 确认不会重复计费或重复入库。任务 id 是幂等键。

接口细节见 视频生成; 错误码全表见 错误码; 计费口径见 计费与余额。