Webhook

送入 Webhook 讓其他系統透過向特定 URL 傳送 JSON 來向頻道發布訊息。寄出 Webhook 則相反:它將訊息傳送至您的 URL,這些訊息是以觸發關鍵字開頭,或是使用者在訊息選單中選取的,然後發布您回覆的內容。

管理 Webhook 的位置

開啟右上角的個人頭像,然後選擇整合。目前社群的整合頁面列出送入的 Webhook和寄出的 Webhook。每個 Webhook 都屬於一個社群。

By default, community admins and system admins can create webhooks. A system admin can give the right to other roles in the permission settings of the System Console. A system admin can also turn each kind off in System Console › Integrations › Integration Management: Enable Incoming Webhooks and Enable Outgoing Webhooks are both on by default.

A channel with messages from a CI bot and from GitHub, shown as cards with fields, pipeline stages and a button
以卡片形式呈現的整合訊息:欄位、管線階段與操作按鈕。

建立傳入 Webhook

  1. 在整合中,選擇送入的 Webhook,然後選擇新增送入的 Webhook。
  2. 填寫標題和敘述:這些資訊僅顯示在整合頁面上。
  3. 選擇訊息預設要發送的頻道。如果是私人頻道,您必須是該頻道的成員。
  4. 如果發送者不應能發布到其他位置,請勾選鎖定至此頻道。
  5. 選填其訊息的使用者名稱和大頭貼網址(請參閱名稱與圖示)。
  6. 選擇儲存。複製顯示的 URL:https://chat.example.com/hooks/<key>。
URL 是唯一的機密:任何擁有它的人都可以向該頻道發布訊息。請不要將其放入公開儲存庫,若洩漏請刪除該 Webhook。

