الانتقال إلى المحتوى
الوثائق · خطافات الويب

خطافات الويب

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

أضف نقطة نهاية

في Usher Console، افتح البيئة، ثم خطافات الويب ← نقطة نهاية جديدة. أدخل عنوانًا لديك يبدأ بـ https://، واختر الأحداث التي يجب أن تصله. يعرض Console سر التوقيع لنقطة النهاية (whsec_…) مرة واحدة: احفظه مع أسرار خادمك الأخرى.

الحدثمتى
user.createdأنشأ شخص حسابًا
user.updatedتغيّر حساب: البريد الإلكتروني، أو الاسم، أو التحقق، أو الحظر (بما في ذلك حظر يفرضه دليل مؤسستك عبر SCIM)
user.deletedحُذف حساب
session.createdسجّل شخص الدخول
session.endedانتهت جلسة: بتسجيل الخروج، أو الإبطال، أو انتهاء صلاحيتها مبكرًا

يرسل إرسال اختبار حدث webhook.test إلى نقطة النهاية تلك وحدها، أيًّا كانت الأحداث المشتركة فيها.

ما الذي يصل

الطلب
POST /usher/webhooks HTTP/1.1
content-type: application/json
user-agent: Usher-Webhooks/1
webhook-id: msg_2fk7x…
webhook-timestamp: 1793643116
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=
المحتوى
{
  "type": "user.created",
  "timestamp": "2026-11-02T18:11:56.412Z",
  "data": {
    "user": {
      "id": "Qz3m…",
      "email": "lena@acme.com",
      "emailVerified": false,
      "name": "Lena Live",
      "image": null,
      "banned": false,
      "createdAt": "2026-11-02T18:11:56.380Z",
      "updatedAt": "2026-11-02T18:11:56.380Z"
    }
  }
}

تصف الأحداث الأشخاص والجلسات، ولا تتضمن أسرارًا أبدًا: لا رموز مميزة، ولا تجزئات لكلمات السر، ولا أدوار، ولا سبب حظر أي شخص.

تحقق من كل عملية تسليم

يوقّع Usher وفق مواصفات Standard Webhooks، لذا تتحقق أي مكتبة من مكتباتها من التوقيع نيابةً عنك. ارفض أي شيء لا يجتاز التحقق. وترفض المكتبات أيضًا أي طابع زمني يبتعد أكثر من خمس دقائق، فلا يمكن إعادة إرسال عملية تسليم قديمة.

app/usher/webhooks/route.ts
// a route that receives Usher's webhooks (Node, the standardwebhooks package)
import { Webhook } from 'standardwebhooks'

const wh = new Webhook(process.env.USHER_WEBHOOK_SECRET!) // whsec_…, from Usher Console

export async function POST(request: Request) {
  const body = await request.text() // the raw body: the signature covers it byte for byte
  let event: { type: string; timestamp: string; data: Record<string, unknown> }
  try {
    event = wh.verify(body, Object.fromEntries(request.headers)) as typeof event
  } catch {
    return new Response('bad signature', { status: 400 })
  }
  // webhook-id is the same on every attempt: skip one you have handled already
  if (await alreadyHandled(request.headers.get('webhook-id')!)) return new Response(null, { status: 204 })
  await queue(event) // answer quickly; do the work afterwards
  return new Response(null, { status: 204 })
}
  • أجب خلال 15 ثانية بأي رمز 2xx. وأي شيء آخر، بما في ذلك إعادة التوجيه، يُحتسب إخفاقًا.
  • توقّع التكرار. تحتفظ الرسالة بقيمة webhook-id نفسها في كل محاولة، فتجاهل أي رسالة سبق أن عالجتها.
  • لا تعتمد على الترتيب. قد تصل المحاولات المعادة بعد أحداث أحدث منها.

حين لا يُجيب خادمك

يحاول Usher مجددًا بعد 5 ثوانٍ، ثم 5 دقائق، ثم 30 دقيقة، ثم ساعتين، ثم 5 ساعات، ثم 10 ساعات، ثم 10 ساعات أخرى (نحو يوم ونصف في المجمل)، ثم يتوقف. يعرض سجل التسليم في Console محاولات كل رسالة وآخر رد من خادمك، ويبدأ إعادة الإرسال عملية التسليم من جديد.

سر جديد

ينشئ سر جديد في Console سرًا آخر ويعرضه مرة واحدة. وطوال الساعات الـ 24 التالية تحمل كل عملية تسليم توقيعين، واحدًا لكل سر، لتتمكن من نشر السر الجديد دون أن يفوتك شيء. بعد ذلك لا يوقّع إلا السر الجديد.

من أين تأتي عمليات التسليم

تغادر خطافات الويب Usher عبر وكيل الاتصالات الصادرة، الذي لا يتصل بالعناوين الخاصة أو الداخلية. ويجب أن تكون نقطة النهاية عنوانًا يبدأ بـ https:// على اسم عام: لا عنوان IP، ولا اسمًا خاصًا، ولا عنوانًا على نطاقات Usher نفسه.