跳到正文

文档从 Key 到第一条视频

完成第一次生成需要的一切:一个 Key、一次请求、查任务、收回调。

开发者 API 需申请开通。

概览

基于 HTTPS 的 REST 接口,请求和返回都是 JSON。所有生成都是异步的。

接口地址
https://api.pershot.app/v1
认证
Authorization: Bearer 加上你的 Key。Key 以 sk_test_ 或 sk_live_ 开头,完整内容只显示一次,我们只保存哈希。
Key 权限
每个 Key 都有权限范围,还可以在创作台设一份可用清单,只放行其中的型号和工具。工具也算在内:图片放大、去背景、视频增强、对口型、扩图和 AI 改图都要在清单里才能用,其他的返回 403 forbidden_model。生成 1080p 或 4K 并增强,视频型号和视频增强都要在清单里。
错误格式
{ "error": { "code", "message", "param", "request_id" } }
ID
按类型加前缀:job_、qt_、key_、up_。
给 AI 智能体
给 AI 智能体读的纯文本:输入、可用取值、每种设置的价格和请求示例seedance-2.0-fastseedance-2.0-miniqwen-image-2512-lightningqwen-image-2512qwen-image-edit-2511-lightningqwen-image-edit-2511

真实生成还没开放。在模型页留下邮箱,开放时我们写信通知你,只发一次。

快速开始

四步,每一步都附上你应该看到的返回。

  1. 01

    获取 Key

    开发者 API 需申请开通:在创作台的 API Key 页面申请。开通后在那里新建 Key 并马上复制,完整的 Key 只显示一次。

    Shell
    export API_KEY="sk_test_…"
  2. 02

    发送请求

    提交镜头时带上 Idempotency-Key 和 max_credits 上限。立即返回 202 和排队中的任务,积分同时冻结。

    POST /videos/generations
    curl https://api.pershot.app/v1/videos/generations \
      -H "Authorization: Bearer $API_KEY" \
      -H "Idempotency-Key: $(uuidgen)" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "seedance-2.0-fast",
        "prompt": "Perfume mist in hard side light. Slow push-in, black background, grain.",
        "duration": 5,
        "resolution": "720p",
        "aspect_ratio": "16:9",
        "generate_audio": true,
        "max_credits": 34
      }'
    应当返回
    {
      "id": "job_01J9ZK4T8W",
      "object": "job",
      "kind": "video",
      "status": "queued",
      "money_status": "reserved",
      "queue_position": 2,
      "requested_model": "seedance-2.0-fast",
      "credits_quoted": 34,
      "credits_charged": null
    }
  3. 03

    查询任务

    轮询任务直到状态变为 succeeded。输出链接是带签名的,会过期,需要的文件请及时下载。

    GET /jobs/{id}
    curl https://api.pershot.app/v1/jobs/job_01J9ZK4T8W \
      -H "Authorization: Bearer $API_KEY"
    应当返回
    {
      "id": "job_01J9ZK4T8W",
      "object": "job",
      "kind": "video",
      "status": "succeeded",
      "money_status": "settled",
      "requested_model": "seedance-2.0-fast",
      "resolved_model": "seedance-2.0-fast",
      "credits_quoted": 34,
      "credits_charged": 34,
      "outputs": [
        {
          "kind": "video",
          "url": "https://…/job_01J9ZK4T8W.mp4?sig=…",
          "width": 1280,
          "height": 720,
          "duration_s": 5
        }
      ],
      "error": null
    }
  4. 04

    接收回调

    传入 webhook_url,每次状态变化我们都会 POST 过去,带时间戳签名。请返回 2xx;投递失败会按退避策略重试。

    POST → webhook_url
    {
      "id": "evt_01J9ZKB1QX",
      "type": "job.succeeded",
      "created_at": "2026-09-29T14:02:31Z",
      "data": {
        "job": {
          "id": "job_01J9ZK4T8W",
          "object": "job",
          "status": "succeeded",
          "money_status": "settled",
          "credits_charged": 34,
          "outputs": [
            {
              "kind": "video",
              "url": "https://…/job_01J9ZK4T8W.mp4?sig=…",
              "width": 1280,
              "height": 720,
              "duration_s": 5
            }
          ]
        }
      }
    }

