Webhook'ler

Gelen webhook, başka bir sistemin gizli bir URL'ye JSON göndererek bir kanala ileti göndermesine olanak tanır. Giden webhook ise bunun tersini yapar: tetikleyici bir kelimeyle başlayan iletileri veya ileti menüsünde insanlar tarafından seçilen iletileri URL'nize gönderir ve sizin verdiğiniz yanıtı yayınlar.

Webhook'ları nerede yönetilir

Sağ üstteki avatarınıza gidin, ardından Bütünleştirmeler'e tıklayın. Mevcut topluluğun bütünleştirme sayfaları Gelen internet kancaları ve Giden internet kancaları listeler. Her webhook tek bir topluluğa aittir.

Varsayılan olarak, topluluk yöneticileri ve sistem yöneticileri webhook oluşturabilir. Bir sistem yöneticisi, Sistem Konsolu'nun izin ayarlarında bu hakkı diğer rollere verebilir. Bir sistem yöneticisi ayrıca her türü Sistem Konsolu › Bütünleştirmeler › Bütünleştirme yönetimi bölümünde kapatabilir: Gelen internet kancaları kullanılsın ve Giden internet kancaları kullanılsın her ikisi de varsayılan olarak açıktır.

A channel with messages from a CI bot and from GitHub, shown as cards with fields, pipeline stages and a button
Kart olarak çizilen entegrasyon iletileri: alanlar, iş akışı aşamaları ve bir eylem düğmesi.

Bir gelen webhook oluşturun

  1. Bütünleştirmeler bölümünde Gelen internet kancaları'nı, ardından Gelen internet kancası ekle'yi seçin.
  2. Bir Başlık ve bir Açıklama girin: bunlar yalnızca entegrasyon sayfalarında görünür.
  3. İletilerin varsayılan olarak gideceği Kanal'ı seçin. Bir özel kanal için, kanalın üyesi olmanız gerekir.
  4. Gönderenlerin başka yerlere ileti gönderememesi gerekiyorsa Şu kanala kilitlensin seçeneğini işaretleyin.
  5. İsteğe bağlı olarak, iletileri için bir Kullanıcı adı ve bir Profil görseli URL'si ayarlayın (bkz. Ad ve simge).
  6. Kaydet'i seçin. Gösterilen URL'yi kopyalayın: https://chat.example.com/hooks/<key>.
URL tek sır olan şeydir: ona sahip olan herkes kanala ileti gönderebilir. Halka açık depolardan uzak tutun ve sızarsa webhook'u silin.

API ile: POST /api/v4/hooks/incoming ve {"channel_id", "display_name", "description", "username", "icon_url", "channel_locked"}; yanıtın id alanı anahtardır. Komut satırından: amctl webhook create-incoming --channel <channel id> --user <user> --display-name "CI".

Bir gelen webhook'a ileti gönderin

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

Sunucu 200 yanıtı verir ve gövdesi ok olur. Ayrıca, Slack'in webhook'ları gibi, JSON'u bir payload alanında içeren application/x-www-form-urlencoded formatını da kabul eder, bu nedenle Slack için yapılmış araçlar genellikle değişiklik yapılmadan çalışır.

AlanAnlam
textMarkdown biçiminde ileti. attachments yoksa zorunludur. Sunucunun iletme sınırından uzun bir metin, birden çok iletmeye bölünür.
channelWebhook'un topluluğundaki başka bir kanal, adıyla (ops-alerts veya #ops-alerts), veya webhook'un sahibinden bir doğrudan ileti için @username. Webhook kanalı kilitliyse reddedilir. Eski ad town-square hâlâ topluluğun varsayılan kanalına, artık general adıyla, ulaşır.
username, icon_url, icon_emojiSunucu geçersiz kılma (override) izin verdiğinde gösterilecek ad ve resim.
attachmentsİletme ekleri, kartlar olarak çizilir (aşağıda).
propsİletide saklanan, bunları okuyan uygulamalar için ek özellikler.
typeBunu çizen bir uygulama için özel bir gönderi türü, örneğin custom_poll. system_ ile başlayan türler reddedilir.
root_idO konuya yanıt vermek için bir Konu'nun ilk iletmesinin kimliği (ID).
priorityİletme önceliği, örneğin {"priority": "urgent"}.
silenttrue, iletme Bildirim göndermeden gönderir.

