DEVELOPER GUIDE / API 接入教程

MiniMax H3 API 接入教程
从第一次请求,到下载成片。

通过星志 API 调用 MiniMax H3:先读取能力和报价,再创建任务、查询进度、下载视频。本教程无需登录即可阅读;实际调用使用你在星志创建的 API Key,与网页共用账号积分。

星志提供第三方接入服务,本页不是 MiniMax 官方 API 文档;请求地址和参数适用于星志。教程整理:2026-11-02。

01 / GET STARTED

调用前需要准备什么?

01

账号与 API Key

登录工作台后打开“开发者 → API Keys”,创建 Key 并核对可用积分。手机端在账号页面进入 API Keys。教程可以公开阅读,生成服务按实际任务计费。

02

读取当前能力

请求 GET /videos/options,确认服务可用、档位、时长和实时报价。请求路径均相对于下方 API 地址。

03

保存请求与任务编号

为每次新生成准备唯一的 Idempotency-Key,发送前保存编号和完整请求。受理后保存任务 id,后续查询、下载都使用这个任务。

API 地址:https://xzanime.com/api/v1

身份验证:Authorization: Bearer YOUR_API_KEY

POST /videos/generations 创建任务 → GET /jobs/{id} 查询至成功 → GET /videos/{id}/download-policy 读取下载协议 → POST /videos/{id}/download 确认后获取文件地址。创建、查询和下载全程通过 API 完成,无需网页登录、Cookie 或网页确认窗口。所有平台请求均使用 Bearer API Key;生成接口必须附带 Idempotency-Key。提交返回任务编号,成片通过后续查询与下载取得。

02 / PRICING

H3 API 生成 10 秒视频多少钱?

下表读取本站当前 API 报价。实际接入时读取 /videos/options 并计算本次请求的 expected_points,不要把示例金额写死。

API · 10 秒 · 768p · 仅视频生成费
档位生成费基础折算
快速200 积分80 积分约 ¥0.80
标准300 积分120 积分约 ¥1.20
增强450 积分180 积分约 ¥1.80
高质量600 积分240 积分约 ¥2.40

无参考视频、不选高清化。人民币按 100 积分约合 1 元折算,不含充值赠送,不代表最低充值额或完整订单总价。

网页与 API 视频活动 4 折 · 截止 2026-11-30 14:05:44(北京时间)

报价读取时间:2026-11-03 23:46:56(北京时间)。价格会随活动与配置变化,请以提交前确认的费用为准。

比较网页与 API 价格、活动和附加费用 →
扣费、退款与 2K 处理怎么结算?

返回 202 前按已知报价直接扣除生成与可选 2K 积分,不计入冻结;单价和账单快照在受理时锁定。视频任务的自动整理不另扣用户积分。reserved_points 表示尚待结算的历史用量预估,charged_points 表示实际扣费,refunded_points 表示退款。原片成功但 2K 失败时,status=succeeded、upscale_failed=true、resolution=768p,保留原片并只退高清部分;生成失败退回生成与高清部分。points 是生成及 2K 报价,完整扣退以账单字段为准。排队、轮询、下载和恢复同一任务不重复收费。暂停或网络中断不等于退款;计费关闭时金额为 0。

03 / REQUEST

文字、图片和视频参考怎么传?

第一次接入可从普通文生视频开始:creation_type=general,不提供参考素材,选择时长和档位。先跑通创建、查询、下载,再加入参考素材。

general · 普通生成

使用文字生成视频,可选图片或参考视频;最多 9 张图片和 1 个视频,可选择四档质量。

video_edit · 视频编辑

必须提供 1 个原视频,可选最多 9 张参考图片,tier=standard。prompt 描述需要修改的内容;duration 为 4–15 秒整数,preserve_source_audio 可按需开启。

character_swap · 人物替换

必须提供 1 个原视频和 1 张目标人物图,tier=standard、preserve_source_audio=true。原视频至少 4 秒,duration=min(15, floor(原视频秒数)),aspect_ratio 按源视频方向填写。例如 5.916 秒横屏原视频应传 duration=5、aspect_ratio=16:9。

