Webhook

Webhook masuk memungkinkan sistem lain mengirim pesan ke kanal dengan mengirimkan JSON ke URL rahasia. Webhook keluar melakukan kebalikannya: ia mengirim pesan ke URL Anda, yaitu pesan yang diawali dengan kata pemicu atau yang dipilih orang di menu pesan, lalu memposting jawaban Anda.

Lokasi untuk mengelola webhook

Buka avatar Anda di kanan atas, lalu pilih Integrasi. Halaman integrasi komunitas saat ini mencantumkan Webhook Masuk dan Webhook Keluar. Setiap webhook milik satu komunitas.

Secara bawaan, admin komunitas dan admin sistem dapat membuat webhook. Admin sistem dapat memberikan hak ini ke peran lain di pengaturan izin Konsol Sistem. Admin sistem juga dapat menonaktifkan masing-masing jenis di Konsol Sistem › Integrasi › Manajemen Integrasi: Aktifkan Webhook Masuk dan Aktifkan Webhook Keluar keduanya aktif secara bawaan.

A channel with messages from a CI bot and from GitHub, shown as cards with fields, pipeline stages and a button
Pesan integrasi yang digambar sebagai kartu: bidang, tahap pipeline, dan tombol aksi.

Buat webhook masuk

  1. Di Integrasi, pilih Webhook Masuk, lalu Tambah Webhook Masuk.
  2. Isi Judul dan Deskripsi: keduanya hanya tampil di halaman integrasi.
  3. Pilih Kanal tempat pesan akan dikirim secara bawaan. Untuk kanal privat, Anda harus menjadi anggota kanal tersebut.
  4. Centang Kunci ke kanal ini jika pengirim tidak boleh dapat mengirim ke tempat lain.
  5. Secara opsional, atur Nama Pengguna dan URL Gambar Profil untuk pesan webhook-nya (lihat Nama dan ikon).
  6. Pilih Simpan. Salin URL yang ditampilkan: https://chat.example.com/hooks/<key>.
URL adalah satu-satunya rahasia: siapa pun yang memilikinya dapat mengirim pesan di kanal tersebut. Jauhkan dari repositori publik, dan hapus webhook jika bocor.