Bir webhook'un gönderdiği her iletinin adının yanında, oluşturucusunun adıyla görünse bile, bir BOT etiketi bulunur; böylece insanlar bunu gerçek bir kişinin iletisinden ayırt edebilir. Webhook iletileri asla giden webhooks'ları tetiklemez.

Ad ve simge

Bir webhook, sunucu değişikliklere izin vermedikçe onu oluşturan kişi adına gönderir. Sistem Konsolu › Bütünleştirmeler › Bütünleştirme yönetimi bölümündeki, her ikisi de varsayılan olarak kapalı olan, iki ayar bunu değiştirir:

  • Bütünleştirmelerin kullanıcı adlarını değiştirebilmesi için açın (ServiceSettings.EnablePostUsernameOverride): webhook'un Kullanıcı adı'sı veya isteğin username alanı bunun yerine gösterilir; ikisi de yoksa ad webhook olur.
  • Bütünleştirmelerin profil görseli simgelerini değiştirmesini açın (ServiceSettings.EnablePostIconOverride): webhook'ün Profil görseli alanı, ya da isteğin icon_url veya icon_emoji alanı gösterilir.

İstekteki değer, webhook üzerinde saklanan değere önceliklidir.

Ekler

Ekler, metnin altına yapılandırılmış içerik ekler. Slack'in iletme eki biçimini izlerler:

{
  "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
  }]
}
AlanAnlam
fallbackKartı gösteremeyen yerler, örneğin Bildirimler için düz metin.
colorRenk çubuğu: bir onaltılık (hex) renk, ya da good, warning, danger.
pretextKartın üstündeki metin.
author_name, author_link, author_iconKüçük bir başlık satırı.
title, title_linkKartın başlığı, isteğe bağlı olarak bir bağlantı.
textKartın gövdesi, Markdown biçiminde.
fields{"title", "value", "short"} biçiminde bir liste; short alanları yan yana yerleşir.
image_url, thumb_urlAltta büyük, ya da kenarda küçük bir resim.
footer, footer_icon, tsBir alt bilgi satırı ve bir zaman (Unix saniyesi).
actionsDüğmeler ve menüler: bkz. Etkileşimli iletiler.

Kartlar: aşamalar ve grafikler

Antimatter, varsayılan arayüz tarafından çizilen ek dosyalara iki alan ekler:

  • stages: bir iş akışının adımları, en fazla 20 adet. Her biri {"name", "status"} biçiminde olup durumu passed, failed, running, pending, skipped veya canceled olabilir.
  • chart: son değerlerin küçük bir çizgi grafiği, {"values": [2 to 200 numbers], "threshold": number, "label": "…"}. Eşik, bir uyarı sınırı olarak kesikli bir çizgi olarak çizilir.
{
  "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"}
  }]
}

Klasik arayüz ve diğer istemciler bu iki alanı görmezden gelir, bu nedenle temel bilgileri text veya fields alanlarına da ekleyin.

Giden webhook oluşturun

Giden internet kancası, bir topluluğun Herkese açık kanallarını izler. İletinin ilk sözcüğü tetikleyici sözcüklerinden biriyle eşleştiğinde ya da bir kişi, ileti menüsünden (bir ileti işlemi) onu seçtiğinde, bir iletinizi adresinize gönderir.

  1. Bütünleştirmeler bölümünde Giden internet kancaları seçeneğini, ardından Giden internet kancası ekle seçeneğini seçin.
  2. Başlık ve Açıklama alanlarını doldurun.
  3. İstek için İçerik Türü seçin: application/x-www-form-urlencoded veya application/json.
  4. Bir Kanal seçin, Tetikleyici sözcükler (her satıra bir tane) alanına değer girin ya da her ikisini de yapın. Bir kanal seçip tetikleyici sözcük girmezseniz, o kanalın tüm iletileri gönderilir. Her ikisini de girerseniz, iletinin her iki koşulda da eşleşmesi gerekir.
  5. Tetiklenme zamanı altında İlk sözcük bir tetikleyici sözcük ile birebir eşleştiğinde, İlk sözcük bir tetikleyici sözcük ile başladığında ya da İleti menüsünden seçeneğini seçin. İleti menüsünden seçeneğinde tetikleyici sözcükler alanı kaybolur, Kanal alanı isteğe bağlı hale gelir (kanal seçilmezse, işlem topluluğun tüm herkese açık kanallarında sunulur) ve Başlık alanı zorunlu hale gelir: bu, menüdeki işlemin adıdır.
  6. Geri dönüş adresleri (her satıra bir tane) alanına değer girin. Her adres, eşleşen her iletiyi alır.
  7. İsteğe bağlı olarak, yanıtlar için kullanılacak Kullanıcı adı ve Profil görseli alanlarını ayarlayın. İleti menüsünden gelen bir işlem için, Simgesi alanı Profil görseli alanının yerini alır: bir .png veya .jpg görselinin adresi ya da Antimatter'ın varsayılan arayüzünde yüklenmiş bir görsel. Menü bunu gri renkte gösterir; simge girilmezse, işlem nötr bir simge alır.
  8. Kaydet seçeneğini seçin ve görünen belirteci (token) kopyalayın. Servisiniz, isteklerin sunucunuzdan geldiğini doğrulamak için bunu kullanır.