提交前读取 /videos/options:available 为 false 时暂不提交;带参考视频还需 reference_video_available=true,视频编辑和人物替换还需 specialized_available=true。素材需先上传并完成校验;时长与宽高使用完成接口返回的真实素材信息。

POST /videos/generations · JSON 请求字段
参数填写与计费规则
creation_type可省略,默认 general(普通生成);video_edit 为视频编辑,character_swap 为人物替换。三个工作流均使用 POST /videos/generations,具体素材和参数要求见下方工作流说明。
model可省略,默认 minimax/h3;以 /videos/options 的 model 为准。
resolution生成分辨率可省略,默认且仅接受 768p;需要 2K 成片请用 upscale_2k=true,不能把请求 resolution 改成 2K。
prompt必填,去除首尾空白后 5–30000 字符,描述希望生成或修改的内容;任务返回的 prompt 保留该原文。服务端按当前配置与工作流处理提示词,调用方无需先调用独立优化接口,自动整理不另收费。prompt_review_enabled 表示当前提示词整理配置,不保证每种工作流都有独立优化步骤。描述命中网站强拦截规则时返回 400,不创建任务、不扣费;仅标记的内容允许继续。
duration4–15 之间的整数,默认 10,单位秒;人物替换须按源视频时长向下取整并最多取 15。视频编辑和人物替换的实际成片时长不超过源视频与请求时长中的较小值。
tierfast(快速)、standard(标准)、enhanced(增强)、quality(高质量)。普通生成可省略,使用 /videos/options 的 default_tier;建议明确传入选定档位。视频编辑和人物替换必须传 standard。四档每秒积分独立配置,实时报价见 tiers。
aspect_ratio16:9 或 9:16,默认 16:9;人物替换须与源视频方向一致:宽度大于或等于高度传 16:9,否则传 9:16。
expected_points必填非负整数。生成原价 G=ceil(effective_points_per_second × duration + effective_video_reference_points_per_second × ceil(参考视频总时长));可选 2K 原价 U=effective_upscale_points_per_second × duration,不选时为 0。AI 视频 API 参与有效的视频优惠,读取 promotion_snapshot.percent 作为比例 P(无优惠为 100);总价为 floor((G×P+50)/100)+floor((U×P+50)/100),两部分分别四舍五入再相加,不要对每秒单价先打折。参考视频单价固定为对应成片单价的一半,可为 22.5 等小数,不得先取整单价;只在生成总积分上向上取整。参考时长由后端核对真实素材,仅文字、图片或尾帧时参考时长为 0。标准档 15 秒参考生成 10 秒原价为 30×10+15×15=525 积分,八折后为 420 积分。单段、连续创作和长视频编辑使用同一规则,2K 仅按成片时长收费。价格变化返回 409,不创建任务、不扣费;刷新报价后重新确认。已受理任务按原账单快照结算。
quality_enhance布尔值,默认 true;加入 /videos/options 返回的通用画质要求,不额外收费。false 不加入通用画质要求;此参数不控制自动提示词整理。
preserve_source_audio布尔值,默认 false;人物替换必须为 true。仅有参考视频时可开启,复用原视频第一条音轨中的对白、音乐和音效,从开头按成片时长裁剪,替换生成声音,不循环、不变速、不混音。
upscale_2k布尔值,默认 false;true 在生成后执行 2K 高清化并保留原声音。横屏 2688×1536、竖屏 1536×2688。额外单价以 /videos/options 的 effective_upscale_points_per_second 为准。本接口在创建时选择高清化。
asset_ids可省略,默认 [];最多 9 张图片 + 1 个视频的已完成上传素材 ID,必须属于当前账号。无需参考素材即可文生视频。不接受任意远程地址、base64 或本地文件路径。
series单段省略。连续创作传 {id: 连续作品 UUID, number: 1–100 的片段编号, expected_job_id: 当前片段任务 ID};新片段 expected_job_id 为空字符串。须按顺序创作、上一段已有成功结果、全片画幅一致。重做使用编辑时的任务 ID,片段被其他页面改动则返回 409,不扣费。
参考图片和视频的上传步骤

