Webhooks 与媒体作业生命周期
注册 mediaWebhookUrl,在任务完成时接收 POST 请求,轮询 GET /api/media/jobs/{id},处理错误代码,并了解计费和幂等性限制。
异步媒体任务操作指南:webhook 注册、状态、轮询、错误代码、费用和幂等性限制,严格依据代码中的当前实现。
作业生命周期
- POST /api/media/generate:成功时
202并{ ok: true, jobId, status: "processing" }。API 没有单独的queued/running状态:在任务完成前,客户端会看到processing。 - 上游可能会经历内部阶段(waiting、generating),这些阶段不会反映在公共 API 中;轮询期间,作业会保持为
processing。 - 终端状态:
success(包含resultUrls,成功后计费)或fail(不收费)。 - 完成记录只会写入一次:通过上游回调,或在
GET /api/media/jobs/{id}中进行延迟轮询时写入。
轮询:GET /api/media/jobs/{id}
GEThttps://getvibeapi.com/api/media/jobs/{id}
| 参数 | 类型 | 描述 |
|---|---|---|
status | string | submitting | processing | success | fail. submitting + media_submission_uncertain is non-terminal; within about 10–15 minutes such a submission is closed as fail (media_submission_not_started) without a charge — create a new task. |
resultUrls | 字符串[] | 签名 URL /api/media/file/{id}/{idx}?sig=…(无需 API key)。 |
priceRub | number | 以 USD 计的费用金额(失败或完成前为 0)。 |
failMsg | string | null | 失败时或出现非终态 media_submission_uncertain 时的安全消息。 |
errorCode | string | null | 错误代码(media_generation_failed)或非终止性 media_submission_uncertain。 |
retryGuidance | string | null | 对于 media_submission_uncertain:稍后轮询相同 jobId 的安全指令,并且不要自动创建重复任务。 |
# 2. poll the job until it is ready
curl https://getvibeapi.com/api/media/jobs/JOB_ID \
-H "Authorization: Bearer $GETVIBE_API_KEY"
# → {"status":"success","resultUrls":["https://..."],"priceRub":...}建议轮询间隔:3–5 s,并采用指数退避,最长 30 s。客户端超时时间应根据应用的 SLA 设置(视频生成可能需要几分钟)。
Webhook 注册
GEThttps://getvibeapi.com/api/webhooks
PATCHhttps://getvibeapi.com/api/webhooks
每个账户一个 URL:mediaWebhookUrl。在 控制面板 → Webhooks 中配置,或通过 API 使用账户会话(登录后的 cookie)进行配置。该端点不接受 sk-pv-…,只能接受经过身份验证的会话。
# Example (a dashboard session is required, not an API key)
curl -X PATCH https://getvibeapi.com/api/webhooks \
-H "Content-Type: application/json" \
-b "session=YOUR_SESSION" \
-d '{"mediaWebhookUrl":"https://example.com/webhooks/media"}'
# Clear the URL
curl -X PATCH https://getvibeapi.com/api/webhooks \
-H "Content-Type: application/json" \
-b "session=YOUR_SESSION" \
-d '{"mediaWebhookUrl":null}'URL 要求
| 参数 | 类型 | 描述 |
|---|---|---|
mediaWebhookUrl | HTTPS URL | 公开的 HTTPS 地址;会拒绝私有/环回地址和我们自己的域名(SSRF 防护),并在每次发送前重新检查该地址。空字符串或 null 会将其重置。 |
balanceWebhookUrl | HTTPS URL | 用于低余额通知的独立 webhook(非媒体),使用相同的账户密钥签名,x-pv-event: balance.low。阈值为 balanceWebhookThresholdRub。 |
作业完成时通过 Webhook 传送
当作业达到终止状态时,GetVibe 会创建一个逻辑事件,并通过 POST 将其传送到已注册的 mediaWebhookUrl。传送次数有限:服务总共最多尝试 5 次。同一有效负载可能会到达多次。
// POST to your mediaWebhookUrl when a job finishes
{
"jobId": "...",
"status": "success", // or "fail"
"model": "veo-3.1",
"kind": "video", // image | video | audio | music | 3d
"resultUrls": ["https://getvibeapi.com/api/media/file/..."],
"failMsg": null,
"createdAt": "2026-06-17T10:00:00.000Z"
}传递行为(与代码一致)
| 参数 | 类型 | 描述 |
|---|---|---|
Signature / auth | — | 每次发送都会使用 Standard Webhooks 签名:webhook-id、webhook-timestamp 和 webhook-signature 标头(v1,对“id.timestamp.body”进行 HMAC-SHA256 后再进行 base64 编码)。账户密钥显示在控制面板 → Webhooks 中,并通过 GET /api/media/webhook-secret 以 accountSecret 的形式返回给 API 密钥;发送到单次请求的 webhook_url 的通知使用该密钥的 secret 字段签名。若签名错误或时间戳早于 5 分钟前,请拒绝请求。 |
Retries | outbox | 总计最多 5 次尝试;失败后的间隔:1、2、4、8 分钟。尝试次数用尽后,事件将移至 FAILED,并且不再自动投递。轮询 GET /api/media/jobs/{id} 仍是状态来源。 |
Receiver dedup | required | 根据 jobId + status 组合去重,并使处理程序具备幂等性。不要将 webhook 作为唯一状态来源。 |
Content-Type | application/json | 正文为 JSON,包含字段 jobId、status、model、kind、resultUrls、failMsg、createdAt。 |
POST /api/media/generate 错误
| HTTP | 何时 | 费用 | 重试 |
|---|---|---|---|
| 202 | 作业已接受(ok: true, jobId) | 否(仅在成功后) | — |
| 400 | 无效的 JSON / 请求正文 | 否 | 修复请求 |
| 401 | 缺少或无效的 API 密钥 | 否 | 检查 Authorization |
| 402 | 余额不足(准入) | 否 | 充值余额 |
| 422 | 未知模型、无效 opts,facade 返回 ok: false | 否 | Fix model/opts |
| 502 | media_submit_failed — 上游不可用 | 否 | 使用退避重试 |
| 503 | priceUnavailable、路由保护、VIDEO_DISABLED、没有价格的 veo | 否 | 其他模型 / 稍后 |
轮询错误和终止失败
| HTTP / 状态 | 含义 | 费用 |
|---|---|---|
| 404 | 找不到任务,或 jobId 属于其他用户 | 否 |
| processing | 任务仍在运行 | 否 |
| success | 完成,resultUrls 已填充 | 是,在响应中返回 priceRub |
| fail | 生成失败 | No (priceRub = 0) |
计费与幂等性
- 成功时只收费一次。 在
finalizeJob中,转换processing → success|fail是原子的:重复回调或轮询不会产生第二次收费。 - fail — 免费。 状态为 fail 时不会扣费。
- 入站报价。 如果创建时保存了报价,则成功时会严格按该报价收费(绝不会超过上游实际计量的费用)。
- 通过 header 创建幂等性。 向 /api/media/generate 重复发送不带该 header 的 POST 请求,会在成功时创建新的任务并产生新的费用。请发送
Idempotency-Key(最多 255 个 ASCII 字符):在 24 小时内使用相同 key 和请求体重试时,会返回相同的 jobId,不会创建新任务;相同 key 搭配不同请求体会返回 422,而在第一个请求仍在处理时会返回 409。付费生成的 jobId 也会显示在 GET /v1/generations 中(job_id 字段)。 - Webhook 最多尝试五次。 每次终止状态转换都会创建一个逻辑事件,但投递尝试可能重复。五次失败后,事件状态会变为
FAILED。客户端处理程序必须对jobId + status这一对值进行去重。