接口

路径都相对于接口地址。

方法路径作用
GET/v1/models当前账户可用的型号、能力和状态
GET/v1/pricing公开价;登录后返回账户实际价
POST/v1/quotes执行计划、分项费用、最高扣费和有效期(10 分钟)
POST/v1/videos/generations生成视频;返回 202 和任务
POST/v1/images/generations生成或编辑图片;返回 202 和任务
GET/v1/jobs/{id}状态、签名下载链接、实际费用
GET/v1/jobs你的任务列表,最新的在前
POST/v1/jobs/{id}/cancel请求取消;模型还没受理时,冻结的积分退回
GET/v1/balance可用和冻结的积分,按类别列出
GET/v1/usage按日期或型号的用量,JSON 或 CSV
POST/v1/uploads上传不超过 10 MB 的 JPEG、PNG 或 WebP

报价与上限

每次生成都要带 quote_id 或 max_credits 上限,二选一。带 quote_id 时按该报价执行;带 max_credits 时,只有价格不超过上限才执行。

model 为 "auto" 时必须带 max_credits。报价 10 分钟内有效,过期返回 quote_expired。

幂等

每个生成请求都要带 Idempotency-Key 请求头(1 到 255 个可见 ASCII 字符)。

24 小时内使用同一个键,返回同一个任务(HTTP 200 而不是 202),超时后重试不会创建或扣费第二个任务。

回调

在生成请求(或批量请求)里传入 webhook_url,即可接收状态变化。每个事件都是一个 POST,JSON 内容包含 id、type、created_at 和 data:任务事件是 data.job,batch.completed 是 data.batch。

事件

  • job.queued
  • job.processing
  • job.succeeded
  • job.failed
  • job.cancelled
  • batch.completed
  • 每次投递都带事件 ID、时间戳和签名,请先验签再处理内容。
  • 你的地址在 10 秒内返回 2xx 才算送达。否则会在 1 分钟、5 分钟、30 分钟、2 小时、6 小时后重试,之后标为失败;客服可以重放。不跟随重定向。
  • 回调地址必须是 https。指向内网、本机或保留地址的主机会被拒绝,提交时和我们连接时都会检查。

请求头

X-Signature
t=<unix>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>
X-Event-Id
事件 ID,和内容里的 id 相同。重试和重放都沿用同一个 ID,请记录下来,已处理过的 ID 直接跳过。
签名密钥
每个账户一个 whsec_… 密钥,在创作台的 API Key 页面查看。HMAC 的密钥就是整个字符串,包括前缀。
轮换
轮换之后的 24 小时内,旧密钥会作为第二个 v1 继续签名。只要任意一个 v1 匹配,就可以接受这次投递。

请用收到的原始内容计算 HMAC,不要用重新序列化后的 JSON;用常量时间比较;拒绝时间戳超过 5 分钟的请求。

验证 X-Signature
import { createHmac, timingSafeEqual } from "node:crypto";

// rawBody: the request body exactly as received, before any JSON parsing.
export function verifyWebhook(header, rawBody, secret, toleranceSec = 300) {
  let t = null;
  const signatures = [];
  for (const item of (header ?? "").split(",")) {
    const [key, value] = item.split("=", 2);
    if (key === "t") t = Number(value);
    if (key === "v1") signatures.push(Buffer.from(value, "hex"));
  }
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSec) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest();
  return signatures.some((s) => s.length === expected.length && timingSafeEqual(s, expected));
}

// verifyWebhook(req.headers["x-signature"], rawBody, process.env.WEBHOOK_SECRET)
// Answer 2xx quickly, and skip an X-Event-Id you have already handled.

错误码

错误码和 HTTP 状态是固定的,message 供人阅读。