1. POST /videos/assets/uploads,JSON 为 {"filename":"reference.png","byte_size":12345},byte_size 必须等于实际文件字节数。返回 201、id、url、fields。

2. 向返回的 url 发送 multipart/form-data POST:原样加入所有 fields,并把 file 作为最后一个字段,上传真实文件。不要自行设置 multipart boundary,也不要携带平台 Bearer Key;成功状态为 204。上传凭证有效期 15 分钟。

3. POST /videos/assets/{id}/complete(Bearer Key,无请求体),校验后返回 status=ready,再把 id 放进生成请求的 asset_ids。此接口可以重复查询完成结果。

4. JPG/JPEG/PNG/WebP 每张 ≤5 MiB,MP4 ≤200 MiB,参考片段约 2–15 秒(允许帧数取整至 15.75 秒),且必须含音轨;上传后校验真实文件格式。人物替换的原视频至少 4 秒。ready 表示已上传就绪,素材审核在任务受理后进行,通过后才生成。等待与审核期间按任务 phase 展示并继续查询;审核失败的任务在退款完成后 status=failed、charged_points=0。审核不可用时拒绝新请求,不扣费。

5. 未使用素材默认 24 小时清理,已使用素材遵循网站参考素材保留配置;进行中的任务会受保护。视频成片目前不自动清理,请及时下载保存。

04 / PYTHON

Python:生成、查询和下载一个视频。

准备 Python 3 和 requests(安装命令:python -m pip install requests),将 API Key 放入环境变量 API_KEY。下面示例与工作台开发者文档共用,默认创建标准档、10 秒、16:9、768p 的纯文字视频,不选择 2K 高清化。

运行前先确认费用。首次创建会扣除本次生成积分。脚本会先把请求写入当前目录的 h3-request.json,受理后保存任务 id;保留文件、在相同目录重跑即可继续同一次请求,不会主动创建新编号。记录文件不保存 API Key。

已有任务可设置环境变量 VIDEO_JOB_ID 直接查询和下载。确实要生成新视频时,用 VIDEO_REQUEST_FILE 指定一个尚不存在的新文件名,再运行脚本;每个文件对应一次生成。旧记录存在时会沿用原参数,修改代码不会改写原请求。

提交超时后保留记录文件;不要通过换文件名来重试。报价变化或请求被拒绝时,先核对响应与原任务是否受理,再决定是否用最新报价创建新请求。

import json, os, time, uuid
from pathlib import Path
import requests

base = os.getenv("API_BASE_URL", "https://xzanime.com/api/v1").rstrip("/")
headers = {"Authorization": "Bearer " + os.environ["API_KEY"]}

def build_request(model):
    duration = 10
    upscale_2k = False  # True 时将高清处理价格加入总报价。
    quality = next(t for t in model["tiers"] if t["tier"] == "standard")
    # 生成和 2K 分别按活动比例四舍五入,再相加;不要先对每秒单价打折。
    percent = model.get("promotion_snapshot", {}).get("percent", 100)
    def activity_price(points):
        return (points * percent + 50) // 100
    return {"creation_type": "general", "model": model["model"], "resolution": model["resolution"],
            "prompt": "云海之上,一条蓝鲸缓缓游过未来城市,镜头平稳跟随。",
            "duration": duration, "aspect_ratio": "16:9", "asset_ids": [],
            "tier": quality["tier"], "quality_enhance": True, "upscale_2k": upscale_2k,
            "expected_points": activity_price(quality["effective_points_per_second"] * duration)
                + (activity_price(model["effective_upscale_points_per_second"] * duration) if upscale_2k else 0)}


