API Webhooks
Buat endpoint webhook Rivya API bertanda tangan, verifikasi signature delivery, periksa percobaan delivery, dan kirim event test yang aman.
Terakhir ditinjau pada 2026/05/11
Gunakan API webhooks saat integrasi Anda membutuhkan Rivya untuk memberi tahu server Anda setelah generasi Public API mencapai status terminal.
Polling GET /api/v1/generations/{taskId} tetap didukung. Webhooks menambahkan callback bertanda tangan untuk sistem production yang lebih memilih delivery event.
Scope yang Dibutuhkan
Pengelolaan webhook membutuhkan API key dengan:
webhooks:manageKey baru yang dibuat di Settings menyertakan scope ini secara default.
Membuat Endpoint
POST /api/v1/webhookscurl https://rivya.ai/api/v1/webhooks \
-H "Authorization: Bearer rvya_sk_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Production webhook",
"url": "https://example.com/rivya/webhook",
"event_types": ["generation.succeeded", "generation.failed"]
}'Respons menyertakan signing_secret hanya satu kali:
{
"id": "whend_...",
"object": "webhook_endpoint",
"name": "Production webhook",
"url": "https://example.com/rivya/webhook",
"event_types": ["generation.succeeded", "generation.failed"],
"status": "active",
"secret_preview": "whsec_12...abc123",
"signing_secret": "whsec_...",
"last_success_at": null,
"last_failure_at": null,
"failure_count": 0,
"created_at": "2026-05-11T00:00:00.000Z",
"updated_at": "2026-05-11T00:00:00.000Z",
"disabled_at": null,
"revoked_at": null
}Simpan secret lengkap di server Anda. Jika hilang, panggil endpoint rotate dan perbarui receiver Anda.
Aturan URL
URL endpoint harus HTTPS. Rivya menolak URL dengan credentials, fragments, nama localhost, alamat jaringan lokal, rentang IP privat, alamat loopback, dan alamat reserved.
Rivya selalu mengirim:
POSTContent-Type: application/json- tidak ada custom request headers yang dikendalikan pengguna
- tidak mengikuti redirect otomatis
- timeout delivery yang singkat
Event
Jenis event saat ini:
generation.succeededgeneration.failed
Payload webhook memakai serializer generasi publik yang sama dengan endpoint status.
{
"id": "evt_...",
"type": "generation.succeeded",
"api_version": "2026-05-11",
"created_at": "2026-05-11T00:00:00.000Z",
"data": {
"generation": {
"id": "task_public_id",
"status": "succeeded",
"model": "z-image",
"reserved_credits": 1,
"final_credits": 1,
"created_at": "2026-05-11T00:00:00.000Z",
"updated_at": "2026-05-11T00:01:00.000Z",
"result": {
"primary_url": "https://...",
"urls": ["https://..."]
},
"error": null
}
}
}Header Delivery
Setiap delivery menyertakan:
Rivya-Webhook-Id: evt_...
Rivya-Webhook-Timestamp: 1778467200
Rivya-Webhook-Signature: v1=<hex-hmac-sha256>
Rivya-Webhook-Attempt: 1
Rivya-Webhook-Endpoint-Id: whend_...
Rivya-Request-Id: req_...Input signature:
${timestamp}.${rawBody}Algoritma:
HMAC-SHA256 with the endpoint signing secretTolak request dengan timestamp lama. Toleransi lima menit adalah default praktis.
Verifikasi JavaScript
import crypto from "node:crypto";
function verifyRivyaWebhook({ rawBody, headers, signingSecret }) {
const timestamp = headers["rivya-webhook-timestamp"];
const signature = headers["rivya-webhook-signature"] || "";
const actual = signature.split(",").find((part) => part.startsWith("v1="))?.slice(3);
const expected = crypto
.createHmac("sha256", signingSecret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
if (!actual) return false;
return crypto.timingSafeEqual(Buffer.from(actual, "hex"), Buffer.from(expected, "hex"));
}Verifikasi Python
import hmac
import hashlib
def verify_rivya_webhook(raw_body: str, headers: dict, signing_secret: str) -> bool:
timestamp = headers.get("rivya-webhook-timestamp", "")
signature = headers.get("rivya-webhook-signature", "")
actual = next((part[3:] for part in signature.split(",") if part.startswith("v1=")), "")
expected = hmac.new(
signing_secret.encode(),
f"{timestamp}.{raw_body}".encode(),
hashlib.sha256,
).hexdigest()
return bool(actual) and hmac.compare_digest(actual, expected)Mengelola Endpoint
GET /api/v1/webhooks
GET /api/v1/webhooks/{endpointId}
PATCH /api/v1/webhooks/{endpointId}
DELETE /api/v1/webhooks/{endpointId}
POST /api/v1/webhooks/{endpointId}/rotate-secretcurl https://rivya.ai/api/v1/webhooks \
-H "Authorization: Bearer rvya_sk_..."
curl https://rivya.ai/api/v1/webhooks/whend_... \
-H "Authorization: Bearer rvya_sk_..."
curl -X PATCH https://rivya.ai/api/v1/webhooks/whend_... \
-H "Authorization: Bearer rvya_sk_..." \
-H "Content-Type: application/json" \
-d '{"status":"disabled"}'
curl -X POST https://rivya.ai/api/v1/webhooks/whend_.../rotate-secret \
-H "Authorization: Bearer rvya_sk_..."DELETE /api/v1/webhooks/{endpointId} menonaktifkan endpoint. Ini tidak menghapus riwayat delivery.
Record Delivery
Daftar event terbaru:
GET /api/v1/webhook-eventscurl https://rivya.ai/api/v1/webhook-events \
-H "Authorization: Bearer rvya_sk_..."Daftar percobaan delivery untuk endpoint:
GET /api/v1/webhooks/{endpointId}/deliveriescurl https://rivya.ai/api/v1/webhooks/whend_.../deliveries \
-H "Authorization: Bearer rvya_sk_..."Record delivery menyertakan status, HTTP status, attempt number, request id, duration, snippet respons yang dipotong, dan field error publik.
Event Test
Kirim payload test yang aman:
POST /api/v1/webhooks/{endpointId}/testcurl -X POST https://rivya.ai/api/v1/webhooks/whend_.../test \
-H "Authorization: Bearer rvya_sk_..."Event test memakai webhook.test. Event ini tidak membuat tugas generasi, tidak memakai credits, dan tidak menyertakan URL hasil nyata.
Kebijakan Retry
Rivya memperlakukan HTTP 2xx sebagai sukses.
Kegagalan mencakup error jaringan, timeout, respons redirect, dan respons non-2xx. Rivya mencoba ulang hingga lima kali:
- segera
- setelah 1 menit
- setelah 5 menit
- setelah 30 menit
- setelah 2 jam
Setelah percobaan terakhir, event ditandai failed.
Kegagalan delivery webhook tidak mengubah status generasi, credits, refund, atau riwayat tugas.
Checklist Keamanan
- Verifikasi signature HMAC sebelum memproses logika bisnis.
- Tolak timestamp lama.
- Perlakukan event test secara terpisah dari event generasi.
- Jangan mencatat signing secret lengkap.
- Kembalikan
2xxhanya setelah receiver Anda menerima event. - Pertahankan polling sebagai fallback untuk rekonsiliasi.
Halaman Terkait
Rivya TypeScript SDK
Gunakan beta Rivya TypeScript SDK untuk memanggil Public API v1 bagi models, generations, files, credits, webhooks, dan Chat termasuk streaming SSE.
Ikhtisar Rivya API
Gunakan Rivya API v1 untuk memanggil model generasi dan chat Rivya dari produk Anda sendiri dengan API key, credits akun, dan streaming SSE opsional.