# Threads Webhook 通知：關鍵字與熱門串文即時推送

Webhook 讓你不用一直輪詢 API：只要設定好規則，Threads 上出現符合條件的串文時，Throk 會主動把串文資料 `POST` 到你指定的網址。常見用途：

- 品牌或產品被提及、而且開始有熱度時，推送到 Slack、LINE 或內部系統
- 監測話題中讚數、回覆數或瀏覽數超過門檻的串文
- 把「正在爆紅」的串文自動匯入你的資料庫或 CRM

:::note[方案需求]
Webhook 需要 **API Standard 以上**的方案，詳見 [API 方案](/api/credits/#api-方案)。
:::

## 運作方式

Webhook 由兩個部分組成：

- **端點（Endpoint）**：接收通知的網址，例如 `https://example.com/throk-webhook`。每個端點有自己的簽章密鑰。
- **規則（Rule）**：決定什麼樣的串文要推送。每條規則掛在一個端點上，一個端點可以有多條規則。

Throk 每 **3 分鐘**檢查一次所有規則。符合條件的串文，會以**一篇串文一則事件**的方式送到端點。同一篇串文對同一條規則只會送出一次。

## 規則類型

### 關鍵字規則

串文內容包含指定關鍵字，**而且**達到你設定的門檻時推送。

- 每條規則一個關鍵字，比對方式與 [關鍵字搜尋](/api/guides/search-rules/) 相同：中文逐字比對、英文以完整單字比對。
- 檢查範圍是**最近 24 小時內發佈**的串文。
- 門檻至少要設定一項，最低值如下：讚數 ≥ 10、回覆數 ≥ 5、瀏覽數 ≥ 20,000。

### 熱門門檻規則

不設關鍵字，只要串文在指定時段內發佈、並達到門檻就推送，適合找出正在爆紅的內容。

- 檢查範圍是**過去 1–72 小時**內發佈的串文（由 `lookbackHours` 設定）。
- 門檻至少要設定一項，最低值如下：讚數 ≥ 500、回覆數 ≥ 100、瀏覽數 ≥ 20,000。

### 兩種規則的共同點

- **同一條規則裡的門檻是「且」**：例如讚數 ≥ 100 **且**回覆數 ≥ 10。
- **不同規則之間互不影響**：一篇串文符合兩條規則，就會送出兩則事件。
- **可以依地區篩選**：`chinese`（所有中文，預設）、`tw`、`hk`、`cn`、`japanese`、`korean`，定義與 [地區與語言](/api/guides/regions/) 相同。
- **包含回覆**：回覆也可能觸發規則，事件中的 `is_reply` 欄位可以區分。
- **瀏覽數門檻會比較晚觸發**：串文的瀏覽數通常要發文後數小時才有資料，設定瀏覽數門檻的規則會比只看讚數、回覆數的規則晚送出。

## 在開發者平台設定

1. 登入 [開發者平台](https://developer.throk.ai/dashboard/webhooks)，進入 **端點與規則**。
2. 按 **新增端點**，輸入你的網址後按 **建立**。
3. 在端點下方按 **+ 新增規則**，選擇 **關鍵字** 或 **熱門門檻**，設定語言與門檻（熱門門檻另外設定「過去幾小時」），按 **新增**。
4. 按端點上的 **測試**，確認你的伺服器可以收到事件。測試事件不扣積分。
5. 展開端點可以看到 **Signing Secret**，用來[驗證簽章](#驗證簽章)。

![開發者平台的 Webhooks 頁面：在端點下新增關鍵字規則，設定語言與讚數、回覆數、瀏覽數門檻](../../../assets/screenshots/api/webhook-rule.jpg)

所有送出的事件、接收端的回應狀態，都可以在 **發送紀錄** 頁面查看；失敗的事件可以重新發送。

## 用 API 設定

也可以用 API 管理端點與規則，請求都需要帶上 API 金鑰。

| 方法與路徑 | 用途 |
| --- | --- |
| `GET /webhook/endpoints` | 列出你的端點、簽章密鑰（`secret`）與規則 |
| `POST /webhook/endpoints` | 建立端點 |
| `DELETE /webhook/endpoints/{endpoint_id}` | 刪除端點（連同它的所有規則） |
| `POST /webhook/endpoints/{endpoint_id}/rules` | 在端點下建立規則 |
| `DELETE /webhook/rules/{rule_id}` | 刪除規則 |
| `POST /webhook/endpoints/{endpoint_id}/test` | 送出一則測試事件（免費） |

建立端點：

```bash
curl -X POST 'https://premium-api.throk.ai/webhook/endpoints' \
  -H 'Authorization: Bearer sk-throk-...' \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://example.com/throk-webhook"}'
```

建立關鍵字規則（讚數 ≥ 100 的台灣串文）：

```bash
curl -X POST 'https://premium-api.throk.ai/webhook/endpoints/{endpoint_id}/rules' \
  -H 'Authorization: Bearer sk-throk-...' \
  -H 'Content-Type: application/json' \
  -d '{"keyword": "珍珠奶茶", "likeCount": 100, "language": "tw"}'
```

建立熱門門檻規則（過去 6 小時內、讚數 ≥ 1,000 的串文）：

```bash
curl -X POST 'https://premium-api.throk.ai/webhook/endpoints/{endpoint_id}/rules' \
  -H 'Authorization: Bearer sk-throk-...' \
  -H 'Content-Type: application/json' \
  -d '{"likeCount": 1000, "lookbackHours": 6}'
```

規則的欄位：

| 欄位 | 說明 |
| --- | --- |
| `keyword` | 關鍵字。不填就是熱門門檻規則 |
| `likeCount`、`replyCount`、`viewCount` | 讚數、回覆數、瀏覽數門檻，至少填一項 |
| `lookbackHours` | 檢查過去幾小時內發佈的串文，1–72。熱門門檻規則必填 |
| `language` | 地區，預設 `chinese` |

規則無法修改，要調整時請刪除後重新建立（開發者平台上可以直接編輯）。

## 推送格式

每則事件以 `POST` 送到你的端點，內容是 JSON：

```json
{
  "post": {
    "url": "https://threads.com/post/DXZoK1VlEvT",
    "code": "DXZoK1VlEvT",
    "caption": "串文內容……",
    "is_reply": false,
    "like_count": 1700,
    "reply_count": 293,
    "repost_count": 40,
    "reshare_count": 180,
    "impression_count": 254300,
    "post_timestamp": 1776760127,
    "media_url": ["https://media01.throk.ai/media/..."]
  },
  "user": {
    "username": "throk.ai",
    "full_name": "Throk｜定義 Threads 數據新標準",
    "profile_picture": "https://media01.throk.ai/profile/77928681697.jpg"
  }
}
```

- 數字是**送出當下**的快照，之後串文繼續成長也不會再送更新。
- `repost_count` 包含轉發與引用；`impression_count` 在還沒有瀏覽數資料時為 `null`。
- 事件內容**不包含規則資訊**。如果需要分辨是哪條規則觸發的，可以為不同規則建立不同的端點，例如在網址加上參數 `https://example.com/throk-webhook?rule=bubble-tea`。

## 驗證簽章

每則事件都附有簽章，讓你確認請求真的來自 Throk、內容沒有被竄改。

- 簽章密鑰就是端點的 **Signing Secret**（開發者平台展開端點即可看到，或在 `GET /webhook/endpoints` 回應的 `secret` 欄位）。
- 簽章放在請求標頭 `X-Convoy-Signature`，格式為 `t=<UNIX 時間戳>,v1=<簽章>`。
- 驗證方式：以 Signing Secret 為金鑰，對 `<時間戳>,<原始請求內容>` 計算 HMAC-SHA256（十六進位），與 `v1` 比對；並檢查時間戳是否在幾分鐘內，避免重放攻擊。

Node.js 範例：

```js
import crypto from 'node:crypto';

// rawBody: 原始請求內容（字串），header: X-Convoy-Signature 的值
function verify(rawBody, header, secret) {
  const fields = header.split(',').map((p) => p.split('='));
  const t = Number(fields.find(([k]) => k === 't')?.[1]);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false; // 只接受 5 分鐘內的請求
  const expected = Buffer.from(
    crypto.createHmac('sha256', secret).update(`${t},${rawBody}`).digest('hex'),
  );
  // 更換密鑰期間可能同時帶有多個 v1，符合任一個即可
  return fields
    .filter(([k]) => k === 'v1')
    .some(([, sig]) => {
      const got = Buffer.from(sig);
      return got.length === expected.length && crypto.timingSafeEqual(got, expected);
    });
}
```

請用**原始的請求內容**（raw body）計算，不要先解析成 JSON 再轉回字串。

## 接收端要注意的事

- 請盡快回應 **HTTP 2xx**；耗時的處理請放到背景執行。
- 回應失敗的事件會自動重試，也可以在開發者平台的 **發送紀錄** 手動重新發送。
- 請以串文的 `code` 做去重複，避免重試時重複處理。

## 計費

- 每送出一則事件扣 **20 積分**，與 API 呼叫共用帳戶積分。同一篇串文對同一條規則只會扣一次。扣點以事件**送出**為準，不論你的伺服器是否回應成功，請確保端點可以正常接收。
- 建立、刪除端點與規則，以及測試事件都**不扣積分**。
- 積分不足時事件會暫停送出；補足積分後，仍在檢查範圍內的串文會在下一輪送出。
- 方案降級到不含 Webhook 的方案後，既有規則會保留，但不會再觸發。
- Webhook 的消耗會出現在 **Credits 消耗紀錄**，API 類型為 `webhook`。

## 停用

Webhook 沒有暫停開關。要停止推送，請刪除規則或端點：刪除端點會一併刪除它的所有規則。