Melalui API: POST /api/v4/hooks/incoming dengan {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"}; id dari respons adalah kuncinya. Dari baris perintah: amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI".

Kirim pesan ke webhook masuk

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:"}'

Server merespons dengan 200 dan isi ok. Ia juga menerima application/x-www-form-urlencoded dengan JSON di bidang payload, seperti webhook Slack, sehingga alat yang dibuat untuk Slack biasanya berfungsi tanpa perubahan.

BidangArti
textPesan dalam format Markdown. Wajib diisi kecuali ada attachments. Teks yang melebihi batas pesan server akan dipecah menjadi beberapa pesan.
channelKanal lain dari komunitas webhook, berdasarkan nama (ops-alerts atau #ops-alerts), atau @username untuk pesan langsung dari pemilik webhook. Ditolak jika webhook dikunci ke kanalnya. Nama lama town-square masih mengarah ke kanal bawaan komunitas, yang sekarang bernama general.
username, icon_url, icon_emojiNama dan gambar yang akan ditampilkan, jika server mengizinkan penggantian.
attachmentsLampiran pesan, yang ditampilkan sebagai kartu (di bawah).
propsProperti tambahan yang disimpan pada pesan, untuk aplikasi yang membacanya.
typeJenis pesan khusus, seperti custom_poll, untuk aplikasi yang menampilkannya. Jenis yang diawali dengan system_ akan ditolak.
root_idID pesan pertama dari sebuah Utas, untuk membalas di utas tersebut.
priorityPrioritas pesan, misalnya {"priority": "urgent"}.
silenttrue mengirim pesan tanpa notifikasi push.

Setiap pesan yang diposting oleh webhook memiliki tag BOT di samping namanya, bahkan jika ditampilkan di bawah nama pembuatnya, sehingga orang dapat membedakannya dari pesan manusia. Pesan webhook tidak pernah memicu webhook keluar.

Nama dan ikon

Webhook memposting sebagai orang yang membuatnya, kecuali server mengizinkan penggantian. Dua pengaturan di Konsol Sistem › Integrasi › Manajemen Integrasi, keduanya nonaktif secara bawaan, mengubah hal itu:

  • Aktifkan integrasi untuk menimpa nama pengguna (ServiceSettings.EnablePostUsernameOverride): Nama Pengguna dari webhook atau username dari permintaan akan ditampilkan; jika keduanya tidak ada, nama yang ditampilkan adalah webhook.
  • Aktifkan integrasi untuk menimpa ikon foto profil (ServiceSettings.EnablePostIconOverride): Gambar Profil dari webhook, atau icon_url atau icon_emoji dari permintaan, akan ditampilkan.

Nilai dalam permintaan mengungguli nilai yang disimpan pada webhook.

Lampiran

Lampiran menambahkan konten terstruktur di bawah teks. Lampiran mengikuti format lampiran pesan 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
  }]
}
BidangArti
fallbackTeks polos untuk tempat yang tidak dapat menampilkan kartu, seperti notifikasi.
colorBilah warna: warna heksadesimal, atau good, warning, danger.
pretextTeks di atas kartu.
author_name, author_link, author_iconBaris judul kecil.
title, title_linkJudul kartu, opsional berupa tautan.
textIsi kartu, dalam format Markdown.
fieldsDaftar {"title", "value", "short"}; kolom short diletakkan berdampingan.
image_url, thumb_urlGambar besar di bawah, atau gambar kecil di samping.
footer, footer_icon, tsBaris footer dan waktu (detik Unix).
actionsTombol dan menu: lihat Pesan interaktif.

Kartu: tahapan dan grafik

Antimatter menambahkan dua bidang ke lampiran, yang ditampilkan oleh antarmuka bawaan:

  • stages: langkah-langkah pipeline sebagai pil, hingga 20. Masing-masing berisi {"name", "status"}, dengan status passed, failed, running, pending, skipped, atau canceled.
  • chart: grafik garis kecil dari nilai terbaru, {"values": [2 to 200 numbers], "threshold": number, "label": "…"}. Ambang batas digambar sebagai garis putus-putus, untuk batas peringatan.
{
  "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"}
  }]
}

Antarmuka klasik dan klien lain mengabaikan dua bidang ini, jadi sertakan juga hal-hal penting di text atau fields.

Buat webhook keluar

Webhook keluar memantau Publik kanal-kanal komunitas. Ia mengirim pesan ke URL Anda ketika kata pertama pesan cocok dengan salah satu kata pemicunya, atau ketika seseorang memilihnya dari menu pesan (sebuah aksi pesan).

  1. Di Integrasi, pilih Webhook Keluar, lalu Tambahkan Webhook Keluar.
  2. Isi Judul dan Deskripsi.
  3. Pilih Jenis Konten dari permintaan: application/x-www-form-urlencoded atau application/json.
  4. Pilih Kanal, masukkan Kata Pemicu (Satu per Baris), atau keduanya. Dengan kanal dan tanpa kata pemicu, setiap pesan di kanal tersebut akan dikirim. Dengan keduanya, pesan harus cocok dengan keduanya.
  5. Di bawah Pemicu Saat, pilih Kata pertama cocok persis dengan kata pemicu, Kata pertama diawali dengan kata pemicu, atau Dari menu pesan. Dengan Dari menu pesan, kata-kata pemicu akan hilang, Kanal bersifat opsional (jika tidak ada, aksi akan ditawarkan di setiap kanal publik komunitas), dan Judul wajib diisi: ini adalah nama aksi di menu.
  6. Masukkan URL Callback (Satu per Baris). Setiap URL akan menerima semua pesan yang cocok.
  7. Secara opsional, atur Nama Pengguna dan Gambar Profil yang digunakan untuk balasan. Untuk aksi dari menu pesan, kolom Ikon menggantikan Gambar Profil: URL gambar .png atau .jpg atau, di antarmuka bawaan Antimatter, gambar yang diunggah. Menu akan menampilkannya dalam warna abu-abu; jika tidak ada, aksi akan mendapatkan ikon netral.
  8. Pilih Simpan dan salin token yang ditampilkan. Layanan Anda menggunakannya untuk memverifikasi bahwa permintaan berasal dari server Anda.

