建立 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 驗證;不要放進瀏覽器程式碼,也不要提交到版本庫。 - 新建 key 時,完整秘密值只會在
api_key欄位回傳一次;之後列表回應只會顯示key_prefix。 - webhook 應該早於帳號授權建立,因為授權進度與入站訊息都會以 webhook 事件送達。
- 設定
signing_secret,並用原始 request body 驗證X-Device-Signature後,再信任 payload。 - 把
message.received當作第一個正式資料契約,而不是臨時 demo 事件。
如果你已有線上 key,現在要更換,請先看 API key 零停機輪換 runbook。若你正在從零規劃入站架構,建議搭配 webhook-first 入站整合清單 一起使用。
1. 先確認 key 對應的 workspace
UnifyPort 目前提供給特定客戶使用;公開文件說明需要聯絡團隊取得 workspace 權限與第一個 API key。拿到 key 後,第一個請求應該是只讀 workspace 檢查,而不是立即發訊息。
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 允許使用精確的公開標準事件名稱,也允許以 ["*"] 接收所有公開標準事件。若你要建立完整帳號狀態機,用 ["*"];若第一個里程碑只是接收客戶入站訊息,用 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。如果框架先解析 JSON 再重新序列化,位元組可能已經改變,簽章驗證就會失敗。
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 回應都會確認 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"
}
}
}
建議保存頂層事件 id 做冪等,保存 provider 與 account_id 做路由,保存 data.conversation.id 做佇列分組,保存 data.sender.id 做身份關聯,保存 data.message.id 做訊息層級動作。一旦這個 shape 穩定,同一個 receiver 可以先接 WhatsApp,再加入 LINE、Telegram、Zalo、TikTok 或 X。若你想看 AI coding agent 如何協助生成實作,可參考 AI 自動回覆 bot 教學。
第一天常見錯誤
| 錯誤 | 影響 | 較安全做法 |
|---|---|---|
| 先建立帳號、後建立 webhook | 授權事件可能在 receiver 準備好之前抵達 | 先建立 webhook endpoint |
| 關閉簽章 | 知道 URL 的人可能提交相似 JSON | 設定 signing_secret 並驗證 raw-body HMAC |
| 只按 delivery attempt 去重 | retry 可能重送同一事件 | 用 X-Device-Event-Id 或事件 id 做冪等 |
| 在 log 印出 API key | log 會讓秘密值擴散到更多系統 | 使用 secrets manager,並在 log 中遮罩 |
把 message.received 視為 WhatsApp 專用 | 它是跨平台歸一化事件 | 保存 provider 與 account 欄位,不寫死單一平台假設 |
FAQ
之後可以取回完整 API key 嗎?
不可以。建立回應只會在 api_key 回傳一次完整秘密值。列表與詳情回應只會提供 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 跑通傳送,再用標準事件把所有入站訊息接回業務系統。