API ile: POST /api/v4/hooks/outgoing ve {"team_id", "channel_id", "trigger_words", "trigger_when", "callback_urls", "content_type", "display_name"} (trigger_when: birebir eşleşme için 0, "başlıyor" için 1, "ileti menüsünden" için 2). trigger_when değeri 2 olan bir webhook tetikleyici sözcük almaz ve bir display_name gerektirir. Simgesini POST /api/v4/hooks/outgoing/{hook_id}/icon ile yükleyin (multipart, alan image: PNG, JPEG veya GIF, 128 px PNG olarak saklanır); ardından icon_url değeri GET /api/v4/hooks/outgoing/{hook_id}/icon adresini gösterir.

Hizmetiniz özel bir ağda bulunuyorsa, bir sistem yöneticisinin adresini Şuraya yapılan güvenilmemiş iç bağlantılara izin verilsin (ServiceSettings.AllowedUntrustedInternalConnections) alanında izin vermesi gerekir. Aksi takdirde sunucu özel adreslere istek göndermez.

Giden istek

Antimatter, içerik türüne göre JSON veya form kodlu olarak bu alanlarla bir POST isteği gönderir:

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

Herhangi bir işlem yapmadan önce token değerini webhook'un token'ıyla karşılaştırın. Form kodlu sürümde timestamp milisaniye değil saniye cinsindendir. Sunucu, Bütünleştirme isteği zaman aşımı süresi boyunca (varsayılan olarak 30 saniye, ServiceSettings.OutgoingIntegrationRequestsTimeout) yanıtınızı bekler.

Giden webhook'a yanıt gönderme

Bir yanıt göndermek için JSON ile yanıt verin. Hiçbir şey göndermemek için boş bir gövde ile yanıt verin.

{
  "text": "Deploying **api 2.4.0** to staging…",
  "response_type": "comment",
  "username": "deploy-bot",
  "icon_url": "https://chat.example.com/static/deploy.png"
}
  • text ve attachments: yanıt. İkisinin de yoksa hiçbir şey gönderilmez.
  • response_type: comment, yanıtı tetikleyen mesajın konusuna gönderir; aksi halde kanala gönderilir.
  • username, icon_url: sunucu geçersiz kılma (override) izin verdiğinde gösterilir; aksi halde webhook'un kendi değerleri kullanılır.
  • props, type, priority: gelen webhook'lar için olduğu gibidir.

Yanıt, webhook'un oluşturucusu olarak, varsa geçersiz kılınmış ad altında gönderilir. Kısa bir yanıtın ötesinde bir şey için hemen yanıt verin ve daha sonra gelen bir webhook veya API ile gönderin.

İleti işlemleri

