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

เริ่ม UnifyPort Inbound Integration ด้วย Webhook: Checklist สำหรับทีมเล็ก

ถ้าทีมของคุณต้องรับข้อความจาก LINE หรือ WhatsApp เข้าระบบซัพพอร์ต ขั้นตอนแรกควรเป็น webhook receiver ไม่ใช่การต่อบัญชี production ก่อน UnifyPort ไม่มี REST API แบบทั่วไปสำหรับอ่านประวัติข้อความย้อนหลัง และไม่รับประกันว่า payload ที่พลาดไปจะถูก replay เสมอ ดังนั้น webhook คือชั้นรับข้อมูลถาวรของคุณ: สร้าง POST /v1/webhook-endpoints, เปิด signing_secret, subscribe message.received หรือ [*], เก็บ event แล้วค่อยส่งต่อไปยัง CRM, AI หรือ automation

สรุปสำคัญ

  • สร้าง webhook ก่อนเชื่อมต่อ messaging account จริง
  • ใช้ signing_secret เพื่อให้ delivery มี X-Device-Timestamp และ X-Device-Signature
  • เก็บ standard event envelope ก่อนทำงานช้าที่ปลายทาง เช่น CRM หรือ AI
  • ถ้าเป็น inbox สำหรับ inbound เท่านั้น ให้ subscribe message.received แล้วเช็ก data.message.direction === "inbound"
  • แยก event filter, signature verification, retry handling และ business routing ออกจากกัน

ทำไมต้องเริ่มที่ webhook

ในไทย LINE มักเป็นช่องทางหลักของลูกค้า แต่ข้อความจาก LINE, WhatsApp หรือ Telegram อาจเข้ามาก่อนที่ shared inbox หรือ AI agent จะพร้อม ถ้า receiver ยังไม่ได้ลงทะเบียน อย่าคาดหวังว่าจะดึงข้อความนั้นกลับมาได้จาก history API ภายหลัง UnifyPort Quickstart จึงวางขั้นตอน register webhook ก่อน account authorization

บทความนี้ควรอ่านคู่กับ Webhook HMAC replay protection ซึ่งอธิบาย timestamp, signature และ idempotency และ UnifyPort webhook event filters ซึ่งช่วยเลือก subscribed_events หรือ wildcard บทความนี้รวมทั้งหมดเป็นลำดับสำหรับเริ่มใช้งานจริง

ขั้นตอนที่ 1: สร้าง signed endpoint

API route จริงคือ POST /v1/webhook-endpoints ถ้าคุณทำ inbound inbox ให้เริ่มจาก message.received ถ้า endpoint เป็น event collector สำหรับทุก public standard event จึงใช้ [*]

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

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

ขั้นตอนที่ 2: ตรวจสอบ raw request body

เมื่อเปิด signing แล้ว UnifyPort จะส่ง X-Device-Signature ซึ่งเป็น hex HMAC-SHA256 ของค่านี้:

<X-Device-Timestamp>.<raw request body>

Receiver ต้อง verify raw bytes ก่อน parse JSON หรือ serialize ใหม่ Node.js มี crypto.createHmac() และ crypto.timingSafeEqual() สำหรับงานนี้ โดยเอกสาร official ระบุว่า buffer ที่ใช้กับ timingSafeEqual() ต้องมีความยาวเท่ากัน

import crypto from 'node:crypto';
import express from 'express';

const app = express();
const signingSecret = process.env.WEBHOOK_SIGNING_SECRET;

app.post('/webhooks/unifyport', express.raw({ type: 'application/json' }), async (req, res) => {
  const timestamp = req.get('X-Device-Timestamp') ?? '';
  const signature = req.get('X-Device-Signature') ?? '';

  const expected = crypto.createHmac('sha256', signingSecret)
    .update(timestamp + '.')
    .update(req.body)
    .digest('hex');

  const valid = /^[0-9a-f]{64}$/i.test(signature) &&
    signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));

  if (!valid) return res.sendStatus(401);
  const event = JSON.parse(req.body.toString('utf8'));
  await inbox.insertIfAbsent(event.id, event);
  return res.sendStatus(202);
});

Production receiver ควรเพิ่ม timestamp freshness, durable deduplication และ acknowledgement ที่รองรับ retry ดูรายละเอียดใน Webhook delivery and signature verification

ขั้นตอนที่ 3: เก็บ standard event envelope

message.received มี top-level shape เดียวกันข้าม provider ดังนั้น LINE และ WhatsApp สามารถเข้ามาที่ receiver เดียวกันได้

{
  "id": "evt_2f9c1a4b7e",
  "type": "message.received",
  "provider": "line",
  "account_id": "acc_8c21d0",
  "occurred_at": "2026-06-08T12:34:56Z",
  "data": {
    "conversation": { "id": "U4af4980629", "type": "user", "title": "Jordan Lee" },
    "sender": { "id": "U4af4980629", "name": "Jordan Lee", "type": "user" },
    "message": {
      "id": "msg_10472",
      "text": "สินค้าจัดส่งหรือยังครับ",
      "direction": "inbound",
      "sent_at": "2026-06-08T12:34:55Z"
    }
  }
}

ควรเก็บอย่างน้อย id, type, provider, account_id, occurred_at, data.conversation.id, data.sender.id และ data.message.id ถ้าจะต่อ n8n ภายหลัง ให้ดู n8n WhatsApp AI agent tutorial เป็นตัวอย่างว่า workflow ควรรับ event ที่ verify แล้ว ไม่ใช่เป็น security boundary แรก

ข้อจำกัดและ trade-off

Unofficial interface เหมาะกับทีมที่ต้องรับ inbound messages จากบัญชีทั่วไปหรือบัญชีเดิม แต่ถ้าคุณต้องใช้ certification, official business features หรือ policy guarantee ของ platform โดยตรง ควรเลือก official API ของ provider นั้น นอกจากนี้ message.received ไม่ได้แปลว่า inbound เสมอ ต้องตรวจ data.message.direction ใน inbox pipeline

FAQ

ควร subscribe event ไหนก่อน?

สำหรับ inbound inbox ให้เริ่มที่ message.received ใช้ [*] เฉพาะเมื่อ endpoint เป็น full event collector

HMAC พอสำหรับป้องกัน duplicate processing ไหม?

ไม่พอ HMAC ตรวจ integrity และ shared secret ต้องเพิ่ม timestamp freshness และ deduplication ด้วย event ID

ตอบ 2xx ก่อน CRM ทำงานเสร็จได้ไหม?

ได้ ถ้า event ถูกเก็บลง durable inbox หรือ queue แล้ว งาน CRM, AI และ notification ควรไปทำแบบ asynchronous

Next step

เปิด Create webhook endpoint เพื่อ register receiver แล้วอ่าน webhook delivery guide ก่อนเชื่อมต่อ messaging account จริง

Sources

Official sources checked on 2026-08-26:

UnifyPort API

เปลี่ยนการเชื่อมต่อข้อความให้เป็น pipeline ผลิตภัณฑ์ที่เสถียร

เริ่มจากการส่งผ่าน API เดียว แล้วส่งข้อความขาเข้าทั้งหมดกลับสู่ระบบธุรกิจของคุณด้วย event มาตรฐาน