إشارات موثوقة للعمل الذي يستغرق وقتًا
طلبات HTTPS موقعة عند تغير المهام أو النطاقات أو النشر أو الموافقات، تُسلّم مرة واحدة على الأقل.
سجّل نقطة نهاية
أضف نقطة نهاية في صفحة المطورون، أو باستخدام نطاق الأذونات webhooks:write:
curl -s -X POST "$BASE/workspaces/$WS/webhooks" \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $(openssl rand -hex 16)" \
-H "Content-Type: application/json" \
-d '{"url":"https://hooks.example.com/mini-casa","events":["job.updated","publication.updated"]}'يحتوي الرد على signing_secret (whsec_...)، ويظهر مرة واحدة. يجب أن يستخدم العنوان HTTPS على المنفذ 443 وألا يُحل إلا إلى عناوين عامة؛ وتُرفض الوجهات الخاصة وعناوين الاسترجاع والوجهات الداخلية، ويُعاد الفحص قبل كل تسليم، ولا تُتبع عمليات إعادة التوجيه أبدًا. يمكن لمساحة العمل امتلاك حتى 10 نقاط نهاية فعالة.
أثبت تحكمك بها
تبدأ نقاط النهاية الجديدة بحالة pending_verification. يرسل زر تحقق (أو POST /webhooks/{id}/verify) حدث webhook.challenge واحدًا موقّعًا. أجب بالرمز 2xx مع {"challenge": "<data.challenge>"} لتصبح نقطة النهاية active.
الأحداث
job.updated: تتغير حالة مهمة أو تشغيل جماعي.job.item.updated: تتغير حالة عنصر واحد في تشغيل جماعي.domain.updated: يتقدم نطاق مخصص في فحوصه.publication.updated: يبدأ بناء أو ينجح أو يفشل أو تحل محله نسخة أحدث.approval.updated: يُبت في موافقة أو تنتهي صلاحيتها أو تُستخدم.billing.entitlement.updated: تتغير الخطة أو حقوق الاستخدام.
تحمل المتون معرفات وحالة فقط، ولا تحمل أبدًا بيانات اعتماد أو محتوى أو بيانات شخصية. اجلب الحالة الحالية باستخدام API.
تحقق من كل طلب
يحمل كل طلب SmallWorld-Webhook-Id وSmallWorld-Webhook-Timestamp (ثواني يونكس) وSmallWorld-Webhook-Signature (v1=<hex>,kid=<key id>). التوقيع هو HMAC-SHA256 للنص <timestamp>.<raw body> باستخدام سرك. استخدم المتن الخام قبل أي تحليل JSON، وقارن في زمن ثابت وارفض الطوابع الزمنية التي تبعد أكثر من خمس دقائق عن ساعتك.
import crypto from "node:crypto";
export function verify(secret, timestamp, rawBody, header) {
const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
const given = /v1=([a-f0-9]+)/.exec(header)?.[1] ?? "";
const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;
return fresh && given.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected));
}ضمانات التسليم
- مرة واحدة على الأقل. يتكرر الطلب حتى تجيب بالرمز
2xx. يبقى معرف الحدث نفسه في كل إعادة محاولة وإعادة تسليم، لذا خزّنه وتجاهل المعرفات التي رأيتها من قبل. - تتباعد المحاولات تدريجيًا من دقيقة إلى يوم، لمدة إجمالية قدرها 72 ساعة. بعد ذلك يصبح التسليم رسالة متعذرة يمكنك إرسالها مجددًا من صفحة المطورين أو باستخدام
redeliver_webhook. - تُوقف نقطة النهاية مؤقتًا عندما يتعذر تسليم 10 أحداث متتالية حتى تستأنفها.
- الترتيب غير مضمون: تعامل مع الحالة كإشارة واقرأ المورد.