# 同一记录文件只代表一次生成。新视频请明确选择另一个文件名。
state_path = Path(os.getenv("VIDEO_REQUEST_FILE", "h3-request.json")).resolve()
job_id = os.getenv("VIDEO_JOB_ID", "")
state = None
if not job_id:
    if state_path.exists():
        state = json.loads(state_path.read_text(encoding="utf-8"))
        if state["base"] != base:
            raise RuntimeError("记录的 API 地址不同,请核对 VIDEO_REQUEST_FILE")
        job_id = state.get("job_id", "")
    else:
        options = requests.get(base + "/videos/options", headers=headers, timeout=30)
        options.raise_for_status()
        model = options.json()
        if not model["available"]:
            raise RuntimeError("视频服务暂不可用")
        # 发起请求前持久保存编号和内容;文件写入失败时不会提交生成。
        state = {"base": base, "request_key": str(uuid.uuid4()), "body": build_request(model)}
        with state_path.open("x", encoding="utf-8") as record:
            json.dump(state, record, ensure_ascii=False, indent=2)
            record.flush()
            os.fsync(record.fileno())

if job_id:
    response = requests.get(base + "/jobs/" + job_id, headers=headers, timeout=30)
else:
    # 超时或进程重启后重放原请求,不重新报价或更换编号。
    response = requests.post(base + "/videos/generations", json=state["body"],
        headers={**headers, "Idempotency-Key": state["request_key"]}, timeout=60)
response.raise_for_status()
job = response.json()
print("保存任务编号:", job["id"])
if state is not None and not state.get("job_id"):
    state["job_id"] = job["id"]
    # 原子替换,避免写入中断损坏原记录;记录中不保存 API Key。
    temporary = state_path.with_name(state_path.name + "." + uuid.uuid4().hex + ".tmp")
    with temporary.open("x", encoding="utf-8") as record:
        json.dump(state, record, ensure_ascii=False, indent=2)
        record.flush()
        os.fsync(record.fileno())
    temporary.replace(state_path)
for _ in range(180):
    if job["status"] in ("succeeded", "failed") or job["recovery_paused"]:
        break
    time.sleep(10)
    response = requests.get(base + "/jobs/" + job["id"], headers=headers, timeout=30)
    response.raise_for_status()
    job = response.json()
if job["status"] != "succeeded":
    raise RuntimeError(f"请保留任务编号后继续查询,勿重复创建:{job}")
print("实际消费:", job["charged_points"])
# 读取本次文件的下载协议;所有操作均可通过 API 完成。
download_base = base + "/videos/" + job["id"]
response = requests.get(download_base + "/download-policy", headers=headers, timeout=30)
response.raise_for_status()
policy = response.json()
print(json.dumps(policy, ensure_ascii=False, indent=2))
# input 仅演示命令行确认;接入应用使用自身的确认流程,无需网页登录或 Cookie。
if input("是否接受以上下载协议?输入 yes 继续:").strip().lower() != "yes":
    raise SystemExit("未确认下载。视频已保存;设置 VIDEO_JOB_ID=" + job["id"] + " 可继续下载。")
response = requests.post(download_base + "/download", headers=headers, timeout=30,
    json={"accepted": True, "version": policy["version"], "content_token": policy["content_token"]})
response.raise_for_status()
download = response.json()  # url 为签名下载地址,expires_in 为有效秒数(900)。
# 签名地址无需 Bearer Key;不要把平台 API Key 转发到文件存储服务。
with requests.get(download["url"], stream=True, timeout=60) as media:
    media.raise_for_status()
    with Path("video.mp4").open("wb") as output:
        for chunk in media.iter_content(1024 * 1024):
            output.write(chunk)

示例提示词用于演示接口调用,不是视频展示片的原始生成记录。代码不会在此页面自动执行。

05 / DOWNLOAD

生成完成后,如何通过 API 下载?

以下路径均相对于 https://xzanime.com/api/v1,{id} 使用已完成任务的 id。读取协议和提交确认使用同一个 Bearer API Key;确认由接入方在自己的应用或业务流程中完成,不要求用户返回网站操作。

1. 任务 status=succeeded 后,GET /videos/{id}/download-policy 读取当前文件的下载协议,返回 version、content_token、notice、article、law_url、responsibilities 等字段。向使用者提供协议内容并取得确认;无需打开网站或先播放视频。

