// docs / webhooks
Webhooks
يرسل FixWeb webhooks صادرة موقعة لاكتمال الفحص، والفشل النهائي، والنتائج عالية الخطورة، وتنبيهات المراقبة الحية، والتشغيلات المجدولة. التسليم at-least-once ويعاد لمدة تقارب 24 ساعة.
الإعداد
افتح Account → Webhooks، أنشئ endpoint عبر HTTPS، واحفظ سر whsec_ الذي يظهر مرة واحدة في المستقبل لديك. تتوفر webhooks في الخطط المدفوعة.
- أنشئ endpoint من Account → Webhooks.
- اختر الأحداث التي يجب أن يرسلها FixWeb إلى ذلك endpoint.
- انسخ السر فورًا؛ يظهر مرة واحدة فقط ولا يمكن لاحقًا إلا تدويره.
الأحداث
يغطي سطح أحداث الإطلاق اللحظات التي تربطها الفرق عادةً مع CI أو التنبيهات أو التذاكر:
- scan.completed — يعمل عندما ينتقل الفحص إلى completed. Payload: scan id، الهدف، الوضع، عدادات الخطورة، ورابط التقرير.
- scan.failed — إشعار فشل نهائي. Payload: scan id، المرحلة الفاشلة، الخطأ، ورابط التقرير.
- finding.created — يرسل لكل finding بدرجة critical أو high. الدرجات الأقل تندمج افتراضيًا في scan.completed لتجنب كثرة الأحداث.
- monitor.alert.fired — يعمل في خطة Unlimited عندما تكتشف certificate transparency logs أو DNS records أو threat-intelligence databases تغييرات.
- schedule.run.queued — يعمل عندما يضع scheduler إعادة الفحص في queue. مفيد لتنسيق CI.
شكل payload
كل عملية تسليم تستخدم نفس الغلاف: <code>id</code> و<code>type</code> و<code>created_at</code> و<code>data</code> الخاصة بالحدث.
{
"id": "8f1c4e2a-8c3a-4b6f-9c0d-9b1e8f3c2a4d",
"type": "scan.completed",
"created_at": "2026-05-15T10:20:30.000Z",
"data": {
"scan": {
"id": "8f1c4e2a-8c3a-4b6f-9c0d-9b1e8f3c2a4d",
"target_hostname": "staging.example.com",
"mode": "passive",
"status": "completed",
"findings_count": { "critical": 0, "high": 1, "medium": 2, "low": 3, "info": 4 },
"report_url": "https://fixweb.app/dashboard/scans/8f1c4e2a-..."
}
}
}التوقيع
يوقع FixWeb جسم JSON الخام بالضبط باستخدام HMAC-SHA-256. تحقق من التوقيع قبل parsing أو الوثوق ببيانات الحدث. Headers:
fixweb-signature: t=<timestamp>,v1=<hex hmac>fixweb-event: scan.completedfixweb-delivery: <uuid>(مفتاح idempotency)
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const signed = `${parts.t}.${rawBody}`;
const expected = createHmac("sha256", secret).update(signed).digest("hex");
const received = Buffer.from(parts.v1 ?? "", "hex");
const calculated = Buffer.from(expected, "hex");
return received.length === calculated.length && timingSafeEqual(received, calculated);
}إعادة المحاولة
أي استجابة غير 2xx أو timeout أو فشل DNS أو حظر أمان SSRF يعاد مع exponential backoff لمدة تقارب 24 ساعة. تعرض صفوف التسليم response status ومقتطفًا قصيرًا وعدد المحاولات وحالة dead-letter في Account → Webhooks.