错误码HTTP何时出现
invalid_request400字段缺失或超出范围
unauthorized401没有 Key、Key 已撤销或签名错误
insufficient_credits402余额不够冻结本次费用
forbidden_model403这个 Key 的可用清单里没有该型号或工具
region_not_supported403该型号在你所在的地区不提供
developer_api_closed403开发者 API 未开通时使用开发者 Key;需申请开通
member_connections_paused403连接自己的 AI 智能体暂停期间使用会员凭据(MCP、连接码或命令行)
not_found404你的账户里没有这个任务、报价或上传
quote_expired409报价已超过 10 分钟
price_changed409价格超出了你的上限
content_rejected422内容被拒绝,不扣费
rate_limited429这个 Key 的请求太频繁
concurrency_limited429这个账户同时运行的任务太多
internal_error500我们这边出了问题
upstream_unavailable503模型暂时不可用,请稍后重试

模型的结果不确定时不返回错误:任务状态标为 unknown,先查询确认,不会重新提交。

限额

请求数
默认每个 Key 每分钟 60 次。
并发
每个账户默认同时跑 3 个任务,可申请提高。
上限
模型的总容量是硬上限,多开 Key 不会增加并发。

图片

POST /v1/images/generations 使用相同的请求头。按档位和操作选型号 ID;改图模型还要传 image_url,出图模型不接受它。

档位出图改图
Image Mini经济 · 草稿qwen-image-2512-lightningqwen-image-edit-2511-lightning
Image Fast推荐qwen-image-2512qwen-image-edit-2511

各型号参数限制

每个型号的 API 页都有完整的表:取值、单位、由谁检查、超出后会怎样。GET /v1/models 以 JSON 返回同样的限制。

  • 平台校验我们检查,不符合就返回 400,不报价也不冻结积分。
  • 供应商校验由供应商检查。被拒的任务会失败,不收费。
  • 建议值没有人检查。控制在范围内,效果更好。
型号主要限制完整表格
seedance-2.0-fastSeedance 2.0 Fast提示词 2 至 2,000 个字符 · 4 至 15 秒 · 最多 9 张参考图 · 图片每边 300 至 6,000 像素查看表格
seedance-2.0-miniSeedance 2.0 Mini提示词 2 至 2,000 个字符 · 4 至 15 秒 · 最多 9 张参考图 · 图片每边 300 至 6,000 像素查看表格
qwen-image-2512Qwen-Image-2512提示词 2 至 2,000 个字符 · 1K 或 2K · 不接受原图查看表格
qwen-image-2512-lightningQwen-Image-2512 · Lightning 4-step提示词 2 至 2,000 个字符 · 1K 或 2K · 不接受原图查看表格
qwen-image-edit-2511Qwen-Image-Edit-2511提示词 2 至 2,000 个字符 · 1K 或 2K · 一张原图,JPEG、PNG 或 WebP,不超过 10 MB查看表格
qwen-image-edit-2511-lightningQwen-Image-Edit-2511 · Lightning提示词 2 至 2,000 个字符 · 1K 或 2K · 一张原图,JPEG、PNG 或 WebP,不超过 10 MB查看表格

上传

POST /v1/uploads 按文件内容判断类型。上传链接 7 天有效。

文件格式最大最长
图片:首帧、参考图或改图原图JPEG, PNG, WebP10 MB–
视频:对口型MP450 MB60 秒
音频:对口型MP3, WAV, M4A10 MB60 秒

其他网站上的图片我们不会去下载。这类链接由供应商检查尺寸,被拒的任务不收费。 同样的限制也能以 JSON 读取:GET /v1/models 为每个型号返回 limits 对象。

从 fal、Replicate 或 WaveSpeed 迁移

只换接口地址和 Key 是不够的:每个请求还要把型号 ID 放进请求体,带上 Idempotency-Key 请求头和价格上限(max_credits 或 quote_id)。迁移指南逐个字段对照 Seedance 2.0 和 Qwen-Image,并列出不能直接沿用的部分。