เว็บฮุค

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

ท่ีจัดการเว็บฮุค

เปิดโปรไฟล์ของคุณที่มุมบนขวา จากนั้นเลือก อินทิเกรชัน หน้าออินทิเกรชันของชุมชนปัจจุบันจะแสดงรายการ เว็บฮุคขาเข้า และ เว็บฮุคทิศทางออก โดยแต่ละเว็บฮุคจะสังกัดชุมชนเพียงชุมชนเดียว

โดยค่าเริ่มต้น ผ้ดูลแลระบบชุมชนและผ้ดูลแลระบบสามารถสร้างเว็บฮุคได้ ผ้ดูลแลระบบสามารถให้อำนาจแก่บทบาทอื่่นในการต้งค่าการอนุญาตในคอนโซลระบบ › อินทิเกรชัน › การจัดการอินทิเกรชัน: เปิดใช้งานเว็บฮุคขาเข้า และ เปิิด Outgoing Webhooks เปิดใช้อยู่โดยค่าเริ่มต้น

A channel with messages from a CI bot and from GitHub, shown as cards with fields, pipeline stages and a button
ข้อความจากการเชื่อมต่องแสดงในรูปการ์ด: ฟิลด์, ระยะของ pipeline และปุ่ม action

สร้างเว็บฮุคเข้า

  1. ใน อินทิเกรชัน เลือก เว็บฮุคขาเข้า จากนั้นเลือก เพิ่่มเว็บฮุคเข้า
  2. กรอกชื่่อ และ คำอธิบาย: ข้อมูลน้ีจะแสดงเฉพาะในหน้าออินทิเกรชันเท่านั้้น
  3. เลืก Channel (ช่อง) ท่ีข้อความจะไปโดยค่าเริ่มต้น สำหรับช่องส่วนตัว (private channel), ต้องเป็นสมาชิกของช่องนั้่น
  4. ทำเครื่่องหมายถูกที่ ล็อกไว้กับช่องน้ี หากต้องการให้ผู้ส่งไม่สามารถโพสต์ไปยังช่องอื่่นได้
  5. โดยเป็นตัวเลือก สามารถตั้่งค่า ชื่่อผู้ใช้ และ URL ของ รปูภาพโปรไฟล์ สำหรับข้อความของเว็บฮุคน้ีได้ (ดู ชื่่อและไอคอน)
  6. เลืก Save (บันทึก) คัดลอก URL ท่ีแสดง: https://chat.example.com/hooks/<key>
URL นั้่นเป็นความลับอยู้่ตัวเดียว: ใค้ท่ีมี URL นั้่นสามารถโพสต์ในช่องได้ อย่าเก็บใน repository ท่ีสาธารณะ, และลบเว็บฮุคนั้่นหาก URL รั่วไหล

ด้วย 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_idID ของข้อความแรกในเธรด เพ่ือตอบกลับในเธรดนั้ น
priorityความสำคญั ของข้อความ เชน่ {"priority": "urgent"}
silenttrue ส่งข้อความโดยไม่มี 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).

  1. ใน อินทิเกรชัน เลือก เว็บฮุคทิศทางออก จากนั้นเลือก เพิ่่มเว็บฮุคแบบ Outgoing
  2. กรอกชื่่อ และ คำอธิบาย
  3. เลือกประเภทเนื้่อหา ของคำขอร้อง: application/x-www-form-urlencoded หรือ application/json
  4. เลือกช่อง กรอกคำกระตื้่น (1 คำตอ่ 1 บรรทัด) หรือทำทั้งสองอย่าง หากเลือกช่องแต่ไม่ใส่คำกระตื้่น ข้อความทุกข้อความในช่องนั้่นจะถูกส่ง หากเลือกทั้งสองอย่าง ข้อความต้องตรงกับทั้งสองเงื่อนไข
  5. ภายใต้ กระตุ้้นเมื่้อ ให้เลือก คำแรกตรงกัับคำกระตุ้้นอย่่างแม่่นยำ, คำแรกขึ้้นต้นดว้่ยคำกระตุ้้น หรื้อ จากเมนูข้้อความ เมื่้อเลือก จากเมนูข้้อความ คำกระตุ้้นจะหายไป ช่้อง เป็้นข้้อไม่จำเป็้น (เมื่้อไม่ระบุ การกระทำจะปรากฏในช่้องสาธารณะท้ังหมดของชุมชน) และ ชื่้อ เป็้นข้้อจำเป็้น: คื้อชื่้อของการกระทำในเมนู
  6. กรอกURLs สำหรับ Callback (หนึ่ง URL ต่อหนึ่งบรรทัด) แต่ละ URL จะไดร้บข้อความท่ีตรงกัับเงื่่อนไขทังหมด
  7. สามารถตั้งค่า ชื่่อผ้้ใช้ และ ร่ปภาพโปรไฟล์ ท่ีใช้สำหร้บข้้อความตอบกล้บได้ สำหรับข้้อความท่ีเข้้าจากเมนูข้้อความ ฟิลด์ ไอคอน จะแทนท่ี ร่ปภาพโปรไฟล์: คื้่อ URL ของร่ปภาพ .png หรือ .jpg หรือร่ปภาพท่ีอปั โหลดไว้ในหน้้าจอเดฟอลต์ของ 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 จะไม่รับคำกระตุ้ และต้องมี 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