RAOHUAN AI
API v1

图片与视频 API

获取模型、提交任务、查询结果。

BASE URL
https://www.raohuanai.com/api/v1

AI 接入

接入说明包含示例和最新文档链接。AI 接入或排错时,可先核对当前接口与模型配置。

查看 OpenAPI JSON

文档持续更新,链接可留在你的项目中。

01

跑通第一个任务

先验证连接与密钥,再选择模型创建任务。

1

创建密钥

在开发者中心创建 API Key,点击复制全文。

2

获取模型

读取当前开放的模型、输入限制与参数选项。

3

创建任务

每个新生成任务使用唯一 Idempotency-Key,重试沿用原键。

4

获取结果

轮询任务,或在 Webhook 中接收终态事件。

先调用 GET /models 验证连接与密钥,该调用不扣生成积分;从响应的 data.data[] 选择模型。

bash
curl "https://www.raohuanai.com/api/v1/models" \
  -H "Authorization: Bearer jg_live_<key_id>_<secret>"
下一步:按模型配置创建生成任务

确定模型与参数后再提交,创建任务会按当前模型计费。按目录要求填写 model、parameters 与必需素材;示例不预设模型或参数。

bash
# 先读取 GET /models:替换 model,按所选模型填写 parameters 和必需素材。
curl -X POST "https://www.raohuanai.com/api/v1/generations" \
  -H "Authorization: Bearer jg_live_<key_id>_<secret>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-generation-001" \
  -d '{
    "model": "<GET /models 返回的 id>",
    "input": { "prompt": "柔和自然光下的商品展示" },
    "parameters": {}
  }'

生成是异步的。HTTP 202 代表任务已入队,不代表媒体已生成完成。

02

身份认证

在每个业务请求的 Authorization 头中传入 API Key。

Bearer Token

API Key 格式为 jg_live_<key_id>_<secret>。密钥与账号绑定,不要放在浏览器端代码、日志或公开仓库中。

账号同时只保留一把有效 Key。轮换后旧 Key 立即失效;轮换冷却为 1 小时,且每个北京时间自然日最多创建或轮换 5 次。

API Key

开发者中心默认脱敏展示,可随时复制全文。仅在服务端使用;重置后旧密钥立即失效。

http
Authorization: Bearer jg_live_<key_id>_<secret>
成功信封{ "data": ..., "request_id": "req_..." }
错误信封{ "error": { ... }, "request_id": "req_..." }

所有响应同时携带 X-Request-Id。联系支持时请提供该值。

GET/models列出已开放模型

目录返回当前账号可用的模型、参数、素材要求与积分价格,和本站当前配置保持同步。model 原样使用返回的 id,不要用名称或自行拼接的 ID。

模型 parameters 数组中的 name 是请求参数对象的 key;options[].value 保持 JSON 原类型,不传整个选项对象或统一转成字符串。参数须满足目录选项与 parameter_constraints.allowed_combinations;fixed_parameters 由服务端补齐,不传入或覆盖。素材遵守 input 与当前 input.modes。

模型可见性、定价与配置变化

只展示已启用、当前账号有权限、本站定价完整且有可用线路的统一模型;调用仍受 OpenAPI 总开关限制。启停与配置变化后重新读取目录;提交期间配置变化会返回 model_changed。

未自定义 ID 时使用 unified:123 形式;自定义 ID 会替代默认 ID。本文响应中的 ID、参数及价格仅作示意,不代表当前可调用配置。

pricing.rules 是当前账号的有效单价,按参数组合匹配 when。优先级为用户专属价 > OpenAPI 独立价 > 本站默认价。无独立价时跟随默认价,清除独立价后恢复继承;无效配置不能通过专属价绕过。

仅在 pricing.multiplier.parameter = "output_count" 时乘以生成数量。最终扣费以创建任务返回的 credits 为准;受理后改价不影响原任务,失败按原实扣金额退回。

历史直连模型不进入新目录;原有已开放 ID 仍按原权限、开关及定价调用。

bash
curl "https://www.raohuanai.com/api/v1/models" \
  -H "Authorization: Bearer jg_live_<key_id>_<secret>"
