الويبهوك

احصل على إشعار موقَّع عند انتهاء عملية توليد في Direct API، وتحقق منه، واقرأ عملية التوليد للاطلاع على تفاصيلها.

الويبهوك نقطة نهاية HTTPS خاصة بك تستدعيها Morphic عندما تبلغ عملية توليد حالة نهائية. التسليمات موقَّعة، ويُعاد إرسالها لمدة يوم تقريبًا، وتُسجَّل. كل حدث إشعار مقتضب: يذكر أي عملية توليد انتهت وكيف، ثم تقرأ عملية التوليد بمفتاحك للاطلاع على أصولها وفوترتها ورسالة الخطأ.

تسجيل نقطة نهاية

يحتاج POST /v1/direct/webhooks إلى النطاق generations:write.

curl -s https://mcp.morphic.com/v1/direct/webhooks \
  -H "Authorization: Bearer $MORPHIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "url": "https://hooks.example.com/morphic",
        "events": ["generation.succeeded", "generation.failed", "generation.cancelled"],
        "description": "Production order pipeline"
      }'
الحقلالقواعد
urlHTTPS على مضيف عام (بلا عناوين IP حرفية، وبلا عناوين خاصة أو محلية)، حتى 2,048 حرفًا
eventsنوع حدث واحد أو أكثر
descriptionاختياري، حتى 200 حرف

الاستجابة هي 201:

{
  "webhook": {
    "id": "01929a10-0c3d-7f44-8a21-0b1c2d3e4f50",
    "url": "https://hooks.example.com/morphic",
    "events": ["generation.succeeded", "generation.failed", "generation.cancelled"],
    "description": "Production order pipeline",
    "created_at": "2026-10-25T08:00:00.000Z",
    "signing_secret": "whsec_4b1e…"
  }
}
  • لا يظهر signing_secret إلا في هذه الاستجابة. خزّنه كما تخزّن مفتاح API.
  • لتدوير السر، سجّل نقطة نهاية جديدة، وانقل استدعاءاتك إلى معرّفها، ثم احذف القديمة.
  • يجوز للمؤسسة أن تحتفظ بما يصل إلى 10 نقاط نهاية.

إدارة نقاط النهاية

الطلبالنطاقالوظيفة
GET /v1/direct/webhooksassets:readيسرد نقاط النهاية بصيغة { "webhooks": [ … ] }، دون أسرارها أبدًا
DELETE /v1/direct/webhooks/{webhook_id}generations:writeيزيل نقطة النهاية؛ وتُترك التسليمات المعلقة إليها

ربط نقطة نهاية باستدعاء

مرّر webhook_id في جسم استدعاء الأداة. تُسلَّم كل عملية توليد يبدأها ذلك الاستدعاء إلى نقطة النهاية تلك عندما تبلغ حالة نهائية اشتركت فيها نقطة النهاية. والاستدعاءات التي لا تحمل webhook_id لا ترسل أي ويبهوك.

الأدوات التي تعرض الفيديو على خوادم Morphic (video_compose وتحويلات video_* وburn_subtitles) لا تقبل webhook_id بعد؛ استطلع عمليات التوليد الخاصة بها.

أنواع الأحداث

الحدثيُرسَل عندما
generation.succeededانتهت عملية التوليد بمخرجات
generation.failedفشلت عملية التوليد؛ ويُسترد المبلغ المخصوم
generation.cancelledأُلغيت عملية التوليد؛ ويُسترد المبلغ المخصوم
  • تنتج كل عملية توليد حدثًا واحدًا على الأكثر.
  • لا تُسلَّم queued وin_progress؛ استطلعها إن كنت تحتاجها.
  • تُراقَب عملية التوليد لمدة 72 ساعة بعد بدئها. والتي تنتهي بعد ذلك لا ترسل أي حدث، فاقرأها بدلًا من ذلك.

التسليم

POST /morphic HTTP/1.1
Host: hooks.example.com
Content-Type: application/json
User-Agent: Morphic-Webhooks/1.0
Morphic-Event-Id: 0192a7c0-5d4e-7b3a-8c2d-1e0f9a8b7c6d
Morphic-Delivery-Id: 0192a7c0-6e5f-7c4b-9d3e-2f1a0b9c8d7e
Morphic-Event-Type: generation.succeeded
Morphic-Signature: t=1792919741,v1=5f8a0c…e21b

{
  "id": "0192a7c0-5d4e-7b3a-8c2d-1e0f9a8b7c6d",
  "type": "generation.succeeded",
  "created_at": "2026-10-25T09:15:42.410Z",
  "api_version": "v1",
  "data": {
    "generation": {
      "object": "generation",
      "id": "0192a7b3-a1c4-7e02-8f9d-1a2b3c4d5e6f",
      "tool": "generate_video",
      "status": "succeeded",
      "completed_at": "2026-10-25T09:15:41.902Z",
      "error_code": null,
      "metadata": { "order_id": "4411" }
    }
  }
}

لا يحمل data.generation إلا هذه الحقول:

الحقلالمعنى
object، id، tool، status، completed_at، metadataكما في كائن عملية التوليد
error_codenull، أو رمز عملية توليد في حالة failed

