HyoNovaالتوثيق

Webhooks

استقبل أحداث هيو ميل الموقّعة على نقطة HTTPS لديك — التسليم والتفاعل وجهات الاتصال والتحويلات وأحداث المتجر — وتحقق من التوقيع وتعامل مع إعادة المحاولة.

متاحيعمل اليوم لمساحات العمل التي تتضمنه خطتها.مرجعلمن: المطورون، تقنية المعلومات والأمان، المديرون العامونآخر تحديث: أُضيفت في:
في هذه الصفحة

تتيح Webhooks لـ HyoNova أن يُبلغ أنظمتك عند وقوع حدث ما، بدل أن تسأل أنظمتك مراراً. وهي جزء من هيو ميل: تُبلغ عن أحداث الرسائل المرسلة عبر واجهة Mail البرمجية، ومستلمي الحملات، وجهات الاتصال، والطلبات القادمة من متجر مربوط.

من يستطيع إعدادها#

يحتاج إنشاء Webhooks وتعديلها وحذفها إلى صلاحية إدارة البريد — وهي افتراضياً للمالكين والمديرين العامين.

إنشاء Webhook#

  1. افتح Webhooks. انتقل إلى البريد › الأتمتة وافتح تبويب Webhooks.
  2. أضف نقطة نهاية. اختر ويب هوك جديد، وأدخل عنوان نقطة النهاية لديك ووصفاً اختيارياً.
  3. اختر الأحداث. حدّد الأحداث التي تريدها. لا تتلقى نقطة النهاية إلا الأحداث التي اشتركت فيها.
  4. انسخ السر. بعد الحفظ يُعرض سر الويب هوك مرة واحدة. احفظه في مدير الأسرار لديك، فأنت تحتاجه للتحقق من التواقيع.

يجب أن تستخدم نقطة النهاية https:// وأن تشير إلى عنوان عام على الإنترنت. تُرفض العناوين الخاصة وعناوين الحلقة المحلية والعناوين الداخلية بالرمز WEBHOOK_HOST_NOT_ALLOWED عند الحفظ، ويُعاد فحصها قبل كل تسليم.

يغيّر تعديل الويب هوك العنوانَ أو الأحداث أو مفعّل. وتعرض التسليمات آخر التسليمات مع الحدث والحالة والمحاولات ورمز HTTP الذي ردّت به نقطة النهاية.

تدوير السر#

يُصدر تدوير السر سراً جديداً ويعرضه مرة واحدة. وخلال الـ 24 ساعة التالية يُوقَّع كل تسليم بالسر الجديد والسر السابق معاً — فتحمل الترويسة قيمتين لـ v1 — لتنقل نقطة النهاية إلى السر الجديد دون أن تفقد أحداثاً. وبعد 24 ساعة يوقّع السر الجديد وحده.

الأحداث#

الحدثيُرسل عندماحقول data
sentقبلت خدمة البريد الرسالةالمعاملاتية: messageId وemail وoccurredAt. الحملات: campaignId وrecipientId وcontactId وemail وoccurredAt
deliveredقبلها خادم بريد المستلمكما في sent
bouncedارتدّت نهائياً، ويُحجب العنوانكما في sent
complaintأبلغ المستلم أنها مزعجة، ويُحجب العنوانكما في sent
failedلم تُرسل، أو رفضتها خدمة البريدكما في sent، مع error للرسائل المعاملاتية
openedفتح مستلم الحملة الرسالة أول مرةحقول الحملة
clickedنقر مستلم الحملة رابطاً متتبَّعاً أول مرةحقول الحملة، مع linkId
unsubscribedألغى مستلم الحملة اشتراكهحقول الحملة
message.acceptedقبلت خدمة البريد رسالة معاملاتيةmessageId وemail وproviderMessageId وoccurredAt
campaign.sentانتهى إرسال حملةcampaignId وaccepted وfailed وsuppressed وskipped وunknown وoccurredAt
campaign.clickكل نقرة على رابط حملة متتبَّع، لا الأولى فقطحقول الحملة، مع linkId وsuspect (‏true عندما تبدو النقرة آلية)
contact.updatedأُنشئت جهة اتصال أو تغيّرت عبر الواجهة البرمجية أو ربط متجرcontactId وemail وstatus وsource وchange (created أو updated أو consent) وoccurredAt
conversion.recordedسُجّل تحويل أو عُدّلconversion، ومع الاسترداد أيضاً adjustment وnetRevenue
order.eventأرسل متجر مربوط أي حدث طلبintegrationId وprovider وorder
order.createdأبلغ متجر مربوط عن طلب جديدكما في order.event
order.paidأبلغ متجر مربوط عن طلب مدفوعكما في order.event

الطلب#

يرسل HyoNova كل حدث في طلب HTTP من نوع POST بمحتوى JSON:

