← บทความทั้งหมด
บทช่วยสอน

ตัวกรองเหตุการณ์ UnifyPort Webhook: เลือก subscribed_events หรือ Wildcard?

สำหรับ handler บน production ที่มีหน้าที่ชัดเจน ให้ระบุเหตุการณ์ใน subscribed_events โดยตรง ส่วน ["*"] เหมาะกับ endpoint ที่รวบรวมเหตุการณ์ทั้งหมด หรือช่วงที่ทีมยังสำรวจว่า workflow ต้องใช้อะไรบ้าง Wildcard ครอบคลุมเหตุการณ์มาตรฐานสาธารณะทั้งหมด แต่ไม่รวม raw event ภายใน หากกำลังทำกล่องข้อความสำหรับ LINE หรือช่องทางอื่น ให้เริ่มด้วย message.received แล้วค่อยเพิ่มเหตุการณ์วงจรชีวิตบัญชีเมื่อ service เดียวกันต้องดูแลสถานะการเชื่อมต่อด้วย

ประเด็นสำคัญ

  • subscribed_events รับชื่อเหตุการณ์สาธารณะที่ตรงตามเอกสาร หรือใช้ ["*"] เพียงค่าเดียวสำหรับรายการสาธารณะทั้งหมด
  • ระบบจะปฏิเสธชื่อเหตุการณ์ที่ไม่รู้จักตอนสร้างหรืออัปเดต endpoint
  • การ subscribe ไม่ได้แปลว่า provider ทุกตัวจะส่งเหตุการณ์นั้น ต้องตรวจสอบ matrix ของแต่ละ provider
  • message.received อาจเป็นข้อความขาเข้าหรือขาออก จึงต้องตรวจ data.message.direction
  • การกรองเหตุการณ์ การลงลายเซ็น HMAC การตอบรับ และการ retry เป็นการควบคุมคนละส่วน

subscribed_events ควบคุมอะไร

UnifyPort ส่งเหตุการณ์ที่เลือกไว้ใน subscribed_events ไปยัง Webhook endpoint ผ่าน HTTP POST envelope มาตรฐานมี id, type, provider, account_id, occurred_at และ data ที่ต่างกันตามประเภทเหตุการณ์ ดูชื่อและรูปแบบ payload ที่รองรับได้ในรายการเหตุการณ์มาตรฐาน

ชุดขั้นต่ำสำหรับรับข้อความคือ:

{
  "subscribed_events": ["message.received"]
}

แต่ handler ยังต้องตรวจทิศทาง:

if (
  event.type === 'message.received' &&
  event.data?.message?.direction === 'inbound'
) {
  await storeInboundMessage(event);
}

เหตุการณ์นี้หมายถึงพบข้อความบน messaging account ที่เชื่อมต่ออยู่ ไม่ได้หมายถึงข้อความขาเข้าเท่านั้น

รูปแบบ Wildcard คือ:

{
  "subscribed_events": ["*"]
}

ใช้เป็นตัวเลือกทั้งหมดโดยไม่ผสม "*" กับชื่อเหตุการณ์อื่นใน array เดียวกัน ระบบจะเลือกเหตุการณ์มาตรฐานสาธารณะทั้งหมด แต่ไม่เปิดเผย raw event ภายใน

รูปแบบตัวกรองที่ใช้ได้จริง 3 แบบ

1. กล่องข้อความขาเข้าอย่างเดียว

เหมาะกับ service ที่เก็บและส่งต่อข้อความจากลูกค้าเท่านั้น:

{
  "subscribed_events": ["message.received"]
}

ประมวลผลเฉพาะรายการที่ data.message.direction เป็น inbound หากภายหลังต้องรองรับการแก้ไข การลบ reaction หรือ receipt ให้เพิ่มชื่อเหตุการณ์ที่ถูกต้องหลังจากกำหนดแล้วว่าแต่ละชนิดจะอัปเดตข้อมูลที่เก็บไว้อย่างไร

2. กล่องข้อความพร้อมสถานะบัญชี

ใช้เมื่อ service เดียวกันต้องแจ้งเตือนการยืนยันตัวตนหมดอายุหรือ runtime หลุดด้วย:

