เว็บฮุค
เว็บฮุคเข้า (incoming webhook) ช่วยให้ระบบอื่นโพสต์ข้อความลงในช่องได้โดยส่ง JSON ไปยัง URL ที่ลับ ส่วนเว็บฮุคออก (outgoing webhook) ทำหน้าที่ตรงกันข้าม: ส่งข้อความไปยัง URL ของคุณ ซึ่งอาจเป็นข้อความที่ขึ้นต้นด้วยคำกระตุ้่น หรือข้อความที่ผู้ใช้เลือกจากเมนูข้อความ จากนั้นจะโพสต์คำตอบที่คุณส่งกลับ
ท่ีจัดการเว็บฮุค
เปิดโปรไฟล์ของคุณที่มุมบนขวา จากนั้นเลือก อินทิเกรชัน หน้าออินทิเกรชันของชุมชนปัจจุบันจะแสดงรายการ เว็บฮุคขาเข้า และ เว็บฮุคทิศทางออก โดยแต่ละเว็บฮุคจะสังกัดชุมชนเพียงชุมชนเดียว
โดยค่าเริ่มต้น ผ้ดูลแลระบบชุมชนและผ้ดูลแลระบบสามารถสร้างเว็บฮุคได้ ผ้ดูลแลระบบสามารถให้อำนาจแก่บทบาทอื่่นในการต้งค่าการอนุญาตในคอนโซลระบบ › อินทิเกรชัน › การจัดการอินทิเกรชัน: เปิดใช้งานเว็บฮุคขาเข้า และ เปิิด Outgoing Webhooks เปิดใช้อยู่โดยค่าเริ่มต้น