http
POST /your/endpoint HTTP/1.1
Content-Type: application/json
User-Agent: HyoNova-Mail-Webhooks/1.0
HyoNova-Signature: t=1792270000,v1=5d41402abc4b2a76b9719d911017c592...
HyoNova-Delivery: 0f8e7d6c-5b4a-4321-9876-0123456789ab
HyoNova-Attempt: 1
json
{
  "id": "0f8e7d6c-5b4a-4321-9876-0123456789ab",
  "event": "delivered",
  "occurredAt": "2026-10-18T09:30:05.000Z",
  "data": {
    "messageId": "6f1c2d4e-9a7b-4c1d-8e2f-3a4b5c6d7e8f",
    "email": "name@example.com",
    "occurredAt": "2026-10-18T09:30:05.000Z"
  }
}
  • id هو معرّف التسليم. ويظهر أيضاً في الترويسة HyoNova-Delivery، ويبقى نفسه عند إعادة المحاولة، فاستخدمه لتجاهل التكرار.
  • HyoNova-Attempt هو رقم المحاولة، ويبدأ من 1.

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

تأخذ HyoNova-Signature الشكل t=<ثوانٍ بتوقيت يونكس>,v1=<التوقيع>. والتوقيع هو HMAC-SHA256 بصيغة hex للنص <t>.<محتوى الطلب الخام> بمفتاح سر الويب هوك. وأثناء تدوير السر تحمل الترويسة قيمتين لـ v1؛ اقبل الطلب إذا طابقت أيٌّ منهما.

للتحقق من طلب:

  1. اقرأ المحتوى الخام كما وصل تماماً، قبل أي تحليل JSON.
  2. احسب HMAC-SHA256 للنص t + "." + body بالسر، بصيغة hex.
  3. قارنه بكل قيمة v1 مقارنةً ثابتة الزمن، وارفض الطلب إن لم تطابق أي قيمة.
  4. ارفض الطلبات التي تبتعد قيمة t فيها أكثر من خمس دقائق عن ساعتك، لمنع إعادة الإرسال.
Node.js / TypeScript
import { createHmac, timingSafeEqual } from 'node:crypto';
import { createServer } from 'node:http';

export function verifyHyoMailSignature(rawBody: string, header: string, secret: string, toleranceSeconds = 300): boolean {
  const parts = header.split(',').map((p) => p.trim());
  const t = parts.find((p) => p.startsWith('t='))?.slice(2) ?? '';
  const signatures = parts.filter((p) => p.startsWith('v1=')).map((p) => p.slice(3));
  if (!/^\d+$/.test(t) || signatures.length === 0) return false;
  if (Math.abs(Math.floor(Date.now() / 1000) - Number(t)) > toleranceSeconds) return false;
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
  return signatures.some((s) => {
    const given = Buffer.from(s, 'hex');
    return given.length === expected.length && timingSafeEqual(given, expected);
  });
}

createServer((req, res) => {
  const chunks: Buffer[] = [];
  req.on('data', (chunk) => chunks.push(chunk));
  req.on('end', () => {
    const raw = Buffer.concat(chunks).toString('utf8');
    const header = String(req.headers['hyonova-signature'] ?? '');
    if (!verifyHyoMailSignature(raw, header, process.env.HYO_MAIL_WEBHOOK_SECRET!)) {
      res.writeHead(400).end();
      return;
    }
    const event = JSON.parse(raw); // { id, event, occurredAt, data }
    // Ignore event.id if you have already handled it, then queue the work.
    res.writeHead(200).end();
  });
}).listen(3000);

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

  • ردّ بأي حالة 2xx خلال 10 ثوانٍ، وأجّل العمل البطيء إلى ما بعد الرد.
  • لا تُتبع عمليات إعادة التوجيه؛ وجّه Webhook إلى العنوان النهائي.
  • أي رد آخر أو انتهاء مهلة أو خطأ شبكة يُحسب محاولة فاشلة. يجري HyoNova حتى 5 محاولات إجمالاً، وينتظر بينها نحو دقيقة، ثم 5 دقائق، ثم 15 دقيقة، ثم ساعة.
  • بعد المحاولة الخامسة الفاشلة ينتقل التسليم إلى حالة الرسائل الميتة (dead_letter) ولا يُعاد تلقائياً. يحتفظ به HyoNova لإعادة محاولة يدوية، لكن قائمة التسليمات لا تعرض زر إعادة المحاولة بعد. أصلح نقطة النهاية، وستُسلَّم الأحداث الجديدة كالمعتاد.
  • قد تصل التسليمات أكثر من مرة، وليس دائماً بالترتيب. اجعل معالجتك آمنة من التكرار باستخدام id التسليم، واستخدم occurredAt لترتيب الأحداث.
  • لا يسجّل HyoNova إلا رمز HTTP الذي ردّت به نقطة النهاية، ولا يحفظ محتوى الرد أبداً.

الحالة#

الميزةالحالةملاحظات
Webhooks موقّعةمتاحيعمل اليوم لمساحات العمل التي تتضمنه خطتها.استقبل أحداث هيو ميل الموقّعة عن التسليم والتفاعل وجهات الاتصال والمتجر على نقطة نهاية HTTPS، مع إعادة محاولة تلقائية ويدوية.
↑↓ للتنقل · Enter للفتح · Esc للإغلاق