Tema
Bahasa

Webhook dan siklus hidup pekerjaan media

Daftarkan mediaWebhookUrl, terima POST saat job selesai, polling GET /api/media/jobs/{id}, tangani kode error, dan pahami penagihan serta batas idempotensi.

Panduan operasional untuk job media asinkron: pendaftaran webhook, status, polling, kode error, biaya, dan batas idempotensi — sepenuhnya sesuai implementasi saat ini di dalam kode.

Siklus hidup job

  1. POST /api/media/generate — saat berhasil 202 dan { ok: true, jobId, status: "processing" }. Tidak ada status queued / running terpisah di API: sampai job selesai, klien melihat processing.
  2. Upstream dapat melewati tahap internal (waiting, generating) — ini tidak tercermin di API publik; selama polling, job tetap processing.
  3. Status terminal: success (memiliki resultUrls, dikenai biaya saat berhasil) atau fail (tanpa biaya).
  4. Penyelesaian dicatat sekali: melalui callback upstream atau pada polling lazy di GET /api/media/jobs/{id}.

Polling: GET /api/media/jobs/{id}

GEThttps://getvibeapi.com/api/media/jobs/{id}
ParameterTipeDeskripsi
statusstringsubmitting | 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.
resultUrlsstring[]URL bertanda tangan /api/media/file/{id}/{idx}?sig=… (tanpa kunci API).
priceRubnumberJumlah biaya dalam USD (0 jika gagal atau sebelum selesai).
failMsgstring | nullPesan aman saat gagal atau media_submission_uncertain non-terminal.
errorCodestring | nullKode error (media_generation_failed) atau media_submission_uncertain non-terminal.
retryGuidancestring | nullPada media_submission_uncertain: instruksi aman untuk melakukan polling ke jobId yang sama nanti dan tidak membuat duplikat secara otomatis.
# 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":...}
Interval polling yang direkomendasikan: 3–5 s, dengan exponential backoff hingga 30 s. Timeout di sisi klien sesuai SLA aplikasi Anda (pembuatan video dapat memakan waktu beberapa menit).

Pendaftaran webhook

GEThttps://getvibeapi.com/api/webhooks
PATCHhttps://getvibeapi.com/api/webhooks

Satu URL per akun: mediaWebhookUrl. Dikonfigurasi di dashboard → Webhooks atau melalui API dengan sesi akun (cookie setelah login). Endpoint tidak menerima sk-pv-… — hanya sesi yang terautentikasi.

# 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}'
Persyaratan URL
ParameterTipeDeskripsi
mediaWebhookUrlURL HTTPSAlamat HTTPS publik; alamat privat/loopback dan domain kami sendiri ditolak (perlindungan SSRF), dan alamat tersebut diperiksa ulang sebelum setiap pengiriman. String kosong atau null akan meresetnya.
balanceWebhookUrlURL HTTPSWebhook terpisah untuk saldo rendah (bukan media), ditandatangani dengan secret akun yang sama, x-pv-event: balance.low. Ambangnya adalah balanceWebhookThresholdRub.

Pengiriman webhook saat pekerjaan selesai

Saat pekerjaan mencapai status terminal, GetVibe membuat satu peristiwa logis dan mengirimkannya melalui POST ke mediaWebhookUrl yang terdaftar. Pengiriman dibatasi: layanan melakukan hingga 5 percobaan total. Payload yang sama dapat tiba lebih dari sekali.

// 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"
}
Perilaku pengiriman (sesuai kode)
ParameterTipeDeskripsi
Signature / auth—Setiap pengiriman ditandatangani dengan Standard Webhooks: header webhook-id, webhook-timestamp, dan webhook-signature (v1, HMAC-SHA256 dalam base64 dari “id.timestamp.body”). Secret akun ditampilkan di dasbor → Webhooks dan dikembalikan ke kunci API sebagai accountSecret oleh GET /api/media/webhook-secret; pengiriman ke webhook_url per permintaan ditandatangani dengan secret kunci tersebut (field secret). Tolak permintaan dengan signature yang salah atau timestamp yang lebih lama dari 5 menit.
RetriesoutboxHingga 5 percobaan total; interval setelah kegagalan: 1, 2, 4, 8 menit. Setelah percobaan habis, event berpindah ke FAILED dan tidak lagi dikirimkan secara otomatis. Polling GET /api/media/jobs/{id} tetap menjadi sumber status.
Receiver deduprequiredDeduplikasi berdasarkan pasangan jobId + status dan buat handler Anda idempoten. Jangan gunakan webhook sebagai satu-satunya sumber status.
Content-Typeapplication/jsonBody berupa JSON dengan field jobId, status, model, kind, resultUrls, failMsg, createdAt.

Error POST /api/media/generate

HTTPKapanBiayaRetry
202Job diterima (ok: true, jobId)Tidak (hanya setelah berhasil)—
400JSON / body permintaan tidak validTidakPerbaiki permintaan
401Kunci API tidak ada atau tidak validTidakPeriksa Authorization
402Saldo tidak cukup (admission)TidakIsi ulang saldo
422Model tidak dikenal, opts tidak valid, ok: false dari fasadTidakFix model/opts
502media_submit_failed — upstream tidak tersediaTidakRetry with backoff
503priceUnavailable, routing guard, VIDEO_DISABLED, veo tanpa hargaTidakModel lain / versi lebih baru

Error polling dan kegagalan terminal

HTTP / statusArtiBiaya
404job tidak ditemukan atau jobId milik pihak lainTidak
processingJob masih berjalanTidak
successSelesai, resultUrls terisiYa — priceRub dalam respons
failPembuatan gagalNo (priceRub = 0)

Penagihan dan idempotensi

  • Ditagih sekali saat berhasil. Di finalizeJob transisi processing → success|fail bersifat atomik: callback atau poll yang berulang tidak menciptakan tagihan kedua.
  • fail — gratis. Tidak ada pendebitan yang dilakukan pada status fail.
  • Kutipan penerimaan. Jika kutipan disimpan saat pembuatan, tepat itulah yang ditagih saat berhasil (tidak pernah lebih dari metering upstream yang sebenarnya).
  • Idempotensi create — melalui header. POST berulang ke /api/media/generate tanpa header tersebut akan membuat job baru dan tagihan baru saat berhasil. Kirim Idempotency-Key (hingga 255 karakter ASCII): percobaan ulang dengan key dan body yang sama dalam 24 jam mengembalikan jobId yang sama tanpa job baru; key yang sama dengan body berbeda menghasilkan 422, dan 409 selama permintaan pertama masih diproses. jobId dari generasi berbayar juga ditampilkan di GET /v1/generations (field job_id).
  • Webhook dibatasi maksimal lima percobaan. Satu event logis dibuat per transisi terminal, tetapi percobaan pengiriman bisa berulang. Setelah lima kegagalan, event mendapat status FAILED . Handler di sisi klien harus melakukan deduplikasi terhadap pasangan jobId + status.
Lihat juga: Media generation, Media model catalog, Errors and limits (kode 401/402/429 umum untuk /v1).
Webhook media GetVibe API — status, error, penagihan | GetVibe API