模型响应示例
json
{
  "data": {
    "object": "list",
    "data": [
      {
        "id": "unified:123",
        "object": "model",
        "name": "商品视频生成",
        "type": "video",
        "input": {
          "prompt": { "required": true, "max_bytes": 10000 },
          "images": { "max_count": 3, "required": false, "allowed_mime_types": ["image/jpeg", "image/png"] },
          "videos": { "max_count": 1, "required": false, "allowed_mime_types": ["video/mp4"] }
        },
        "parameters": [
          { "name": "duration", "label": "时长", "type": "select", "required": true, "options": [{ "value": 5 }, { "value": 10 }] },
          { "name": "aspect_ratio", "label": "画面比例", "type": "select", "required": true, "options": [{ "value": "9:16" }, { "value": "16:9" }] }
        ],
        "fixed_parameters": {},
        "pricing": {
          "unit": "credits",
          "rules": [
            { "when": { "duration": 5, "aspect_ratio": "9:16" }, "credits": 20 },
            { "when": { "duration": 5, "aspect_ratio": "16:9" }, "credits": 20 },
            { "when": { "duration": 10, "aspect_ratio": "9:16" }, "credits": 40 },
            { "when": { "duration": 10, "aspect_ratio": "16:9" }, "credits": 40 }
          ]
        }
      }
    ],
    "has_more": false
  },
  "request_id": "req_01J..."
}
POST/uploads创建 COS 直传签名

生成接口不接受任意公网 URL。先为本地素材创建上传签名,响应的 data.upload 是上传信息,data.id 是用于生成输入的 asset_*。

1. 申请上传签名

bash
curl -X POST "https://www.raohuanai.com/api/v1/uploads" \
  -H "Authorization: Bearer jg_live_<key_id>_<secret>" \
  -H "Content-Type: application/json" \
  -d '{
    "file_name": "product-front.jpg",
    "mime_type": "image/jpeg",
    "size_bytes": 1842031
  }'

2. 直接上传二进制文件

bash
curl -X PUT "<upload.url>" \
  -H "Content-Type: image/jpeg" \
  -H "Cache-Control: private, max-age=86400" \
  --upload-file "./product-front.jpg"
上传响应示例
json
{
  "data": {
    "id": "asset_01J...",
    "object": "asset",
    "kind": "image",
    "mime_type": "image/jpeg",
    "size_bytes": 1842031,
    "status": "pending",
    "upload": {
      "method": "PUT",
      "url": "https://cos.example.com/presigned-upload...",
      "headers": {
        "Content-Type": "image/jpeg",
        "Cache-Control": "private, max-age=86400"
      },
      "expires_at": "2026-09-01T14:10:00.000Z"
    }
  },
  "request_id": "req_01J..."
}

PUT 时必须逐项、原样发送 upload.headers 返回的全部签名 header,客户端不得遗漏或自行改写,否则 COS 会拒绝签名。

PUT 成功后即可将 asset_* 传入生成请求,无需调用额外的上传确认接口;创建任务时服务端会检查素材归属、租约和模型要求。上传支持 JPEG、PNG、WebP 图片和 MP4 视频,单文件最多 20 MiB,模型若有更低大小限制仍需满足。

素材有效期与批量上传

预签名有效期较短,请立即上传。待接收素材需在 24 小时内用于生成;任务成功接收后可复用 7 天,每次被新任务接收都会续期。单账号最多保留 64 个 / 512 MiB 待接收素材;已接收素材统一按账号存储容量管理。清理文件后会同步释放素材名额,已清理的 asset ID 不可再用。重复使用同一素材时请复用 asset ID,生成重试无需重新申请上传。

批量任务建议按“上传一条任务的素材 → 提交该任务”持续补位;任务受理后释放待接收名额。50 个任务共用同一素材时可复用 asset ID,不必重复上传;多素材任务不宜先把整批文件全部预存。

POST/generations创建图片或视频生成

使用 model 传入 GET /models 返回的公开 ID,使用 input 传入提示词与素材,使用 parameters 传入该模型允许的可见参数。

json
{
  "model": "unified:123",
  "input": {
    "prompt": "保持商品外观一致,缓慢环绕镜头",
    "images": ["asset_01JIMAGE..."],
    "videos": ["asset_01JVIDEO..."],
    "video_durations": [4.125]
  },
  "parameters": {
    "duration": 5,
    "aspect_ratio": "9:16"
  }
}

使用参考视频时,若目录返回 input.videos.requires_duration_seconds = true,或存在 max_duration_seconds / max_total_duration_seconds,均须提供 input.video_durations,数量及顺序与 input.videos 对应;填写实际秒数(可含小数),并遵守单条与总时长上限。parameters.duration 是生成时长,不能代替参考视频时长。

parameters.output_count 表示一个任务由模型原生生成的结果数,以目录选项为准。批量创建 50 个独立任务时,请分别提交 50 次请求,每个任务使用不同的幂等键。

HTTP 202 响应示例
json
{
  "data": {
    "id": "gen_01J...",
    "object": "generation",
    "model": "unified:123",
    "type": "video",
    "status": "queued",
    "progress": 0,
    "credits": 20,
    "output": { "assets": [] },
    "error": null,
    "created_at": "2026-09-01T14:00:00.000Z",
    "updated_at": "2026-09-01T14:00:00.000Z",
    "completed_at": null,
    "idempotent_replay": false
  },
  "request_id": "req_01J..."
}
1queued已入队
2processing处理中
3succeeded成功
4failed失败
5canceled已取消

