Webhook
Usher แจ้งเซิร์ฟเวอร์ของคุณได้ทันทีที่มีสิ่งใดเกิดขึ้นในสภาพแวดล้อม: มีคนเข้าร่วม ลงชื่อเข้า เปลี่ยนรายละเอียด หรือออกไป แต่ละเหตุการณ์คือ POST ที่ลงนามแล้วไปยังที่อยู่ที่คุณเลือก และจะส่งซ้ำหากเซิร์ฟเวอร์ของคุณไม่ตอบ
เพิ่มเอนด์พอยต์
ใน Usher Console ให้เปิดสภาพแวดล้อม แล้วไปที่ Webhook → เอนด์พอยต์ใหม่ ระบุที่อยู่ 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 ไลบรารีใดๆ ของข้อกำหนดนี้จึงตรวจสอบลายเซ็นให้คุณได้ ให้ปฏิเสธทุกอย่างที่ตรวจสอบไม่ผ่าน ไลบรารีเหล่านี้ยังปฏิเสธเวลาประทับที่ห่างเกินห้านาที การส่งเก่าจึงนำมาเล่นซ้ำไม่ได้
// 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 นาที 2 ชั่วโมง 5 ชั่วโมง 10 ชั่วโมง และ 10 ชั่วโมง (รวมประมาณหนึ่งวันครึ่ง) แล้วจึงหยุด บันทึกการส่งใน Console แสดงทุกครั้งที่พยายามส่งของแต่ละข้อความ และคำตอบล่าสุดจากเซิร์ฟเวอร์ของคุณ ส่วน ส่งอีกครั้ง จะเริ่มการส่งใหม่ตั้งแต่ต้น
ข้อมูลลับใหม่
ข้อมูลลับใหม่ ใน Console จะสร้างข้อมูลลับอีกชุดและแสดงเพียงครั้งเดียว ในช่วง 24 ชั่วโมงถัดไป การส่งแต่ละครั้งจะมีลายเซ็นสองรายการ หนึ่งรายการต่อหนึ่งข้อมูลลับ คุณจึงนำข้อมูลลับใหม่ไปใช้ได้โดยไม่พลาดสิ่งใด หลังจากนั้นจะมีเพียงข้อมูลลับใหม่ที่ลงนาม
การส่งมาจากที่ใด
Webhook ออกจาก Usher ผ่านพร็อกซีขาออก ซึ่งจะไม่เชื่อมต่อไปยังที่อยู่ส่วนตัวหรือที่อยู่ภายใน เอนด์พอยต์ต้องเป็นที่อยู่ https:// บนชื่อสาธารณะ: ไม่ใช่ที่อยู่ IP ไม่ใช่ชื่อส่วนตัว และไม่ใช่ที่อยู่บนโดเมนของ Usher เอง