Dengan API: POST /api/v4/hooks/outgoing dengan {"team_id", "channel_id", "trigger_words", "trigger_when", "callback_urls", "content_type", "display_name"} (trigger_when: 0 untuk kecocokan persis, 1 untuk "diawali dengan", 2 untuk "dari menu pesan"). Webhook dengan trigger_when 2 tidak memerlukan kata pemicu dan membutuhkan display_name. Unggah ikonnya dengan POST /api/v4/hooks/outgoing/{hook_id}/icon (multipart, field image: PNG, JPEG, atau GIF, disimpan sebagai PNG 128 px); icon_url kemudian menunjuk ke GET /api/v4/hooks/outgoing/{hook_id}/icon.

Jika layanan Anda berada di jaringan privat, admin sistem harus mengizinkan alamatnya di Izinkan koneksi internal yang tidak tepercaya ke (ServiceSettings.AllowedUntrustedInternalConnections). Server tidak akan memanggil alamat privat jika tidak.

Permintaan keluar

Antimatter mengirim POST dengan bidang-bidang berikut, sebagai JSON atau form-encoded tergantung pada tipe konten:

{
  "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": ""
}

Bandingkan token dengan token webhook sebelum melakukan apa pun. Dalam versi form-encoded, timestamp dalam detik, bukan milidetik. Server menunggu jawaban Anda selama yang diizinkan oleh Timeout permintaan integrasi (30 detik secara default, ServiceSettings.OutgoingIntegrationRequestsTimeout).

Balas webhook keluar

Untuk memposting balasan, jawab dengan JSON. Untuk tidak memposting apa pun, jawab dengan body kosong.

{
  "text": "Deploying **api 2.4.0** to staging…",
  "response_type": "comment",
  "username": "deploy-bot",
  "icon_url": "https://chat.example.com/static/deploy.png"
}
  • text dan attachments: isi balasan. Tanpa salah satu dari keduanya, tidak ada yang diposting.
  • response_type: comment memposting balasan di utas pesan pemicu; selain itu, balasan masuk ke kanal.
  • username, icon_url: ditampilkan jika server mengizinkan penggantian nilai; jika tidak, nilai milik webhook itu sendiri yang digunakan.
  • props, type, priority: sama seperti pada webhook masuk.

Balasan diposting atas nama pembuat webhook, dengan nama yang diganti jika ada. Untuk konten yang lebih panjang dari sekadar jawaban singkat, jawab segera dan posting kemudian menggunakan webhook masuk atau API.

Aksi pesan