上述是对外稳定状态,不暴露供应商内部阶段。v1 暂不提供主动取消接口。

GET/generations/{id}查询单个任务
bash
curl "https://www.raohuanai.com/api/v1/generations/gen_01J..." \
  -H "Authorization: Bearer jg_live_<key_id>_<secret>"

保存创建响应的 data.id,每 5–10 秒查询一次并读取 data.status。succeeded / failed / canceled 均停止轮询;仅成功时读取 data.output.assets,失败时读取 data.error。HTTP 200 只表示查询成功,不代表任务成功;不要因等待超时重新创建任务。

data.output.assets[].url 默认优先使用可直接下载的厂商原链接,管理员可按用户设置为 COS 链接。图片数据或需要服务端鉴权等无法直用的结果会自动转存 COS。厂商链接可能过期,请及时下载。设置仅影响新 API 任务,历史和已受理任务、网页生成保持原方式;查询、列表、幂等重放和 Webhook 使用同一任务的最终结果链接。

成功结果示例
json
{
  "data": {
    "id": "gen_01J...",
    "object": "generation",
    "model": "unified:123",
    "type": "video",
    "status": "succeeded",
    "progress": 100,
    "credits": 20,
    "output": {
      "assets": [
        {
          "type": "video",
          "url": "https://cdn.example.com/result.mp4",
          "mime_type": "video/mp4",
          "duration": 5
        }
      ]
    },
    "error": null,
    "created_at": "2026-09-01T14:00:00.000Z",
    "updated_at": "2026-09-01T14:03:12.000Z",
    "completed_at": "2026-09-01T14:03:12.000Z"
  },
  "request_id": "req_01J..."
}
失败任务示例(HTTP 200)

任务失败返回 data.status = failed 和 data.error;HTTP 请求失败使用顶层 error,两者分别处理。

json
{
  "data": {
    "id": "gen_01J...",
    "object": "generation",
    "model": "<创建任务时使用的 model>",
    "type": "video",
    "status": "failed",
    "progress": 0,
    "credits": 20,
    "output": { "assets": [] },
    "error": {
      "code": "<任务错误码>",
      "message": "本次生成失败,按实际错误码处理"
    },
    "created_at": "2026-09-01T14:00:00.000Z",
    "updated_at": "2026-09-01T14:03:12.000Z",
    "completed_at": "2026-09-01T14:03:12.000Z"
  },
  "request_id": "req_01J..."
}
GET/generations分页列出任务

可使用 status、limit 查询,并把响应中的 next_cursor 作为下一页的 starting_after。任务仅对创建它的账号可见。

bash
curl "https://www.raohuanai.com/api/v1/generations?status=succeeded&limit=20" \
  -H "Authorization: Bearer jg_live_<key_id>_<secret>"

50 个任务可每个间隔 5–10 秒查询一次,并错开请求时间;也可使用列表接口(limit 最大 100)批量读取,或接收 Webhook。列表须按 has_more / next_cursor 翻页,仍未确认终态的任务继续按 ID 查询,不能仅凭最近一页判断整批完成。

07

幂等、并发与限流

客户端必须安全重试,同时遵守账号级速率和并发容量限制;轮换 Key 不会重置配额。

Idempotency-Key

POST /generations 必须携带 8–128 个可见 ASCII 字符。同一账号 + 同一 Idempotency-Key + 相同请求体会返回原任务,不会重复扣积分;请求体不同时返回 HTTP 409。

支持 50 个任务并行提交,账号排队与处理中的任务合计上限为 100。该容量与供应商的实际执行并发不同;模型线路忙时会排队。终态任务释放容量后可继续提交,无需等待固定批次结束。

范围默认限制适用接口
业务入口1800 次/分钟/客户端 IP需要鉴权的 /api/v1 请求,鉴权前
读取接口1200 次/分钟/账号模型列表、任务查询
上传签名300 次/分钟/账号POST /uploads
生成创建不单独限制每分钟创建次数受用户并发与入口总请求限制约束
用户并发每用户 100 个非终态任务queued + processing

经过速率检查的响应包含 X-RateLimit-Limit、X-RateLimit-Remaining 和 X-RateLimit-Reset(Unix 秒)。rate_limit_exceeded 的 429 响应包含 Retry-After(等待秒数);任务或素材容量不足的 429 不保证携带该头,应按 error.code 等待任务完成或释放容量。

08

Webhook(可选)

先用轮询跑通即可。需要结果通知时,在开发者中心配置 HTTPS 接收地址。