{
  "subscribed_events": [
    "message.received",
    "account.status.updated",
    "account.started",
    "account.auth.required",
    "account.auth.succeeded",
    "account.auth.failed"
  ]
}

อย่าตีความทุก status event ว่าเป็นคำสั่ง restart ให้บันทึก auth_status และ runtime_status แล้วตรวจสถานะบัญชีอีกครั้งก่อนสั่งงาน คู่มือกู้คืน runtime ของ messaging accountอธิบายว่าเมื่อใดควร refresh, reconnect, start หรือยืนยันตัวตนใหม่

3. ตัวรวบรวมเหตุการณ์ทั้งหมด

เลือก ["*"] เมื่อ endpoint เป็นจุดรับข้อมูลกลางและค่อยกระจายงานในระบบด้านหลัง แนวทางนี้ทำให้ LINE, WhatsApp, Telegram, TikTok, Zalo และ X ใช้ queue ที่ลงลายเซ็นร่วมกัน แล้วแยก consumer สำหรับข้อความ receipt กลุ่ม และสถานะบัญชี

แม้ใช้ Wildcard ก็ต้องมี default branch สำหรับเหตุการณ์สาธารณะที่อาจเพิ่มในอนาคต เก็บ envelope อย่างปลอดภัย ตอบรับการส่ง และส่ง type ที่ยังไม่รองรับไปยังคิวแยกที่ตรวจสอบได้ อย่าตั้งสมมติฐานว่าทุก event คือข้อความ

สร้าง endpoint ด้วยตัวกรองแบบระบุชื่อ

เส้นทาง API จริงคือ POST /v1/webhook-endpoints คำขอต่อไปนี้สร้าง endpoint ที่ active และเปิดใช้ลายเซ็น สำหรับข้อความกับสถานะบัญชี:

curl -X POST https://api.unifyport.ai/v1/webhook-endpoints \
  -H "X-Api-Key: $UNIFYPORT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"url\": \"https://inbox.example.com/webhooks/unifyport\",
    \"status\": \"active\",
    \"subscribed_events\": [
      \"message.received\",
      \"account.status.updated\",
      \"account.auth.required\"
    ],
    \"signing_secret\": \"$WEBHOOK_SIGNING_SECRET\",
    \"retry_policy\": { \"max_attempts\": 3 }
  }"

ดูสัญญาคำขอได้จากเอกสาร Create webhook endpoint ค่า retry_policy.max_attempts นับจำนวน retry หลังการส่งครั้งแรก ค่าเริ่มต้นตามเอกสารคือ 3 จึงหมายถึงคำขอแรกและ retry ได้อีกสูงสุดสามครั้ง ช่วงที่กำหนดได้คือ 0 ถึง 5

เมื่อต้องเปลี่ยนตัวกรอง ให้ใช้ PATCH /v1/webhook-endpoints/{endpoint_id} ตามเอกสาร แล้วส่ง subscribed_events ชุดใหม่ กฎตรวจสอบชื่อเดียวกับตอนสร้าง endpoint

แยกการกรองออกจากความปลอดภัยของการส่ง

ตัวกรองกำหนดว่า UnifyPort จะส่งอะไร ส่วน signing_secret กำหนดว่าการส่งจะมี X-Device-Timestamp และ X-Device-Signature หรือไม่ เมื่อเปิดลายเซ็น ให้ตรวจ HMAC-SHA256 แบบเลขฐานสิบหกจาก timestamp ตามด้วยจุดและ raw request body ก่อน parse JSON

สถานะ 2xx ใด ๆ คือการตอบรับสำเร็จ ข้อผิดพลาดการเชื่อมต่อและ HTTP 408, 429, 5xx retry ได้ตามการตั้งค่า ส่วน 4xx อื่นจะไม่ retry การส่งเป็นแบบ at-least-once จึงต้องจัดการ retry ของเหตุการณ์ทั่วไปแบบ idempotent

ดู receiver ฉบับเต็มในคู่มือการส่ง Webhook และตรวจลายเซ็น และบทเรียน HMAC replay protection กับ idempotency