使用 API:POST /api/v4/hooks/incoming,搭配 {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"};回應中的 id 即為金鑰。從命令列:amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI"。

向傳入 Webhook 發送訊息

curl -X POST https://chat.example.com/hooks/xgh5ycrx1jf7mbs9w8z4c8e7ho \
  -H 'Content-Type: application/json' \
  -d '{"text": "Deploy of **api 2.4.0** finished :white_check_mark:"}'

伺服器會以 200 回應,內容為 ok。它也接受 application/x-www-form-urlencoded,將 JSON 放在 payload 欄位中,就像 Slack 的 Webhook 一樣,因此為 Slack 打造的工具通常可以不加修改直接使用。

欄位意義
text以 Markdown 格式撰寫的訊息內容。除非包含 attachments,否則此欄位為必填。若文字長度超過伺服器的訊息限制,將被拆分為多則訊息。
channelWebhook 所在社群的另一個頻道,以名稱指定(ops-alerts 或 #ops-alerts),或指定 @username 以從 Webhook 擁有者發送私人訊息。若 Webhook 已鎖定至特定頻道,則會拒絕。舊名稱 town-square 仍可到達社群的預設頻道,該頻道現已更名為 general。
username, icon_url, icon_emoji要顯示的名稱與圖片,前提是伺服器允許覆寫。
attachments訊息附件,將以卡片形式呈現(見下方)。
props儲存在訊息上的額外屬性,供應用程式讀取。
type自訂的貼文類型,例如 custom_poll,供特定應用程式繪製。以 system_ 開頭的類型將被拒絕。
root_id討論串第一則訊息的 ID,用於在該討論串中回覆。
priority訊息優先順序,例如 {"priority": "urgent"}。
silent設定為 true 時,將發送訊息但不觸發推送通知。

Webhook 發布的每一則訊息,其名稱旁都會帶有 機器人 標籤,即使它顯示在建立者名下也是如此,以便使用者能將其與真實人員的訊息區分開來。Webhook 訊息永遠不會觸發寄出 Webhook。

名稱與圖示

Webhook 會以建立者的身分發文,除非伺服器允許覆寫。系統控制台 › 整合 › 整合管理 中有兩項設定可變更此行為,兩者預設皆為關閉:

  • 允許外部整合功能覆寫使用者名稱(ServiceSettings.EnablePostUsernameOverride):將顯示 Webhook 的使用者名稱或請求中的username;若兩者皆無,則名稱顯示為webhook。
  • 允許外部整合功能覆寫大頭貼(ServiceSettings.EnablePostIconOverride):將顯示 Webhook 的大頭貼,或請求中的icon_url或icon_emoji。

請求中的值優先於儲存在 Webhook 上的值。

附件

附件會在文字下方新增結構化內容。其遵循 Slack 的訊息附件格式:

{
  "text": "Build failed on `main`",
  "attachments": [{
    "fallback": "main #1902 failed",
    "color": "#d24b4e",
    "author_name": "GitHub Actions",
    "author_icon": "https://chat.example.com/static/ci.png",
    "title": "main #1902 failed",
    "title_link": "https://ci.example.com/runs/1902",
    "text": "Commit `0f4d8e2` by Jonas Weber",
    "fields": [
      {"title": "Branch", "value": "zephyr-3.7", "short": true},
      {"title": "Duration", "value": "3m 40s", "short": true}
    ],
    "footer": "Lumen CI",
    "ts": 1760000000
  }]
}
欄位意義
fallback純文字,用於無法顯示卡片的環境,例如通知。
color色彩欄:十六進位色彩值,或 good、warning、danger。
pretext卡片上方的文字。
author_name, author_link, author_icon小型標題列。
title, title_link卡片的標題,可選地作為連結。
text卡片的內容,以 Markdown 格式撰寫。
fields{"title", "value", "short"} 的列表;short 欄位會並排顯示。
image_url, thumb_url下方大型圖片,或側邊小型圖片。
footer, footer_icon, ts頁尾列與時間(Unix 秒)。
actions按鈕與選單:請參閱 互動式訊息。

卡片:階段與圖表

Antimatter 為附件新增兩個欄位,並由預設介面繪製:

  • stages:以膠囊樣式顯示管線的步驟,最多 20 個。每個步驟為 {"name", "status"},狀態可為 passed、failed、running、pending、skipped 或 canceled。
  • chart:近期數值的迷你折線圖,{"values": [2 to 200 numbers], "threshold": number, "label": "…"}。閾值以虛線繪製,代表警報的限值。
{
  "attachments": [{
    "color": "danger",
    "title": "main #1902 failed",
    "stages": [
      {"name": "build", "status": "failed"},
      {"name": "unit", "status": "skipped"},
      {"name": "publish", "status": "skipped"}
    ]
  }, {
    "color": "warning",
    "title": "API latency above 400 ms",
    "chart": {"values": [210, 230, 260, 390, 450, 470], "threshold": 400, "label": "p95 latency, ms"}
  }]
}

傳統介面和其他用戶端會忽略這兩個欄位,因此請務必在 text 或 fields 中也包含必要資訊。

建立傳出 Webhook

寄出 Webhook 會監控社群的公開頻道。當訊息的首字與其觸發關鍵字之一相符,或有人在訊息選單中選取它(即訊息操作)時,它會將訊息傳送至您的 URL。

  1. 在整合中,選擇寄出的 Webhook,然後選擇增加寄出的 Webhook。
  2. 填寫標題和敘述。
  3. 選擇請求的內容類型:application/x-www-form-urlencoded 或 application/json。
  4. 選擇一個頻道,輸入觸發關鍵字(每行一個),或兩者皆設。若設定頻道但未設定觸發關鍵字,該頻道的每則訊息都會被送出。若兩者皆設,訊息必須同時符合兩者。
  5. 在觸發於下,選擇首字完全和觸發關鍵字相符、首字以觸發關鍵字開頭,或從訊息選單。若選擇從訊息選單,觸發關鍵字將消失,頻道為選填(若未指定,該操作將提供給社群中的所有公開頻道),且標題為必填:它是該操作在選單中的名稱。
  6. 輸入Callback 網址(每行一個)。每個網址都會收到所有符合條件的訊息。
  7. 選填用於回覆的使用者名稱和大頭貼。對於來自訊息選單的操作,圖示欄位會取代大頭貼:可以是 .png 或 .jpg 圖片的 URL,或在 Antimatter 的預設介面中為已上傳的圖片。選單中會以灰色顯示該圖示;若未提供,該操作將使用中性圖示。
  8. 選擇儲存並複製顯示的令牌。您的服務將使用此令牌來驗證請求是否來自您的伺服器。

透過 API:POST /api/v4/hooks/outgoing,搭配 {"team_id", "channel_id", "trigger_words", "trigger_when", "callback_urls", "content_type", "display_name"}(trigger_when:0 代表完全匹配,1 代表「以...開頭」,2 代表「從訊息選單」)。trigger_when 設為 2 的 Webhook 不需要觸發詞,但需要 display_name。使用 POST /api/v4/hooks/outgoing/{hook_id}/icon 上傳其圖示(multipart,欄位 image:PNG、JPEG 或 GIF,儲存為 128 px 的 PNG);其 icon_url 隨後指向 GET /api/v4/hooks/outgoing/{hook_id}/icon。

如果您的服務位於私人網路中,系統管理員必須在允許不受信任的內部連線連往(ServiceSettings.AllowedUntrustedInternalConnections)中允許其位址。否則,伺服器不會呼叫私人位址。

傳出請求

Antimatter 會傳送包含以下欄位的 POST 請求,根據內容類型以 JSON 或表單編碼格式傳送:

{
  "token": "6kd1ofo5ojr5zgu5ipfipybgnc",
  "team_id": "…",
  "team_domain": "lumen-labs",
  "channel_id": "…",
  "channel_name": "ops-alerts",
  "timestamp": 1760010000000,
  "user_id": "…",
  "user_name": "priya",
  "post_id": "…",
  "text": "deploy api 2.4.0",
  "trigger_word": "deploy",
  "file_ids": ""
}

在執行任何操作之前,請先將 token 與 Webhook 的 token 進行比對。在表單編碼版本中,timestamp 以秒為單位,而非毫秒。伺服器會等待您的回應,時間長度以整合請求超時設定為準(預設為 30 秒,ServiceSettings.OutgoingIntegrationRequestsTimeout)。

回覆傳出 Webhook

若要發布回覆,請以 JSON 格式回應。若要什麼都不發布,請以空內容回應。

{
  "text": "Deploying **api 2.4.0** to staging…",
  "response_type": "comment",
  "username": "deploy-bot",
  "icon_url": "https://chat.example.com/static/deploy.png"
}
  • text 與 attachments:即為回覆內容。若兩者皆無,則不會發布任何內容。
  • response_type:comment 會將回覆發布在觸發訊息的討論串中;否則會發布在頻道中。
  • username、icon_url:當伺服器允許覆寫時會顯示;否則會使用 Webhook 本身的值。
  • props、type、priority:與傳入 Webhook 相同。

回覆會以 Webhook 建立者的身分發布,若存在覆寫名稱,則使用該名稱。若內容長於簡短回應,請立即回應,並稍後透過傳入 Webhook 或 API 發布。

訊息動作

訊息動作是一種 觸發於 設為 從訊息選單 的傳出 Webhook。它不會因已發佈的訊息而觸發。相反地,使用者會在訊息的選單中看到它:訊息動作(⋯)› 更多動作,位於 整合 標題下,並顯示其圖示。經典介面不會顯示訊息動作。選擇它會將該單則訊息傳送至回呼 URL,並顯示一條簡短通知,內容為已 傳送至 該動作的名稱,或顯示您的 ephemeral_text。

  • 顯示位置:在該 Webhook 的頻道中;若未指定頻道,則在其社群的所有公開頻道中。只有公開頻道才有訊息動作。
  • 訪客 只能看到與其所在頻道綁定的動作,無法看到社群範圍的動作。
  • 已封存與唯讀頻道:訊息仍可傳送。封存頻道會刪除與其綁定的 Webhook,因此已封存的頻道只保留社群範圍的動作。若使用者無法在該頻道發佈回覆,該回覆將僅對該使用者顯示。
  • 速率限制:每位使用者每分鐘可執行 10 次訊息動作,初始爆發上限為 5 次。超過此限制時,伺服器將回應 429。
  • 私人網路:與其他傳出 Webhook 相同,內部地址必須在 允許不受信任的內部連線連往 中獲准。

請求

負載(payload)會根據 Webhook 的內容類型,以 JSON 或表單編碼方式傳送:

{
  "token": "6kd1ofo5ojr5zgu5ipfipybgnc",
  "trigger": "message_action",
  "team_id": "…",
  "team_domain": "lumen-labs",
  "channel_id": "…",
  "channel_name": "ops-alerts",
  "timestamp": 1760010000000,
  "user_id": "…",
  "user_name": "priya",
  "post_id": "…",
  "post_root_id": "",
  "post_create_at": 1760009000000,
  "post_user_id": "…",
  "post_user_name": "jonas",
  "permalink": "https://chat.example.com/lumen-labs/pl/…",
  "text": "The staging database is full again",
  "files": [{"id": "…", "name": "df.txt", "link": "https://chat.example.com/api/v4/files/…"}],
  "priority": "",
  "requested_ack": false,
  "burn_on_read": false
}
  • user_id 和 user_name 是選擇該動作的使用者;post_user_id 和 post_user_name 是該訊息的作者。
  • 只傳送該則訊息,絕不傳送其討論串的其餘部分。
  • files 僅在選擇該動作的使用者有權下載該訊息的檔案時,才會列出這些檔案。下載 link 需要會話或令牌,與 API 中的任何檔案相同。
  • 已讀即焚訊息不會包含文字與檔案,且 burn_on_read 設為 true。
  • 若使用表單編碼,檔案會以重複的 file_id、file_name 和 file_link 欄位呈現,順序相同。

回應

回應方式與任何傳出 Webhook 相同(請參閱 回應傳出 Webhook):text 或 attachments 會在頻道中發佈回覆,而 "response_type": "comment" 則會在該訊息的討論串中發佈。您也可以使用 ephemeral_text(截斷為 300 個字元)回應:這會單獨顯示給選擇該操作的人,並出現在通知中。空白的回應體不會發佈任何內容。

{"ephemeral_text": "Ticket OPS-412 created"}

透過 API

  • GET /api/v4/channels/{channel_id}/message_actions:列出您在頻道中可選擇的操作,包含 id、display_name、description 和 icon_url。不會回傳令牌或回呼 URL。
  • POST /api/v4/posts/{post_id}/message_actions/{hook_id}:對您有權讀取的訊息執行操作。回應 {"ephemeral_text"}。

當 Webhook 無法運作時

  • Hook URL 回傳 501:伺服器上的傳入 Webhook 已停用。
  • 400 "Failed to decode the payload…":JSON 無效,或表單欄位未命名為 payload。"No text specified." 表示請求中既沒有 text 也沒有 attachments。
  • 403:Webhook 被鎖定在其他頻道,或其擁有者已無法讀取該頻道。
  • 傳出 Webhook 從未觸發:頻道為私人頻道、觸發詞不是第一個字、訊息來自 Webhook,或 Webhook 設為從訊息選單觸發。
  • 訊息操作未出現在選單中:頻道為私人頻道、操作綁定至其他頻道、該使用者為訪客且操作未指定頻道,或傳出 Webhook 已停用。
  • 執行訊息操作時出現 404:操作不存在,或該操作未涵蓋該使用者對該訊息所在頻道的存取權限。429:該使用者在一分鐘內執行了超過 10 次操作。502:無法連接到任何回呼 URL(日誌中會記錄原因)。
  • 日誌:開啟 啟用 Webhook 除錯(LogSettings.EnableWebhookDebugging),並將日誌層級設為 DEBUG,伺服器會記錄失敗的傳入請求內容。失敗的傳出呼叫會記錄為 Outgoing Webhook POST failed。