สร้างเว็บฮุคเข้า
- ใน อินทิเกรชัน เลือก เว็บฮุคขาเข้า จากนั้นเลือก เพิ่่มเว็บฮุคเข้า
- กรอกชื่่อ และ คำอธิบาย: ข้อมูลน้ีจะแสดงเฉพาะในหน้าออินทิเกรชันเท่านั้้น
- เลืก Channel (ช่อง) ท่ีข้อความจะไปโดยค่าเริ่มต้น สำหรับช่องส่วนตัว (private channel), ต้องเป็นสมาชิกของช่องนั้่น
- ทำเครื่่องหมายถูกที่ ล็อกไว้กับช่องน้ี หากต้องการให้ผู้ส่งไม่สามารถโพสต์ไปยังช่องอื่่นได้
- โดยเป็นตัวเลือก สามารถตั้่งค่า ชื่่อผู้ใช้ และ URL ของ รปูภาพโปรไฟล์ สำหรับข้อความของเว็บฮุคน้ีได้ (ดู ชื่่อและไอคอน)
- เลืก Save (บันทึก) คัดลอก URL ท่ีแสดง:
https://chat.example.com/hooks/<key>
ด้วย API: POST /api/v4/hooks/incoming พร้อม {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"}; id ใน response คือ key จาก command line: amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI"
ส่งข้อความไปยังเว็บฮุคเข้า
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 พร้อม body ok ยังยอมรับ application/x-www-form-urlencoded ท่ีมี JSON ในฟิลด์ payload เหมืนเว็บฮุคของ Slack, ซึ่่งทำให้อุปกรณ์ท่ีสร้างสำหรับ Slack ใช้อยู้่แล้วโดยไมต่้องเปลี่่ยน
| ฟิลด์ | ความหมาย |
|---|---|
text | ข้อความใน Markdown ต้องมียกเว้นว่ามี attachments ข้อความที่ยาวกว่่าขั้้นพิกัดข้อความของเซิร์ฟเวอร์จะถกแบ่งออกเป็นข้อความหลายข้้อ |
channel | อีกช่องในชุมชนของเว็บฮุค โดยระบุชื่อ (ops-alerts หรือ #ops-alerts) หรือ @username สำหรับข้อความส่วนตัวจากเจ้าของเว็บฮุค ระบบจะปฏิเสธคำขอเมื่อเว็บฮุคถูกล็อกไว้กับช่องเดียว ชื่อเก่า town-square ยังคงส่งไปยังช่องเริ่มต้นของชุมชน ซึ่งปัจจุบันมีชื่อว่า general |
username, icon_url, icon_emoji | ชื่่อและรูปท่ีจะแสดง เม่ือเซิร์ฟเวอร์อนุญาติให้อัปเดต |
attachments | ไฟล์แนบของข้อความ ท่ีถกแสดงในรู่ปของการ์ด (ข้่าล่่าง) |
props | คุณสมบัตติ์เพิ่่มท่ีถกเก็บไว้กบั ข้อความ สำหรบั แอปท่ีอ่านข้้อมูลเหล่าน้ี |
type | ประเภทข้อความพเิ ศษ เชน่ custom_poll สำหรบั แอปท่ีจะแสดงข้้อมูลน้ี ประเภทท่ีตองด้วย system_ จะถกปัดถ่า |
root_id | ID ของข้อความแรกในเธรด เพ่ือตอบกลับในเธรดนั้ น |
priority | ความสำคญั ของข้อความ เชน่ {"priority": "urgent"} |
silent | true ส่งข้อความโดยไม่มี push notifications |
ข้อความทุกข้อความที่เว็บฮุคโพสต์จะมีป้าย BOT อยู่ข้างชื่อ แม้จะแสดงภายใต้ชื่อผู้สร้าง เพื่อให้ผู้ใช้แยกแยะออกจากข้อความของบุคคลจริงได้ ข้อความจากเว็บฮุคจะไม่กระตุ้่นเว็บฮุคออก
ชื่่อและไอคอน
เว็บฮุคจะโพสต์ในนามของผู้ท่ีสร้าง เว้นแต่เซิร์ฟเวอร์จะอนุญาตให้แทนที่ ได้ 2 การตั้่งค่าใน คอนโซลระบบ › อินทิเกรชัน › การจัดการอินทิเกรชัน (ทั้งสองปิดโดยค่าเริ่มต้น) ท่ีสามารถเปลี่่ยนพฤติกรรมน้ีได้:
- เปิดใช้งานการอินทิเกรตเพื่่อแทนท่ีชื่่อผู้ใช้ (
ServiceSettings.EnablePostUsernameOverride): จะแสดง ชื่่อผู้ใช้ ของเว็บฮุค หรือusernameจากคำขอร้องแทน; หากไม่มีทั้งสองอย่าง ชื่่อจะแสดงเป็นwebhook - เปิดใช้งานให้ integrations ทับไอคอนรปูโปรไฟล์ (
ServiceSettings.EnablePostIconOverride): จะแสดง รปูภาพโปรไฟล์ ของเว็บฮุค หรือicon_urlหรือicon_emojiจากคำขอร้อง
ค่าน์ อกจากคำขอร้ องจะชนะค่าท่ีเก็บไว้กบั เว็บฮุค
ไฟล์แนบ
ไฟล์แนบเพิ่ มเนื้ อหาท่ีมีโครงสร้างไว้ข้่าล่่างข้ อความ ท่ีตามรูปแบบ attachment ของข้ อความ 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 | แถบส่ี: ส่ี hex หรือ 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 seconds) |
actions | ป่ มและเมนู: ดู Interactive messages |
การ์ด: ส่ วนประกอบและกราฟ
Antimatter เพิ่มฟิลด์สองอย่างในไฟล์แนบ ซึ่งอินเทอร์เฟซเริ่มต้นจะแสดง:
stages: ขั้นตอนของ pipeline ในรูปแบบ pill สูงสุด 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 ด้วย
สร้างเว็บฮุคขาออก
An outgoing webhook watches the public channels of a community. It sends a message to your URL either when the message's first word matches one of its trigger words, or when someone picks it in the message's menu (a message action).
- ใน อินทิเกรชัน เลือก เว็บฮุคทิศทางออก จากนั้นเลือก เพิ่่มเว็บฮุคแบบ Outgoing
- กรอกชื่่อ และ คำอธิบาย
- เลือกประเภทเนื้่อหา ของคำขอร้อง:
application/x-www-form-urlencodedหรือapplication/json - เลือกช่อง กรอกคำกระตื้่น (1 คำตอ่ 1 บรรทัด) หรือทำทั้งสองอย่าง หากเลือกช่องแต่ไม่ใส่คำกระตื้่น ข้อความทุกข้อความในช่องนั้่นจะถูกส่ง หากเลือกทั้งสองอย่าง ข้อความต้องตรงกับทั้งสองเงื่อนไข
- ภายใต้ กระตุ้้นเมื่้อ ให้เลือก คำแรกตรงกัับคำกระตุ้้นอย่่างแม่่นยำ, คำแรกขึ้้นต้นดว้่ยคำกระตุ้้น หรื้อ จากเมนูข้้อความ เมื่้อเลือก จากเมนูข้้อความ คำกระตุ้้นจะหายไป ช่้อง เป็้นข้้อไม่จำเป็้น (เมื่้อไม่ระบุ การกระทำจะปรากฏในช่้องสาธารณะท้ังหมดของชุมชน) และ ชื่้อ เป็้นข้้อจำเป็้น: คื้อชื่้อของการกระทำในเมนู
- กรอกURLs สำหรับ Callback (หนึ่ง URL ต่อหนึ่งบรรทัด) แต่ละ URL จะไดร้บข้อความท่ีตรงกัับเงื่่อนไขทังหมด
- สามารถตั้งค่า ชื่่อผ้้ใช้ และ ร่ปภาพโปรไฟล์ ท่ีใช้สำหร้บข้้อความตอบกล้บได้ สำหรับข้้อความท่ีเข้้าจากเมนูข้้อความ ฟิลด์ ไอคอน จะแทนท่ี ร่ปภาพโปรไฟล์: คื้่อ URL ของร่ปภาพ .png หรือ .jpg หรือร่ปภาพท่ีอปั โหลดไว้ในหน้้าจอเดฟอลต์ของ Antimatter เมนูจะแสดงไอคอนน้ีเป็นส้ีเทา หากไม่มีไอคอน ข้้อความน้ันจะได้ไอคอนท่ีไม่แสดงสถานะใด ๆ
- เลือก บันทึก แล้วยคัดลอกโทเคนที่แสดงขึ้้นมา เซิรวิสของคุณจะใช้โทเคนน้ีเพื่่อตรวจสอบว่าคำขอร้องมาจำกเซิรเวอร์ของคุณ
ผ่าน 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 จะไม่รับคำกระตุ้ และต้องมี display_name อัปโหลดไอคอนด้วย POST /api/v4/hooks/outgoing/{hook_id}/icon (multipart, ฟิลด์ image: PNG, JPEG หรือ GIF, เก็บเป็น PNG ขนาด 128 px); icon_url ของมันจะชี้ไปที่ GET /api/v4/hooks/outgoing/{hook_id}/icon.
ServiceSettings.AllowedUntrustedInternalConnections) มิฉะนั้น เซิร์ฟเวอร์จะไม่เช่ือมต่อนท่ีอยู่บนเครือข่ายส่วนตัวคำขอขาออก
Antimatter ส่ง POST พร้อมฟิลด์เหล่านี้ เป็น JSON หรือ form-encoded ขึ้นอยู่กับ content type:
{
"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 กับโทเคนของเว็บฮุคก่อนดำเนินการใด ๆ ในรูปแบบ form-encoded ค่า timestamp จะอยู่ในหน่วยวินาทีแทนมิลลิวินาที เซิร์ฟเวอร์จะรอคำตอบของคุณตามระยะเวลาที่ Timeout สำหรับคำขอ Integration อนุญาต (ค่าเริ่มต้นคือ 30 วินาที ServiceSettings.OutgoingIntegrationRequestsTimeout)
ตอบกลับเว็บฮุคขาออก
เพื่อโพสต์คำตอบ ให้ตอบกลับด้วย JSON หากต้องการโพสต์อะไรเลย ให้ตอบกลับด้วย body ที่ว่างเปล่า
{
"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: แสดงเมื่อเซิร์ฟเวอร์อนุญาตให้แทนที่ค่า; ในกรณีอื่นจะใช้ค่าของเว็บฮุคเองprops,type,priority: เหมือนกับเว็บฮุคขาเข้า
คำตอบจะถูกโพสต์ในนามของผู้สร้างเว็บฮุค ภายใต้ชื่อที่แทนที่ (ถ้ามี) สำหรับเนื้อหาที่ยาวกว่าคำตอบสั้นๆ ให้ตอบกลับทันทีและโพสต์ทีหลังด้วยเว็บฮุคขาเข้าหรือ API
คำสั่งข้อความ
การดำเนินการข้้oความคือเว็บฮุคขาออกที่มี กระตุ้เมื่o ตั้งค่าเป็น จากเมนูข้oความ มันจะไม่ถูกกระตุ้จากข้oความท่ีโพสต์แล้ว แต่ผู้ใช้จะเห็นมันในเมนูของข้oความ: การดำเนินการข้้oความ (⋯) › การดำเนินการเพิ่mเติม ใต้หัวข้อ อินทิเกรชัon พร้อมไอคอน อินเทอร์เฟซแบบคลาสสิกจะไม่แสดงการดำเนินการข้้oความ การเลือกมันจะส่งข้oความนั้นไปยัง URL ที่เรียกกลับ และข้อความแจ้งสั้น ๆ จะแสดงว่า ส่งไป ชื่อของการดำเนินการ หรือแสดง ephemeral_text ของคุณ
- ท่ีแสดง: ในช่องของเว็บฮุคนั้น หรือ หากไม่มีช่อง จะแสดงในทุกช่องสาธารณะของชุมชน เฉพาะช่องสาธารณะเท่านั้นท่ีมี การดำเนินการข้oความ
- แขก จะได้รับเฉพาะการดำเนินการท่ีผูกกับช่องท่ีพวกเขาอยู่เท่านั้น ไม่รวมถึงการดำเนินการระดับชุมชน
- ช่องท่ีเก็บถาวรและช่องท่ีอ่านเท่านั้n: ยังสามารถส่งข้oความได้ การเก็บถาวรช่องจะลบเว็บฮุคท่ีผูกกับช่องนั้นออก ดังนั้นช่องท่ีเก็บถาวรจะคงเหลือเฉพาะการดำเนินการระดับชุมชนเท่านั้n คำตอบท่ีผู้ใช้นั้nไม่สามารถโพสต์ในช่องได้ จะแสดงให้เฉพาะผู้นั้nเท่านั้n
- ขีดจำกัดเรท: แต่ละคนสามารถรัน การดำเนินการข้oความ ได้ 10 ครั้งต่อนาที หลังจากการกระตุ้ 5 ครั้งติดต่อกัน หากเกินกว่านั้n เซิร์ฟเวอร์จะตอบกลับด้วย
429 - เครือข่ายส่วnตัว: เช่นเดียวกับเว็บฮุคขาออกประเภทอื่n ท่ีีท่ีอยู่ภายในต้องได้รับอนุญาตใน อนุญาติการเช่ืomต่อnภายในท่ีไม่ไว้วางใจถิง
คำขอ
เพย์โหลดจะถูกส่งเป็น JSON หรือ form-encoded ตาม content type ของเว็บฮุค:
{
"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คือผู้เขียนข้oความ- ส่งเฉพาะข้oความนั้nเท่านั้n ไม่ส่งเธรดท่ีเหลือ
filesจะระบุไฟล์ของข้oความเฉพาะเมื่อผู้ท่ีเลือกการดำเนินการมีสิทธิ์ดาวน์โหลดไฟล์นั้n การดาวน์โหลดlinkต้องใช้เซสชันหรือโทเคน เช่นเดียวกับไฟล์อื่nของ API- ข้่าความท่ีจะเผาหลั่กอ่าน (burn-on-read) จะถูกส่งไปโดยไม่มีเนื้่อความและไฟล์แนบ และตั้่งค่า
burn_on_readเป็นtrue - เมื่่อส่งในรู่ปแบบ form-encoded ไฟล์จะปรากฏเป็นฟิลด์
file_id,file_nameและfile_linkซ้ำก่นในลำดับเดีียวกัน
การตอบกลับ
ตอบกลับเช่่นก่น outgoing webhook (ดู การตอบกลับ outgoing webhook): text หรือ attachments จะโพสต์ข้่าความตอบกลับในช่อง และ "response_type": "comment" จะโพสต์ในเธรดของข้่าความนั้้น คุนยังสามารถตอบกลับด้วย ephemeral_text (ตััดท่ี 300 ตัวอัตต์ร์) ซ่่งจะแสดงให่้เพีียงแต่ผู้ท่ีเลือกการกระท่อนั้้นเห็นในข้่าความแจ้งเตือน การส่ง body ว่างจะไม่โพสต์อะไรเลย
{"ephemeral_text": "Ticket OPS-412 created"}
ผ่่าน API
GET /api/v4/channels/{channel_id}/message_actions: การกระทำท่ีคุนสามารถเลือกได้ในช่อง พร้อมid,display_name,descriptionและicon_urlจะไม่มี token หรือ callback URL ใด ๆ ถููกส่งกลับมาPOST /api/v4/posts/{post_id}/message_actions/{hook_id}: รันการกระทำในข้่าความท่ีคุนสามารถอ่านได้ จะตอบกลับ{"ephemeral_text"}
เมื่อเว็บฮุคไม่ทำงาน
- 501 จาก URL ของเว็บฮุค: เว็บฮุคขาเข้าถูกปิดใช้งานบนเซิร์ฟเวอร์
- 400 "Failed to decode the payload…": JSON ไม่ถูกต้อง หรือฟิลด์ฟอร์มไม่ได้ตั้งชื่อว่า
payload"No text specified." หมายความว่าคำขอไม่มีทั้งtextและattachments - 403: เว็บฮุคถูกล็อกไว้กับช่องอื่น หรือผู้ครอบครองไม่สามารถอ่านช่องนั้นได้อีกต่อไป
- Outgoing webhook ไม่เคยทำงาน: ช่องเป็นช่องส่วนตัว, คำท่ีตั้้งไว้ไม่ใช่คำแรกในข้่าความ, ข้่าความมาจาก webhook, หรือ webhook ถููกตั้้งไว้ให้ทำงาน จากเมนูข้่าความ
- การกระทำในข้่าความไม่ปรากฏในเมนู: ช่องเป็นช่องส่วนตัว, การกระทำนั้้นถููกตั้้งไว้สำหรับช่องอ่่น, ผู้ใช้เป็นแขก (guest) และไม่มีช่องใด ๆ ท่ีตั้้งไว้สำหรับ การกระทำนั้้น, หรือ outgoing webhooks ถููกปิดไว้
- 404 เมื่่อรันการกระทำในข้่าความ: การกระทำนั้้นไม่มีอยู่, หรือไม่ครอบคลุมช่องของข้่าความนั้้นสำหรับผู้ใช้คนนั้้น 429: ผู้ใช้รันการกระทำมากก่ว่า 10 ครั้งใน 1 นาที 502: ไม่สามารถเข้าถึง callback URL ใด ๆ ได้ (เหตุผลอยู่ใน log)
- Logs: เมื่อเปิด เปิิด Webhook Debugging (
LogSettings.EnableWebhookDebugging) และตั้งระดับ log เป็นDEBUGเซิร์ฟเวอร์จะบันทึก payload ของคำขอเข้าท่ีเกิดข้้นความพ่ายพ้ด คำขอออกท่ีพ่ายพ้ดจะถกบันทึกเป็นOutgoing Webhook POST failed