API 文档
用程序批量生成图片和视频。API 和网站共用同一个账号、同一份积分,价格与网站一致;任务失败会自动退回积分。
快速开始
1. 登录网站,打开「设置」页,在最下面的「API 密钥」里点「生成新密钥」,复制保存(密钥只显示一次)。
2. 所有请求的地址前缀为:
https://niuzhatian.com
3. 试一下查余额:
curl https://niuzhatian.com/v1/balance \
-H "Authorization: Bearer nzt-你的密钥"认证
在每个请求的请求头里带上密钥:
Authorization: Bearer nzt-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
调用流程
生成是异步的:
① GET /v1/models 查有哪些模型、各自支持的参数和价格
(可选)POST /v1/media 上传视频要参考的图片 / 音频 / 视频,拿到素材编号
② POST /v1/generations 提交任务,立刻拿到任务 id(同时扣积分)
③ 每隔 5–10 秒 GET /v1/generations/{id} 查进度,直到 status 变成 succeeded 或 failed
④ 成功后 GET /v1/generations/{id}/content 下载图片 / 视频
可以一次性并发提交很多任务,不用等上一个完成。
模型列表
/v1/models返回当前可用的全部模型。模型会随平台更新,请以这个接口的返回为准,不要把模型写死在代码里太久。
{
"object": "list",
"data": [
{
"id": "m-3f8a1c92d4",
"name": "Seedance 2.5 VIP(720p)",
"type": "video",
"resolutions": ["720p"],
"durations": { "min": 5, "max": 30 },
"aspect_ratios": ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9"],
"references": { "images": 9, "audios": 3, "videos": 3 },
"price": { "unit": "per_task", "by_resolution": { "720p": 400 } }
},
{
"id": "m-xxxxxxxxxx",
"name": "某图片模型",
"type": "image",
"sizes": [ { "value": "2K", "price": 30 } ],
"max_reference_images": 4,
"price": { "unit": "per_image", "by_size": { "2K": 30 } }
}
]
}
| 字段 | 说明 |
|---|---|
id | 提交任务时填的 model |
type | image 图片 / video 视频 |
resolutions | 视频可选分辨率 |
durations | 视频可选时长(秒)。可能是列表 [5,10,15],也可能是范围 {"min":5,"max":30} |
max_duration_by_resolution | (部分模型)不同分辨率的最长时长 |
aspect_ratios | 视频可选比例 |
sizes | (部分图片模型)可选尺寸及每张价格 |
max_reference_images | (图片模型)最多可传几张参考图,0 表示不支持 |
references | (视频模型)最多可传的参考图片 / 音频 / 视频数量,0 表示不支持 |
modes | (部分视频模型)支持的参考方式,见下方 generation_mode |
price.unit | per_task 每条 / per_second 每秒 / per_image 每张,单位都是积分 |
cost 是实际扣除的积分。上传参考素材
/v1/media?type={类型}&name={文件名}给视频模型用的参考素材要先上传,拿到素材编号后再提交任务。请求体直接放文件内容(不是表单),并设置对应的 Content-Type。
| type | 格式 | 大小上限 |
|---|---|---|
image | JPG / PNG / WEBP(建议边长 300–6000 像素) | 20MB |
audio | 常见音频格式(推荐 MP3) | 15MB |
video | MP4 | 50MB |
curl "https://niuzhatian.com/v1/media?type=image&name=hero.jpg" \
-H "Authorization: Bearer nzt-你的密钥" \
-H "Content-Type: image/jpeg" \
--data-binary @hero.jpg返回:
{ "id": "xxxxxxxx:rAbCdEf...", "type": "image" }
· 素材编号请在 3 天内使用,同一个素材可以在多个任务里重复使用。
· 部分模型对参考视频有时长要求(例如参考视频时长 + 生成时长不超过 25 秒),超出时提交会报错并且不扣积分。
提交任务
/v1/generations请求体为 JSON(Content-Type: application/json)。
生成视频
| 参数 | 必填 | 说明 |
|---|---|---|
model | 是 | 模型 id |
prompt | 是 | 画面描述 |
resolution | 否 | 分辨率,如 720p,默认第一个 |
duration | 否 | 时长(秒)。不在可选范围内时自动取最接近的值 |
aspect_ratio | 否 | 比例,如 16:9、9:16 |
media | 否 | 参考素材数组,每项是上传接口返回的 {"id": "...", "type": "image"},数量不超过模型的 references。在 prompt 里用 @图片1、@音频1、@视频1 指代它们(按同类素材在数组里的顺序编号,从 1 开始) |
generation_mode | 否 | 模型带 modes 时可选:reference 普通参考(默认);first_frame 首帧(只传 1 张图,作为视频开头);first_last_frame 首尾帧(只传 2 张图,第 1 张开头、第 2 张结尾) |
curl https://niuzhatian.com/v1/generations \
-H "Authorization: Bearer nzt-你的密钥" \
-H "Content-Type: application/json" \
-d '{"model":"m-3f8a1c92d4","prompt":"清晨的海边,一只金毛在奔跑,电影感","duration":10,"aspect_ratio":"9:16"}'
带参考素材生成视频
curl https://niuzhatian.com/v1/generations \
-H "Authorization: Bearer nzt-你的密钥" \
-H "Content-Type: application/json" \
-d '{"model":"m-3f8a1c92d4","prompt":"@图片1 是主角,在海边奔跑,背景音乐用 @音频1","duration":10,
"media":[{"id":"上传返回的图片编号","type":"image"},{"id":"上传返回的音频编号","type":"audio"}]}'
生成图片
| 参数 | 必填 | 说明 |
|---|---|---|
model | 是 | 模型 id |
prompt | 是 | 画面描述 |
size | 否 | 模型带 sizes 时填其中的 value,默认第一个 |
reference_images | 否 | 参考图数组(不超过 max_reference_images)。每张为 base64 数据:data:image/jpeg;base64,....,支持 JPG / PNG / WEBP,建议单张不超过 5MB。yk: 开头的模型也可以直接填公开的 https 图片地址 |
curl https://niuzhatian.com/v1/generations \
-H "Authorization: Bearer nzt-你的密钥" \
-H "Content-Type: application/json" \
-d '{"model":"模型id","prompt":"一杯冰美式,白色背景,商业摄影"}'
返回
{
"id": "tQ2x9vLm4kP7wZ",
"type": "video",
"model": "m-3f8a1c92d4",
"status": "queued",
"cost": 400
}
Idempotency-Key: 任意唯一字符串,网络重试时避免重复提交。查询任务
/v1/generations/{id}{
"id": "tQ2x9vLm4kP7wZ",
"type": "video",
"model": "Seedance 2.5 VIP(720p)",
"status": "succeeded",
"progress": null,
"error": null,
"cost": 400,
"result_url": "https://niuzhatian.com/v1/generations/tQ2x9vLm4kP7wZ/content",
"created_at": "2026-11-02T08:00:00.000Z"
}
| status | 含义 |
|---|---|
queued | 排队中 |
processing | 生成中(部分模型会在 progress 里给出进度) |
succeeded | 完成,可以从 result_url 下载 |
failed | 失败,原因在 error,积分已自动退回(refunded: true) |
canceled | 被平台取消,积分已退回 |
建议每 5–10 秒查一次。图片一般几十秒,视频一般几分钟到十几分钟。
下载结果
/v1/generations/{id}/content返回图片或视频文件本身,同样需要带 Authorization。加 ?dl=1 时可能会 302 跳转到平台的下载地址,请让你的程序跟随跳转(curl 加 -L)。
curl -L https://niuzhatian.com/v1/generations/tQ2x9vLm4kP7wZ/content \
-H "Authorization: Bearer nzt-你的密钥" -o result.mp4
查询余额
/v1/balance{ "balance": 12800 }
错误码
出错时返回对应的 HTTP 状态码,响应体为:
{ "error": { "message": "积分不足:这个任务需要 400 积分,当前只有 120 积分,请先到「积分」页兑换" } }
| 状态码 | 含义 | 建议 |
|---|---|---|
400 | 参数不对、模型不存在或暂未开放 | 按 message 修改后再提交 |
401 | 密钥无效、已删除或被停用 | 检查密钥 |
402 | 积分不足 | 到网站「积分」页兑换 |
403 | 密钥不能用于这个接口 | 只能调用本文档列出的接口 |
404 | 任务不存在,或不是这个账号的任务 | 检查 id |
409 | 任务还没完成就去下载 | 等 succeeded 后再下载 |
429 | 同时进行中的任务太多 | 等前面的完成后再提交 |
502 | 上游平台暂时连不上 | 稍后重试;提交阶段失败不会扣积分 |
限制与计费
· 积分与网站共用,价格与网站一致;提交时扣除,任务失败或被取消自动退回。
· 每个账号默认最多同时有 1000 个进行中的任务,需要更多请联系站长。
· 每个账号最多 5 个 API 密钥,可随时在「设置」页删除。
· API 生成的任务也会出现在网站的积分记录里。
· 视频的参考素材先用 /v1/media 上传,上传不扣积分。
完整示例(Python)
import time, requests
BASE = "https://niuzhatian.com"
H = {"Authorization": "Bearer nzt-你的密钥"}
# 1. 提交
r = requests.post(f"{BASE}/v1/generations", headers=H, json={
"model": "m-3f8a1c92d4",
"prompt": "清晨的海边,一只金毛在奔跑,电影感",
"duration": 10,
"aspect_ratio": "9:16",
})
r.raise_for_status()
task = r.json()
print("已提交", task["id"], "花费", task["cost"], "积分")
# 2. 等待完成
while True:
t = requests.get(f"{BASE}/v1/generations/{task['id']}", headers=H).json()
if t["status"] in ("succeeded", "failed", "canceled"):
break
time.sleep(8)
# 3. 下载
if t["status"] == "succeeded":
data = requests.get(t["result_url"], headers=H).content
open(task["id"] + ".mp4", "wb").write(data)
print("已保存")
else:
print("失败:", t["error"], "(积分已退回)")带参考图生成视频(Python)
def upload(path, kind, ctype):
with open(path, "rb") as f:
r = requests.post(f"{BASE}/v1/media", params={"type": kind, "name": path},
headers={**H, "Content-Type": ctype}, data=f.read())
r.raise_for_status()
return r.json() # {"id": "...", "type": "image"}
hero = upload("hero.jpg", "image", "image/jpeg")
r = requests.post(f"{BASE}/v1/generations", headers=H, json={
"model": "m-3f8a1c92d4",
"prompt": "@图片1 是主角,在雨夜的街头回头微笑",
"duration": 10,
"media": [hero],
})
print(r.json())批量并发提交
from concurrent.futures import ThreadPoolExecutor
prompts = ["海边日出", "雪山日落", "城市夜景"] # 可以是几百条
def submit(p):
r = requests.post(f"{BASE}/v1/generations", headers=H,
json={"model": "m-3f8a1c92d4", "prompt": p, "duration": 5})
return r.json()
with ThreadPoolExecutor(20) as ex:
tasks = list(ex.map(submit, prompts))
print([t.get("id") or t.get("error") for t in tasks])