Bir ileti işlemi, Tetiklenme zamanı değeri İleti menüsünden olarak ayarlanmış bir giden webhook'tur. Gönderilen iletiler üzerinde asla tetiklenmez. Bunun yerine kişiler, İleti işlemleri (⋯) › Diğer işlemler bölümünde, Bütünleştirmeler başlığı altında ve simgesiyle birlikte görür. Klasik arayüz, ileti işlemlerini göstermez. İşlem seçildiğinde yalnızca o ileti, geri bildirim URL'lerine gönderilir ve kısa bir bildirim, işlemin adının Gönderildi ifadesiyle birlikte veya ephemeral_text değerinizle gösterilir.

  • Görünme yeri: webhook'un kanalı içinde veya kanal belirtilmediyse, topluluğunun tüm herkese açık kanallarında. Yalnızca herkese açık kanallarda ileti işlemleri bulunur.
  • Konuklar, yalnızca içinde bulundukları kanala bağlı işlemleri görür; topluluk geneli işlemleri görmez.
  • Arşivlenmiş ve salt okunur kanallar: İleti yine de gönderilebilir. Bir kanal arşivlendiğinde, ona bağlı webhook'lar silinir; bu nedenle arşivlenmiş bir kanalda yalnızca topluluk geneli işlemler kalır. Kişinin oraya gönderemediği bir yanıt, yalnızca ona gösterilir.
  • Hız sınırı: Her kişi, 5'lik bir patlama (burst) sonrasında dakikada 10 ileti işlemi çalıştırabilir. Bu sınırı aşan isteklerde sunucu 429 yanıtı verir.
  • Özel ağlar: Diğer giden webhook'lerde olduğu gibi, iç adreslere erişim için Şuraya yapılan güvenilmemiş iç bağlantılara izin verilsin ayarında izin verilmelidir.

İstek

Yük (payload), webhook'un içerik türüne göre JSON veya form kodlu olarak gönderilir:

{
  "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 ve user_name, işlemi seçen kişiyi; post_user_id ve post_user_name ise ilenin yazarını belirtir.
  • Yalnızca o ileti gönderilir, konusunun geri kalanı asla gönderilmez.
  • files, işlemi seçen kişinin dosyaları indirebilme yetkisine sahip olması durumunda yalnızca ilenin dosyalarını listeler. Bir link adresinden dosya indirmek, API'deki herhangi bir dosya için olduğu gibi bir oturum veya token gerektirir.
  • Okunduğunda imha edilen (burn-on-read) bir ileti, metni ve dosyaları olmadan, burn_on_read değeri true olarak ayarlanarak gönderilir.
  • Form kodlu gönderimde dosyalar, aynı sırayla tekrarlanan file_id, file_name ve file_link alanları olarak gelir.

Yanıt

Herhangi bir giden webhook için olduğu gibi yanıtlayın (bkz. Giden webhook'a yanıt): text veya attachments kanala bir yanıt gönderir, "response_type": "comment" ise iletiyi ilgili konuya (thread) gönderir. Ayrıca ephemeral_text ile de (300 karakterle sınırlı) yanıt verebilirsiniz: bu, eylemi seçen kişiye yalnızca bildirim alanında gösterilir. Boş bir gövde hiçbir şey göndermez.

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

API ile

  • GET /api/v4/channels/{channel_id}/message_actions: bir kanalda seçilebilecek eylemler, id, display_name, description ve icon_url ile birlikte. Ne jetonlar ne de geri çağrı (callback) URL'leri döndürülür.
  • POST /api/v4/posts/{post_id}/message_actions/{hook_id}: okuyabildiğiniz bir iletide bir eylemi çalıştırır. {"ephemeral_text"} ile yanıt verir.

Bir webhook çalışmıyorsa

  • Hook URL'den 501: sunucuda gelen webhook'lar kapalıdır.
  • 400 "Failed to decode the payload…": JSON geçersizdir veya form alanının adı payload değildir. "No text specified.", istekte ne text ne de attachments olduğu anlamına gelir.
  • 403: webhook başka bir kanala kilitlenmiştir veya sahibi artık kanalı okuyamıyor.
  • Giden webhook asla tetiklenmez: kanal özel, tetikleyici ilk kelime değil, ileti bir webhook'tan geldi veya webhook İletiden menüden tetiklenmek üzere yapılandırılmış.
  • Bir iletiden eylem menüde görünmüyor: kanal özel, eylem başka bir kanala bağlı, kişi konuk ve eylem bir kanala bağlı değil veya giden webhooks kapalı.
  • Bir iletiden eylem çalıştırılırken 404: eylem mevcut değil veya o kişi için o iletinin kanalını kapsamıyor. 429: kişi bir dakikadan fazla 10 eylem çalıştırdı. 502: hiçbir geri çağrı (callback) URL'sine ulaşılamadı (nedeni günlükte bulunur).
  • Günlükler: İnternet kancası hata ayıklaması kullanılsın açıkken (LogSettings.EnableWebhookDebugging) ve günlük seviyesi DEBUG olduğunda, sunucu başarısız gelen isteklerin yüklerini (payload) günlüğe yazar. Başarısız giden çağrılar Outgoing Webhook POST failed olarak günlüğe kaydedilir.