Webhooks とメディアジョブのライフサイクル
mediaWebhookUrl を登録し、ジョブ完了時に POST を受信して GET /api/media/jobs/{id} をポーリングし、エラーコードを処理して、課金と冪等性の制限を理解します。
非同期メディアジョブの操作ガイド: webhook の登録、ステータス、ポーリング、エラーコード、課金、冪等性の制限 — すべてコード内の現在の実装に厳密に準拠しています。
ジョブのライフサイクル
- POST /api/media/generate — 成功時は
202と{ ok: true, jobId, status: "processing" }。queued/runningという個別のステータスは API にはありません。ジョブが完了するまで、クライアントには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 | string[] | 署名付き URL /api/media/file/{id}/{idx}?sig=…(API キー不要)。 |
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 秒、最大 30 秒の指数バックオフを併用します。クライアント側のタイムアウトはアプリケーションの SLA に従ってください(動画生成には数分かかることがあります)。
Webhook の登録
GEThttps://getvibeapi.com/api/webhooks
PATCHhttps://getvibeapi.com/api/webhooks
アカウントごとに 1 つの 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です(media用ではありません)。同じアカウントシークレットで署名され、x-pv-event: balance.lowが使用されます。しきい値はbalanceWebhookThresholdRubです。 |
ジョブ完了時の Webhook 配信
ジョブが終端ステータスに達すると、GetVibe は 1 つの論理イベントを作成し、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、base64 HMAC-SHA256の「id.timestamp.body」)が使用されます。アカウントシークレットはダッシュボード → Webhooksに表示され、GET /api/media/webhook-secretによってAPIキーにaccountSecretとして返されます。リクエストごとのwebhook_urlへの配信は、そのキーのシークレット(secretフィールド)で署名されます。署名が正しくない場合、またはtimestampが5分を超えて古い場合は、リクエストを拒否してください。 |
Retries | outbox | 合計最大 5 回の試行。失敗後の間隔は 1、2、4、8 分です。試行を使い切ると、イベントは FAILED に移行し、自動配信は行われなくなります。状態のソースは引き続き GET /api/media/jobs/{id} によるポーリングです。 |
Receiver dedup | required | jobId + status のペアで重複を排除し、ハンドラーを冪等にしてください。Webhook を状態の唯一の情報源として使用しないでください。 |
Content-Type | application/json | ボディは、jobId、status、model、kind、resultUrls、failMsg、createdAtのフィールドを持つJSONです。 |
POST /api/media/generate のエラー
| HTTP | タイミング | 課金 | 再試行 |
|---|---|---|---|
| 202 | ジョブを受け付けました(ok: true, jobId) | いいえ (成功後のみ) | — |
| 400 | 無効なJSON / リクエストボディ | いいえ | リクエストを修正する |
| 401 | API キーが欠落しているか無効です | いいえ | Authorizationを確認 |
| 402 | 残高不足(受付時) | いいえ | 残高をチャージする |
| 422 | 不明なモデル、無効な opts、ファサードからの 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) |
請求と冪等性
- 成功時に1回だけ課金されます。
finalizeJobでは、遷移processing → success|failはアトミックです。コールバックやポーリングを繰り返しても、2回目の課金は発生しません。 - fail — 無料。 fail ステータスでは引き落としは行われません。
- 受付時の見積もり。 作成時に見積もりが保存されていた場合、成功時にはまさにその額が課金されます(実際の上流での計測額を超えることはありません)。
- 冪等性の作成 — ヘッダーによる指定。 ヘッダーなしで /api/media/generate に POST を繰り返すと、新しいジョブが作成され、成功時に新たな課金が発生します。
Idempotency-Keyを送信してください(最大255 ASCII文字)。同じキーと同じボディで24時間以内に再試行すると、新しいジョブを作成せずに同じ jobId が返されます。同じキーでボディが異なる場合は 422、最初のリクエストがまだ処理中の場合は 409 です。有料生成の jobId は GET /v1/generations でも表示されます(job_id フィールド)。 - Webhook は最大 5 回の試行に制限されます。 論理イベントは終端遷移ごとに 1 つ作成されますが、配信の試行は繰り返されることがあります。5 回失敗すると、イベントのステータスは
FAILEDになります。クライアントのハンドラーはjobId + statusのペアを重複排除する必要があります。