لا يحمل الحدث أبدًا المخرجات أو الروابط أو الفوترة أو النموذج أو رسالة الخطأ، لذا فإن التسليم الذي يصل إلى المكان الخطأ أو إلى سجل لا يكشف شيئًا. عند الاستلام، اقرأ عملية التوليد بمفتاحك: GET /v1/direct/generations/{id}، أو القراءة المجمّعة لعدة عمليات. وبحلول وقت إرسال الحدث لا يتبقى شيء مستحق على فوترته، لذا تكون تلك القراءة نهائية.

الترويسةالمعنى
Morphic-Event-Idمعرّف الحدث، متطابق في كل إعادة محاولة؛ أزِل التكرار بناءً عليه
Morphic-Delivery-Idهذه المحاولة بعينها؛ يختلف في كل إعادة محاولة
Morphic-Event-Typeقيمة type في الجسم
Morphic-Signaturet=<unix seconds>,v1=<hex HMAC-SHA256>

يُرسَل الحدث عادةً في غضون دقيقة تقريبًا من بلوغ عملية التوليد حالتها النهائية. وهو ليس تدفقًا في الوقت الفعلي: للحصول على أقل زمن انتقال لعملية توليد واحدة تنتظرها، استطلعها استطلاعًا طويلًا.

التحقق من التوقيع

v1 هو HMAC-SHA256 بالصيغة الست عشرية، بمفتاح signing_secret الخاص بنقطة النهاية، للسلسلة {t}.{raw request body}.

  1. قسّم الترويسة عند , إلى t وv1.
  2. احسب HMAC_SHA256(secret, t + "." + raw_body) على البايتات الخام التي استلمتها، قبل أي تحليل لـ JSON أو إعادة تسلسل.
  3. قارنه بـ v1 في زمن ثابت.
  4. ارفض التسليم إذا كان t يبعد أكثر من 5 دقائق عن الوقت الحالي، لمنع إعادة الإرسال.
import crypto from 'node:crypto';
import express from 'express';

const app = express();

app.post('/morphic', express.raw({ type: 'application/json' }), (req, res) => {
  const header = req.get('Morphic-Signature') ?? '';
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const expected = crypto
    .createHmac('sha256', process.env.MORPHIC_WEBHOOK_SECRET)
    .update(`${parts.t}.${req.body}`)
    .digest('hex');

  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) <= 300;
  const valid =
    parts.v1?.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected));

  if (!fresh || !valid) return res.sendStatus(400);

  const event = JSON.parse(req.body);
  enqueue(event); // process asynchronously, keyed by event.id
  res.sendStatus(204);
});

نقطة النهاية غير المتحقق منها باب مفتوح: يستطيع أي شخص يعرف عنوان URL الخاص بها أن يخبرك بأن عملية توليد قد انتهت. تحقق من كل توقيع، وارفض أي طابع زمني يزيد عمره على 5 دقائق.

الرد وإعادة المحاولات

  • أجب بأي 2xx خلال 10 ثوانٍ، ثم أنجز العمل.
  • أي شيء آخر محاولة فاشلة: حالة غير 2xx، أو انتهاء المهلة، أو رفض الاتصال، أو خطأ TLS.
  • لا تُتبَع عمليات إعادة التوجيه؛ وتُعد 3xx محاولة فاشلة.
  • الترتيب غير مضمون، وقد يصل الحدث أكثر من مرة. اجعل المعالج لديك آمنًا للتكرار بناءً على Morphic-Event-Id، أو على data.generation.id، لأن لكل عملية توليد حدثًا واحدًا على الأكثر.

يُعاد إرسال المحاولة الفاشلة بعد:

إعادة المحاولة1234567
الانتظار بعد المحاولة السابقة1 دقيقة5 دقائق15 دقيقة1 ساعة3 ساعات6 ساعات12 ساعة

بعد إعادة المحاولة السابعة، أي بعد نحو 22 ساعة من المحاولة الأولى، يُترك الحدث. ولا تتأثر عملية التوليد نفسها: اقرأها عبر GET /v1/direct/generations/{id}.

سجل التسليم

يعيد GET /v1/direct/webhooks/{webhook_id}/events (النطاق assets:read) أحدث 20 حدثًا لنقطة النهاية، لكل منها الجسم المرسَل بالضبط ونتيجة كل محاولة. أضف ?generation_id=… لأحداث عملية توليد واحدة.

{
  "webhook_events": [
    {
      "id": "0192a7c0-5d4e-…",
      "type": "generation.succeeded",
      "generation_id": "0192a7b3-…",
      "status": "delivered",
      "created_at": "2026-10-25T09:15:42.410Z",
      "payload": { "…": "the body that was sent" },
      "attempts": [
        { "id": "0192a7c0-6e5f-…", "attempted_at": "2026-10-25T09:15:42.900Z", "response_status": 204, "duration_ms": 131, "error": null, "response_body_excerpt": null }
      ]
    }
  ]
}
status الحدثالمعنى
pendingلم يُسلَّم بعد؛ وقد تتبعه محاولات أخرى
deliveredأجابت نقطة النهاية لديك بـ 2xx
abandonedفشلت آخر إعادة محاولة، أو أُزيلت نقطة النهاية
skippedلم تشترك نقطة النهاية في نوع الحدث ذلك

الويبهوك هو الإشارة الأرخص والأسرع، لا الضمان. احتفظ باستطلاع عرضي لعمليات التوليد التي لم تتلقَّ خبرها كشبكة أمان.


إذا واجهت أي مشكلة أو كانت لديك أي أسئلة، فلا تتردد في التواصل معنا. يسعدنا مساعدتك. اكتب لنا على support@morphic.com.

في هذه الصفحة