وثائق Rivya AI

خطافات Webhook لواجهة API

أنشئ نقاط Webhook موقعة لواجهة Rivya API، وتحقق من توقيعات التسليم، وافحص محاولات التسليم، وأرسل أحداث اختبار آمنة.

آخر مراجعة في 2026/05/11

استخدم خطافات Webhook لواجهة API عندما يحتاج تكاملك إلى أن تخطر Rivya خادمك بعد وصول توليد Public API إلى حالة نهائية.

يبقى استطلاع GET /api/v1/generations/{taskId} مدعوما. تضيف Webhooks استدعاءات راجعة موقعة لأنظمة الإنتاج التي تفضل تسليم الأحداث.

النطاق المطلوب

تتطلب إدارة Webhook مفتاح API يتضمن:

webhooks:manage

تتضمن المفاتيح الجديدة التي تنشأ في Settings هذا النطاق افتراضيا.

إنشاء نقطة Webhook

POST /api/v1/webhooks
curl 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"]
  }'

تتضمن الاستجابة signing_secret مرة واحدة فقط:

{
  "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
}

خزن السر الكامل على خادمك. إذا فقدته، فاستدع نقطة التدوير وحدث المستقبل لديك.

قواعد URL

يجب أن تكون عناوين نقاط Webhook عبر HTTPS. ترفض Rivya العناوين التي تحتوي على بيانات اعتماد، أو أجزاء fragment، أو أسماء localhost، أو عناوين شبكة محلية، أو نطاقات IP خاصة، أو عناوين loopback، أو عناوين محجوزة.

ترسل Rivya دائما:

  • POST
  • Content-Type: application/json
  • من دون رؤوس طلب مخصصة يتحكم فيها المستخدم
  • من دون اتباع عمليات إعادة التوجيه تلقائيا
  • مهلة تسليم قصيرة

الأحداث

أنواع الأحداث الحالية:

  • generation.succeeded
  • generation.failed

تستخدم حمولات Webhook نفس مسلسِل التوليد العام المستخدم في نقطة الحالة.

{
  "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
    }
  }
}

رؤوس التسليم

يتضمن كل تسليم:

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_...

مدخل التوقيع:

${timestamp}.${rawBody}

الخوارزمية:

HMAC-SHA256 with the endpoint signing secret

ارفض الطلبات ذات الطوابع الزمنية القديمة. يعد هامش خمس دقائق افتراضا عمليا.

التحقق في 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"));
}

التحقق في 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)

إدارة نقاط Webhook

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-secret
curl 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} نقطة Webhook. ولا يحذف سجل التسليم.

سجلات التسليم

اسرد الأحداث الأخيرة:

GET /api/v1/webhook-events
curl https://rivya.ai/api/v1/webhook-events \
  -H "Authorization: Bearer rvya_sk_..."

اسرد محاولات التسليم لنقطة Webhook:

GET /api/v1/webhooks/{endpointId}/deliveries
curl https://rivya.ai/api/v1/webhooks/whend_.../deliveries \
  -H "Authorization: Bearer rvya_sk_..."

تتضمن سجلات التسليم الحالة، وحالة HTTP، ورقم المحاولة، ومعرف الطلب، والمدة، ومقتطف الاستجابة المختصر، وحقول الخطأ العامة.

حدث الاختبار

أرسل payload اختبار آمنا:

POST /api/v1/webhooks/{endpointId}/test
curl -X POST https://rivya.ai/api/v1/webhooks/whend_.../test \
  -H "Authorization: Bearer rvya_sk_..."

يستخدم حدث الاختبار webhook.test. لا ينشئ مهمة توليد، ولا يستهلك رصيدا، ولا يتضمن URL نتيجة حقيقيا.

سياسة إعادة المحاولة

تتعامل Rivya مع HTTP 2xx على أنه نجاح.

تشمل الإخفاقات أخطاء الشبكة، والمهلة، واستجابات redirect، والاستجابات غير 2xx. تعيد Rivya المحاولة حتى خمس محاولات:

  • فورا
  • بعد دقيقة واحدة
  • بعد 5 دقائق
  • بعد 30 دقيقة
  • بعد ساعتين

بعد المحاولة الأخيرة، يوسم الحدث بأنه failed.

لا تغير إخفاقات تسليم Webhook حالة التوليد، أو الرصيد، أو الاستردادات، أو سجل المهام.

قائمة التحقق الأمنية

  • تحقق من توقيع HMAC قبل تحليل منطق العمل.
  • ارفض الطوابع الزمنية القديمة.
  • عامل أحداث الاختبار بشكل منفصل عن أحداث التوليد.
  • لا تسجل أسرار التوقيع كاملة.
  • أعد 2xx فقط بعد أن يقبل المستقبل لديك الحدث.
  • أبق الاستطلاع كخيار احتياطي للمطابقة.

الصفحات ذات الصلة

جدول المحتويات