Aksi pesan adalah webhook keluar dengan Pemicu Saat diatur ke Dari menu pesan. Aksi ini tidak pernah dipicu oleh pesan yang diposting. Sebaliknya, orang melihatnya di menu pesan: Aksi pesan (⋯) › Lainnya, di bawah judul Integrasi, dengan ikonnya. Antarmuka klasik tidak menampilkan aksi pesan. Memilihnya mengirim satu pesan tersebut ke URL callback, dan pemberitahuan singkat mengatakan Dikirim ke nama aksi tersebut, atau menampilkan ephemeral_text Anda.

  • Di mana ditampilkan: di kanal webhook, atau, tanpa kanal, di setiap kanal publik komunitasnya. Hanya kanal publik yang memiliki aksi pesan.
  • Tamu hanya mendapatkan aksi yang terikat ke kanal yang mereka masuki, bukan yang berlaku untuk seluruh komunitas.
  • Kanal yang diarsipkan dan hanya-baca: pesan masih dapat dikirim. Mengarsipkan kanal menghapus webhook yang terikat ke kanal tersebut, sehingga kanal yang diarsipkan hanya mempertahankan aksi yang berlaku untuk seluruh komunitas. Jawaban yang tidak dapat diposting oleh orang tersebut hanya ditampilkan untuk mereka sendiri.
  • Batas laju: setiap orang dapat menjalankan 10 aksi pesan per menit, setelah burst 5. Di atas itu, server menjawab 429.
  • Jaringan privat: seperti webhook keluar lainnya, alamat internal harus diizinkan di Izinkan koneksi internal yang tidak tepercaya ke.

Permintaan

Beban (payload) dikirim sebagai JSON atau form-encoded, sesuai dengan tipe konten webhook:

{
  "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 dan user_name adalah orang yang memilih tindakan; post_user_id dan post_user_name adalah penulis pesan.
  • Hanya pesan tersebut yang dikirim, tidak pernah sisanya dari utas.
  • files mencantumkan file pesan hanya jika orang yang memilih tindakan dapat mengunduhnya. Mengunduh link membutuhkan sesi atau token, seperti file API lainnya.
  • Pesan yang dibakar saat dibaca dikirim tanpa teks dan file, dengan burn_on_read diatur ke true.
  • Jika form-encoded, file datang sebagai field file_id, file_name, dan file_link yang diulang, dalam urutan yang sama.

Jawaban

Jawab seperti webhook keluar lainnya (lihat Balas webhook keluar): text atau attachments memposting balasan di kanal, dan "response_type": "comment" mempostingnya di utas pesan. Anda juga dapat menjawab dengan ephemeral_text (dipangkas menjadi 300 karakter): ini hanya ditampilkan kepada orang yang memilih tindakan, di notifikasi. Badan kosong tidak memposting apa pun.

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

Dengan API

  • GET /api/v4/channels/{channel_id}/message_actions: tindakan yang dapat Anda pilih di kanal, dengan id, display_name, description, dan icon_url. Tidak ada token maupun URL callback yang dikembalikan.
  • POST /api/v4/posts/{post_id}/message_actions/{hook_id}: menjalankan tindakan pada pesan yang dapat Anda baca. Menjawab {"ephemeral_text"}.

Ketika webhook tidak berfungsi

  • 501 dari URL hook: webhook masuk dimatikan di server.
  • 400 "Failed to decode the payload…": JSON tidak valid, atau field form tidak bernama payload. "No text specified." berarti permintaan tidak memiliki text maupun attachments.
  • 403: webhook terkunci ke kanal lain, atau pemiliknya tidak lagi dapat membaca kanal tersebut.
  • Webhook keluar tidak pernah dipicu: kanalnya privat, pemicu bukan kata pertama, pesan berasal dari webhook, atau webhook diatur untuk dipicu Dari menu pesan.
  • Tindakan pesan tidak ada di menu: kanalnya privat, tindakan terikat ke kanal lain, orang tersebut adalah tamu dan tindakan tidak memiliki kanal, atau webhook keluar dimatikan.
  • 404 saat menjalankan tindakan pesan: tindakan tidak ada, atau tidak mencakup kanal pesan tersebut untuk orang tersebut. 429: orang tersebut menjalankan lebih dari 10 tindakan dalam satu menit. 502: tidak ada URL callback yang dapat dijangkau (log memiliki alasannya).
  • Log: dengan Aktifkan Debugging Webhook diaktifkan (LogSettings.EnableWebhookDebugging) dan tingkat log pada DEBUG, server mencatat payload dari permintaan masuk yang gagal. Panggilan keluar yang gagal dicatat sebagai Outgoing Webhook POST failed.