建立 UnifyPort API key 之後:第一個 Webhook 測試清單
收到第一個 UnifyPort API key 後,唔好即刻連接 messaging account。較穩陣嘅次序係:用 GET /v1/workspace 驗證 key,先建立有簽章嘅 webhook endpoint,訂閱 message.received 或 ["*"],把事件存起來,再授權 WhatsApp、Telegram、LINE、TikTok、Zalo 或 X。
重點
- API key 透過
X-Api-Keyheader 驗證;唔好放入瀏覽器程式碼,亦唔好提交到 repo。 - 新建 key 時,完整秘密值只會喺
api_key欄位回傳一次;之後列表回應只會顯示key_prefix。 - webhook 應該早過帳號授權建立,因為授權進度同入站訊息都會以 webhook event 送達。
- 設定
signing_secret,並用原始 request body 驗證X-Device-Signature,先好信任 payload。 - 把
message.received當作第一個正式資料契約,而唔係臨時 demo event。
如果你已有 production key,需要安全更換,先睇 API key 零停機輪換 runbook。如果你由零開始設計入站流程,建議配合 webhook-first 入站整合清單 使用。
1. 先確認 key 對應邊個 workspace
UnifyPort 目前提供予特定客戶使用;公開文件說明需要聯絡團隊取得 workspace access 同第一個 API key。拿到 key 後,第一個 request 應該係只讀 workspace check,而唔係即刻發訊息。
export UNIFYPORT_API_KEY="set-this-in-your-secret-manager"
curl https://api.unifyport.ai/v1/workspace \
-H "X-Api-Key: $UNIFYPORT_API_KEY"
成功回應代表呢個 key 能夠解析到一個 workspace。Introduction 文件 亦說明,所有 /v1 endpoint 都用 X-Api-Key request header 驗證;JSON 成功同錯誤回應會帶頂層 request_id,方便排查同對帳。
2. 建立有名稱嘅 key,並只保存一次完整秘密值
如果 workspace 允許建立額外 key,請用清楚描述用途嘅名稱,例如 production inbound worker。根據 Create API key reference,回應入面 key 係記錄資訊,完整秘密值只會喺 api_key 欄位出現一次。
curl -X POST https://api.unifyport.ai/v1/api-keys \
-H "X-Api-Key: $UNIFYPORT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Production inbound worker",
"prefix": "dk_live"
}'
實務規則:把回傳嘅 api_key 直接寫入 secrets manager,唔好貼去 issue、聊天記錄或前端環境變數。OWASP 官方 Secrets Management Cheat Sheet 亦將 API keys 視為 secrets,並把建立、保存、輪換、撤銷同審計視為同一個生命週期。
3. 連接帳號之前先建立 webhook
呢一步要早過 QR、驗證碼或 session 授權。UnifyPort 不保證完整補送錯過嘅 webhook delivery,所以真正持久嘅入站紀錄應該由你嘅 receiver 同資料庫負責。
export WEBHOOK_SIGNING_SECRET="generate-a-long-random-secret"
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/unifyport/webhook",
"status": "active",
"subscribed_events": ["message.received"],
"signing_secret": "'"$WEBHOOK_SIGNING_SECRET"'"
}'
Create webhook endpoint reference 允許使用精確公開標準 event name,亦可以用 ["*"] 接收全部公開標準 event。如果你要建立完整帳號狀態機,用 ["*"];如果第一個 milestone 只係接入客戶入站訊息,用 message.received 會更易驗證。
4. 用原始 request body 驗證簽章
delivery 文件定義咗幾個重要 header:X-Device-Event-Id、X-Device-Delivery-Id、X-Device-Timestamp 同 X-Device-Signature。簽章係以下內容嘅十六進制 HMAC-SHA256:
<X-Device-Timestamp> + "." + <raw request body>
重點係 raw body。如果 framework 先解析 JSON,再重新序列化,bytes 可能已經改變,簽章驗證就會失敗。
import crypto from 'crypto';
import express from 'express';
const app = express();
const signingSecret = process.env.WEBHOOK_SIGNING_SECRET;
app.post('/unifyport/webhook', express.raw({ type: 'application/json' }), (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 = signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) return res.status(401).end();
const event = JSON.parse(req.body.toString('utf8'));
if (event.type === 'message.received') {
console.log(event.provider, event.data.conversation.id, event.data.message.text);
}
res.status(200).end();
});
更完整說明見 Webhook delivery & signature verification。該頁亦覆蓋 retry、idempotency、過期 timestamp 檢查,以及任何 2xx response 都會確認 delivery 嘅規則。
5. 把 message.received envelope 作為第一個資料契約
一般入站訊息會帶穩定 envelope:id、type、provider、account_id、occurred_at 同 data。standard event payload reference 展示應該圍繞哪些欄位建模:
{
"id": "evt_2f9c1a4b7e",
"type": "message.received",
"provider": "whatsapp",
"account_id": "acc_8c21d0",
"occurred_at": "2026-06-08T12:34:56Z",
"data": {
"conversation": { "id": "8613912345678", "type": "user" },
"sender": { "id": "8613912345678", "type": "user", "name": "Jordan Lee" },
"message": {
"id": "wamid.HBgM",
"text": "Hi - is my order shipped yet?",
"direction": "inbound",
"sent_at": "2026-06-08T12:34:55Z"
}
}
}
建議保存頂層 event id 做 idempotency,保存 provider 同 account_id 做 routing,保存 data.conversation.id 做 queue grouping,保存 data.sender.id 做身份關聯,保存 data.message.id 做訊息級操作。一旦呢個 shape 穩定,同一個 receiver 可以先接 WhatsApp,再加入 LINE、Telegram、Zalo、TikTok 或 X。想睇 AI coding agent 協助產生實作,可以參考 AI auto-reply bot 教學。
第一日常見錯誤
| 錯誤 | 影響 | 較安全做法 |
|---|---|---|
| 先建立帳號,後建立 webhook | 授權事件可能早過 receiver 準備好 | 先建立 webhook endpoint |
| 關閉簽章 | 知道 URL 的人可能提交相似 JSON | 設定 signing_secret 並驗證 raw-body HMAC |
| 只按 delivery attempt 去重 | retry 可能重送同一事件 | 用 X-Device-Event-Id 或 event id 做 idempotency |
| 在 log 印出 API key | log 會令秘密值擴散到更多系統 | 使用 secrets manager,並在 log 中遮罩 |
把 message.received 視為 WhatsApp 專用 | 它是跨平台歸一化 event | 保存 provider 同 account 欄位,不寫死單一平台假設 |
FAQ
之後可否取回完整 API key?
不可以。建立 response 只會在 api_key 回傳一次完整秘密值。列表同詳情 response 只會提供 key_prefix 等安全顯示欄位。
應該訂閱 message.received 定 ["*"]?
首輪只測入站訊息,用 message.received。如果系統要接收授權、runtime、訊息、回執、會話或群組事件,用 ["*"]。
建立帳號前一定要有 webhook endpoint 嗎?
若要可靠完成首次測試,建議要。帳號授權進度同即時入站訊息都會透過 webhook 到達,UnifyPort 不承諾完整補送錯過的 payload。
每個平台都需要官方商業帳號嗎?
不需要。UnifyPort 為 WhatsApp、Telegram、LINE、TikTok、Zalo 同 X 提供非官方接口,並可在合適場景下連接個人或一般 messaging account。
下一步
打開 Quickstart,把 API key 放入 secrets manager,先建立 webhook endpoint,再按 delivery 驗簽文件完成 receiver。
Sources checked on 2026-09-01
令訊息接入變成一條穩定嘅產品管線。
先用統一嘅 API 跑通發送,再用標準事件將所有入站訊息接返去業務系統。