接入 Webhook:事件、验签与重试
generation.succeededgeneration.failed
json
{
  "id": "evt_01J...",
  "type": "generation.succeeded",
  "created_at": "2026-09-01T14:03:12.000Z",
  "data": {
    "id": "gen_01J...",
    "object": "generation",
    "model": "unified:123",
    "type": "video",
    "status": "succeeded",
    "progress": 100,
    "credits": 20,
    "output": {
      "assets": [
        { "type": "video", "url": "https://cdn.example.com/result.mp4", "mime_type": "video/mp4" }
      ]
    },
    "created_at": "2026-09-01T14:00:00.000Z",
    "completed_at": "2026-09-01T14:03:12.000Z"
  }
}

请求头

X-Jiguang-Event-Id稳定事件 ID,用于接收方去重
X-Jiguang-TimestampUnix 时间戳(秒)
X-Jiguang-Signaturev1=<hex hmac sha256>

Node.js 验签

javascript
import crypto from "node:crypto";

function verifyWebhook(rawBody, timestamp, signature, secret) {
  const timestampSeconds = Number(timestamp);
  if (!Number.isInteger(timestampSeconds)) return false;
  if (Math.abs(Date.now() / 1000 - timestampSeconds) > 300) return false;

  const matched = /^v1=([a-f0-9]{64})$/i.exec(signature);
  if (!matched) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(timestamp + "." + rawBody)
    .digest("hex");

  const expectedBytes = Buffer.from(expected, "hex");
  const receivedBytes = Buffer.from(matched[1], "hex");
  return expectedBytes.length === receivedBytes.length
    && crypto.timingSafeEqual(expectedBytes, receivedBytes);
}

必须对未解析的原始请求体验签:HMAC_SHA256(secret, timestamp + "." + rawBody)。拒绝与当前时间相差超过 5 分钟的请求,并按 X-Jiguang-Event-Id 幂等去重;不要对重新序列化后的 JSON 计算签名。

2xx 表示送达成功。网络错误、408、429 和 5xx 按 1 分钟、5 分钟、30 分钟、2 小时、6 小时、24 小时递增重试;其他 4xx 视为终止失败。

09

错误处理

根据机器可读的 error.code 分支处理,不要依赖可读文案。

排错先核对最新规范与当前 GET /models,再查看开发者中心的调用日志。保留 request_id、HTTP 状态、error.code 和任务 ID;不要在日志中写入 Key、上传签名链接或素材内容。

json
{
  "error": {
    "code": "prompt_too_long",
    "message": "提示词超过当前模型长度限制,请缩短后重试",
    "param": "input.prompt"
  },
  "request_id": "req_01J..."
}
查看全部错误码
error.codeHTTP处理说明
invalid_request400请求体、查询参数或素材不符合要求
invalid_api_key401API Key 缺失、格式错误、已停用或已失效
model_forbidden403当前账号无权使用该模型
model_not_found404模型不存在或未对 OpenAPI 开放
generation_not_found404生成任务不存在或不属于当前账号
invalid_asset400素材不存在、不属于当前账号或不符合模型要求
invalid_asset_type400图片或视频素材类型与输入字段不匹配
asset_expired400素材的待上传或可复用租约已到期
asset_quota_exceeded429待接收素材数量或容量已达上限,details 返回当前用量与上限
storage_quota_exceeded409账号存储容量不足,请清理文件或联系管理员调整容量
invalid_parameters400模型参数名或参数值不合法
prompt_too_long400提示词超过模型限制,请缩短 input.prompt;字节上限见当前 GET /models
invalid_cursor400分页游标不存在或不属于当前账号,请从第一页重新查询
invalid_idempotency_key400Idempotency-Key 缺失或格式不合法
idempotency_conflict409同一幂等键被用于不同请求体
idempotency_in_progress409相同幂等请求正在提交,请稍后重试
model_changed409提交期间模型配置发生变化,请刷新模型列表
insufficient_credits402账号积分不足
rate_limit_exceeded429账号或客户端 IP 速率限制已触发,按 Retry-After 等待
concurrency_limit_exceeded429账号的非终态生成任务已达上限
openapi_disabled503OpenAPI 全局服务当前未启用
rate_limit_unavailable503限流服务不可用;系统 fail-closed 拒绝请求
storage_unavailable503素材上传存储暂时不可用
service_unavailable503模型服务或依赖暂时不可用,请保留 request_id 供排查;勿据此盲目修改模型参数
internal_error500未预期的服务端错误
generation_unavailable500任务暂时不可读取,创建请求请保持原幂等键重试
重试建议

网络中断、408、速率 429 和可恢复的 5xx 使用带随机抖动的指数退避;有 Retry-After 时至少等待指定秒数。409 idempotency_in_progress 表示原请求尚在提交,可稍后用原键重试;idempotency_conflict 必须先检查请求体。任务或素材容量不足需等待或释放容量,服务未启用需先解决配置。重试创建任务必须复用原 Idempotency-Key 和相同请求体,避免重复创建与扣费。