2. POST /videos/{id}/download,Content-Type 为 application/json,JSON 为 {"accepted":true,"version":"本次协议返回的 version","content_token":"本次协议返回的 content_token"}。accepted 必须为布尔值 true;version 和 content_token 原样使用本次协议的返回值,不要写死,也不要跨作品或分辨率版本复用。

3. 成功返回 HTTP 200 和 {"url":"签名下载地址","expires_in":900},直接 GET url 保存文件,无需也不要发送平台 API Key。地址过期后,对原任务重新读取协议并确认获取新地址,不会重新生成或扣费。

4. 下载版本不包含平台添加的显式 AI 提示文字或语音提示,仍保留文件内的隐式 AIGC 标识;历史作品以协议的 notice 与 metadata_verified 为准。播放接口提供带显式提示的播放版本。

5. 默认下载最终成片(已成功高清化时为 2K)。需要原分辨率版本时,读取协议与提交下载两个接口都带 original=true;这仅选择分辨率版本。native_video_url 和 /content?original=true 属于播放接口,不能据此判断是否带显式标识。

6. 收到 HTTP 409 且响应 JSON 的 detail.code=ai_label_consent_required,表示请求了需要下载确认的源片入口(如 /jobs/{id}/files/0 或 /videos/{id}/content?download=true)。请保留原任务 id,改走以上协议与确认接口;无需重新生成、重复扣费或跳转网页。确认成功后使用返回的 url,不要重试原 files/content 地址;确认不会把这些入口永久解锁。

7. POST /download 返回 400 且提示未接受协议时,应先取得确认再提交 accepted=true;返回 409 且提示文件或协议已更新时,重新读取同一作品、同一分辨率版本的 download-policy,再确认并提交最新字段。不要把所有 409 当成同一种错误,也不要默认替用户接受协议。

连续创作、尾帧衔接和整片导出

1. GET /videos/series 查看本人连续作品;POST 同一路径,提交 {"id":"客户端生成的 UUID"} 创建。网络重试沿用同一 UUID。作品与网站共用;PATCH /videos/series/{id} 提交 title 可改名。

2. POST /videos/generations 添加 series 参数,第一段 number=1、expected_job_id=""。下一段必须等上一段已有成功结果;每段独立报价、计费和查询。重新生成已有片段时传编辑开始时的 job.id,不可用轮询后的新编号偷偷替换它。

3. GET /videos/series/{id} 返回 segments、snapshot、can_preview、can_export、export。job 是当前尝试;ready 是最近一次成功结果,重做失败或取消不会删除上一版。continuity_changed=true 表示上一段已变化,应检查衔接。

4. GET /videos/{上一段 ready.id}/last-frame 预览实际尾帧,POST /videos/{id}/frame-reference 将其变成参考素材,把返回 id 放入下一段 asset_ids。不会默认使用尾帧;旧尾帧与上一段不匹配时拒绝提交。

5. can_export=true 时 POST /videos/series/{id}/exports,提交 {"snapshot":"详情返回的当前快照"}。重复请求复用同一整片;快照变化返回 409。轮询详情的 export,succeeded 后 GET /videos/series/{id}/exports/{export_id}/download-policy,再 POST /videos/series/{id}/exports/{export_id}/download;确认字段和签名文件下载步骤与单段视频相同。

6. GET /videos 与 /videos/{id} 可查看本人从网站或 API 创建的视频;列表每页最多 30 条,将 next_cursor 原样作为 before 参数继续查询,空值表示末页。不要自行拼时间游标。这些接口不返回 API 专用账单明细;API 提交任务用 /jobs/{id} 查询扣退。返回的原片和嵌套 upscale_job 的结果路径均接受 Bearer Key。

06 / TROUBLESHOOTING

等待、超时与下载问题怎么处理?

请求超时了,要不要重新生成?