ตรวจสอบ provider ก่อนเพิ่มชื่อเหตุการณ์

รายการสาธารณะบอกชื่อที่ถูกต้อง แต่ parser ของแต่ละ provider ไม่ได้ map ทุก event เหมือนกัน message.received และเหตุการณ์บัญชีหลักมีการรองรับกว้าง ขณะที่ receipt การแก้ไขข้อความ การเปลี่ยน conversation และการอัปเดตกลุ่มแตกต่างกัน

ก่อนให้ consumer พึ่งพาเหตุการณ์หนึ่ง ให้ดูความแตกต่างของ Webhook event ตาม provider subscription ที่ถูกต้องเป็นเพียงตัวกรอง ไม่ได้รับประกันว่าบัญชีต้นทางจะสร้าง event นั้น

หากกำลังทำ automation แทนตัวรวบรวมทั่วไป บทเรียน n8n WhatsApp signed webhook แสดงเหตุผลที่ควรวางการตรวจลายเซ็นและการรับข้อมูลแบบทนทานไว้ก่อน AI workflow

ข้อจำกัดและสิ่งที่ต้องแลก

รายการแบบระบุชื่อช่วยลดข้อมูลรบกวนและทำให้ความรับผิดชอบชัด แต่ต้องแก้ configuration เมื่อมีความต้องการใหม่ Wildcard ลดโอกาสพลาด event สาธารณะชนิดใหม่ แต่ consumer ต้องรองรับ type มากขึ้นและพร้อมต่อการเปลี่ยนแปลงในอนาคต

UnifyPort ไม่มี REST API ทั่วไปสำหรับอ่านข้อความย้อนหลัง และไม่รับประกันการส่ง payload ที่พลาดไปซ้ำทั้งหมด ควรลงทะเบียน receiver ก่อนเชื่อมต่อ messaging account บน production และเก็บ event ที่จำเป็นทันทีเมื่อมาถึง การซิงค์ประวัติ WhatsApp แบบจำกัดช่วยเรื่องความต่อเนื่อง แต่ไม่แทน event store ของคุณ

UnifyPort เป็นอินเทอร์เฟซที่ไม่เป็นทางการ หากงานต้องใช้เส้นทางการรับรองอย่างเป็นทางการ หรือความสามารถเฉพาะ provider ที่อยู่นอก matrix ในเอกสาร ให้เลือก API ทางการของแพลตฟอร์มนั้น

คำถามที่พบบ่อย

ควรใช้ message.received หรือ ["*"]?

ใช้ message.received สำหรับ handler ของกล่องข้อความโดยเฉพาะ และใช้ ["*"] สำหรับตัวรวบรวมที่เก็บและกระจายเหตุการณ์มาตรฐานสาธารณะทั้งหมด

message.received มีเฉพาะข้อความขาเข้าหรือไม่?

ไม่ใช่ หาก workflow รับเฉพาะขาเข้า ให้ตรวจว่า data.message.direction เป็น inbound

Subscribe เหตุการณ์ภายในของ provider ได้หรือไม่?

ไม่ได้ subscribed_events รับเฉพาะชื่อมาตรฐานสาธารณะ และ Wildcard ก็ไม่เปิดเผย raw event ภายใน

ถ้าสะกดชื่อเหตุการณ์ผิดจะเกิดอะไรขึ้น?

คำขอสร้างหรืออัปเดตจะปฏิเสธชื่อที่ไม่รู้จัก แทนที่จะบันทึกตัวกรองที่ไม่มีวันตรงกับ event

["*"] รับประกันทุก event จากทุก provider หรือไม่?

ไม่รับประกัน มันเลือกชนิดสาธารณะทั้งหมด แต่การรองรับจริงและความพร้อมจากต้นทางยังต่างกันตาม provider

ขั้นตอนถัดไป

เปิดเอกสาร Create webhook endpoint เลือกหนึ่งในสามรูปแบบด้านบน และลงทะเบียน receiver ก่อนเชื่อมต่อ messaging account สำหรับ production

แหล่งข้อมูล

ตรวจสอบเมื่อ 19 สิงหาคม 2026: