// docs / webhooks
Webhooks
يرسل FixVibe webhooks صادرة موقعة لاكتمال الفحص، والفشل النهائي، والنتائج عالية الخطورة، وتنبيهات المراقبة الحية، والتشغيلات المجدولة. التسليم at-least-once ويعاد لمدة تقارب 24 ساعة.
الإعداد
افتح Account → Webhooks، أنشئ endpoint عبر HTTPS، واحفظ سر whsec_ الذي يظهر مرة واحدة في المستقبل لديك. تتوفر webhooks في الخطط المدفوعة.
- أنشئ endpoint من Account → Webhooks.
- اختر الأحداث التي يجب أن يرسلها FixVibe إلى ذلك endpoint.
- انسخ السر فورًا؛ يظهر مرة واحدة فقط ولا يمكن لاحقًا إلا تدويره.
الأحداث
يغطي سطح أحداث الإطلاق اللحظات التي تربطها الفرق عادةً مع CI أو التنبيهات أو التذاكر:
- scan.completed — يعمل عندما ينتقل الفحص إلى completed. Payload: scan id، الهدف، الوضع، عدادات الخطورة، ورابط التقرير.
- scan.failed - إشعار بفشل المحطة الطرفية. الحمولة: معرف المسح وسبب الفشل ورابط التقرير عند توفره.
- 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://fixvibe.app/dashboard/scans/8f1c4e2a-..."
}
}
}التوقيع
يوقع FixVibe جسم JSON الخام بالضبط باستخدام HMAC-SHA-256. تحقق من التوقيع قبل parsing أو الوثوق ببيانات الحدث. Headers:
fixvibe-signature: t=<timestamp>,v1=<hex hmac>fixvibe-event: scan.completedfixvibe-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، أو انتهاء المهلة، أو DNS، أو رفض أمان التسليم مع التراجع الأسي لمدة 24 ساعة تقريبًا. تعرض صفوف التسليم حالة الاستجابة، ومقتطف استجابة قصير، وعدد المحاولات، وحالة الأحرف الميتة في الحساب → Webhooks.