先判断是否已经取得任务 id。有 id 时查询原任务;尚未取得 id 时,使用原 Idempotency-Key 和完全相同的请求重试。不要因为页面等待或网络中断就换新编号提交,否则可能创建另一条任务。

返回 409,是不是视频生成失败?

不一定。提交阶段可能是报价或幂等请求冲突;下载阶段可能是未走下载确认流程,或协议、文件已更新。结合响应正文判断,并按对应步骤处理。已完成的视频不需要因此重新生成。

能否直接通过程序完成下载?

可以。用同一个 API Key 读取下载协议,在你的应用内向使用者展示并取得确认,再提交确认取得签名地址。文件下载请求不发送平台 API Key。

API Key 应放在网页前端吗?

调用应由你控制的服务端或本地程序发起。不要把完整 Key 写入公开网页、代码仓库或截图;查询问题时提供任务编号即可。

查看任务状态与恢复规则
phase=site_queued / queue_source=site

等待制作。仅在 phase=site_queued 且 queue_position 非 null 时,它表示从 1 开始的本站等待顺序。展示以当前 phase 为准,不根据 status 自行推算排位或等待时长。

waiting / moderating / submitting / preparing

正在等待处理、审核素材、整理提示词或提交生成。展示以 phase 为准,继续查询同一任务,无需重复创建。

phase=service_processing / service_load

展示“服务处理中”,可附带 service_load_label:service_load 为 low / normal / high,分别对应“较少 / 一般 / 较多”。两者为 null 时仅显示服务处理中;繁忙程度不代表具体排位或预计完成时间,可能随处理情况变化。此阶段 queue_position、estimated_start_at、progress 均为 null。status 用于判断任务状态;暂停、取消、失败和完成按对应字段处理。单任务、作品列表、连续片段和嵌套 2K 任务使用相同展示规则。

queued / running

queued 表示已受理并排队,running 表示正在制作。phase=service_processing 时使用 service_load_label;其他阶段仅展示实际返回的非空 progress,null 不代表 0%。网络中断后继续查询原任务。

saving / phase=upscaling

正在保存成片或执行可选 2K 高清化;继续查询直到 succeeded。2K 成功时 resolution=2K;native_video_url 是原分辨率版本的播放接口,下载原分辨率成片请按下方流程使用 original=true。

succeeded / failed

完成并结算 / 失败且退款已处理。只有 succeeded 才会返回 result.files。

phase / recovery_paused / can_resume / resume_after_seconds

phase=settlement 或 refund 表示结算或退款中。recovery_paused=true 时,只有 can_resume=true 且等待 resume_after_seconds 后才可 POST /jobs/{id}/resume;其他情况保留任务编号联系管理员核对。恢复原任务不重扣积分。

can_cancel / phase=cancelling / phase=cancelled

仅 can_cancel=true 时可 POST /videos/{id}/cancel,是否仍可取消以服务端处理时的状态为准。返回 202 代表已接受取消请求;继续查询,直到 phase=cancelled,并通过账单字段确认退款。不要根据等待时长或进度自行判断是否能够取消。

素材与服务错误的详细处理

400 且 X-Error-Code=content_blocked 表示视频描述命中网站强拦截规则;503 且 X-Error-Code=visual_audit_unavailable 表示带素材请求因审核不可用而未受理。这两类拒绝不预留或扣除积分,响应头 X-Developer-Request-ID 可定位调用日志。素材接口还可能返回 410(尚未完成或已过期)、413(上传体积超限);生成请求包含未就绪素材也会返回 410。409 且 X-Error-Code=asset_busy 表示素材正在校验或使用,按 Retry-After 等待后沿用原请求重试。HTTP 5xx 或网络超时若无法确认是否受理,请沿用原 Idempotency-Key 和请求内容重试,切勿直接换新编号。

网站「开发者 → 调用日志」可按任务 ID 查询模型、生成档位、锁定单价、Key、状态、耗时、预留、消费和退款;被拒绝的生成请求通过响应头 X-Developer-Request-ID 定位。需要协助时提供任务 ID 或请求 ID,不要提供完整 API Key 或签名下载地址。