Webhook ile mesaj gönder
Webhook, topluluğuna mesaj gönderen bir URL’dir. CI, izleme, bir cron işi ya da bir betik gibi HTTP isteği yapabilen herhangi bir şeyden ona JSON gönder, mesaj kanalda görünsün.
Neler yapabilirsin
- Metin ya da kart gönderDüz metin ya da başlığı, rengi, markdown’ı, alanları ve görselleri olan bir kart.
- Dosya ekleMesaj başına en fazla beş dosya: loglar, raporlar, ekran görüntüleri.
- Düğme ekleBağlantılar ya da kartı değiştiren veya servisine ulaşan düğmeler.
- Sonradan değiştirYanıt, mesajı güncellemek ya da silmek için bir callback URL içerir.
Uygulamada
CI’dan tek istek, #deploys kanalında tek kart. En üstteki ad, webhook’a verdiğin addır.
Hızlı başlangıç
Webhook’u oluştur
Masaüstü uygulamasında topluluğunun Manage Server → Webhooks bölümünü aç, bir webhook oluştur, mesaj gönderebileceği kanalları seç ve bir kanalın URL’sini kopyala. Şu biçimdedir:
urlhttps://mss.gs/api/v1/webhook/{webhook_guid}/{token}/{channel_guid}Mesaj gönder
JSON’u webhook’un gizli anahtarıyla imzala ve POST et. Masaüstü uygulamasında oluşturulan bir webhook’un her zaman bir gizli anahtarı vardır: onu webhook’un ayarlarındaki Webhook Secret alanından kopyala.
bashBODY='{"content": "Build #1847 passed on main"}' SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MSSGS_WEBHOOK_SECRET" | sed 's/^.* //') curl -X POST "$MSSGS_WEBHOOK_URL" \ -H "Content-Type: application/json" \ -H "X-Mssgs-Signature: sha256=$SIG" \ -d "$BODY"Yanıtı oku
Yanıt sana mesajın id’sini ve mesajı sonradan değiştirmek için bir
callback_urlverir.json{ "success": true, "message_id": "aZZ1a2b-...", "callback_url": "https://mss.gs/api/v1/trigger-callback/8f14e45f-...", "stream_url": "https://mss.gs/api/v1/instant/6b1e...c0?token=a1b2c3d4-..." }
Neler gönderebilirsin
Bir mesaj ya kısa biçimdedir (başlığı ve rengi olan bir metin) ya da tam bir karttır; ikisi de düğme ve dosya taşıyabilir. Kartın üstündeki ad her zaman webhook’un kendi adıdır. Webhook’un ayarlarında ayrıca görsel gönderip gönderemeyeceğine ve kişilerden bahsedip bahsedemeyeceğine de karar verirsin.
Kısa biçim
Çoğu uyarı için yeterli.
{
"content": "Server backup completed at 03:00 UTC",
"color": "green",
"title": "Backup Bot"
}| Alan | Tür | Ne yapar |
|---|---|---|
content | string | Mesaj metni. Kart ya da dosya göndermiyorsan zorunlu. |
color | string | blue (varsayılan), green, orange, red, yellow ya da purple. |
title | string | Metnin üstünde bir başlık. Varsayılan olarak webhook’un adı. |
Tam bir kart
Bağlantılı başlığı, alt başlığı, markdown’ı, alanları ve görselleri olan bir kart için bir message_container gönder. Webhook üzerinden bir kart type, color, title, title_url, sub_title, description, fields, avatar_url, image_url, image_base64, images ve yükleme alanlarını kabul eder. Durum kapsülü, rozet, diff istatistikleri ve katlanmış akıl yürütme komut yanıtları içindir. Tüm alanlar mesaj kartları sayfasında.
{
"message_container": {
"type": "embed_message",
"color": "green",
"title": "Build #1847 passed",
"title_url": "https://ci.example.com/builds/1847",
"description": "All 212 tests green on **main**.",
"fields": [
{ "field": "Duration", "value": "2m 34s" },
{ "field": "Commit", "value": "1a2b3c4" }
]
}
}Düğmeler
Mesajın altına düğme koymak için bir actions dizisi ekle. Nasıl çalıştıkları düğmeler sayfasında.
Dosyalar
Bir mesajla gerçek dosyalar gönder: bir log, bir rapor, bir ekran görüntüsü. Diğer ekler gibi görünürler: bir indirme satırı olarak ya da görseller, video ve ses için doğrudan mesajın içinde. Yalnızca dosyalardan oluşan bir mesaj da olur: content alanını ve kartı çıkar.
{
"message_container": {
"color": "orange",
"title": "Log dump: ios",
"description": "DMs stopped arriving after switching networks"
},
"attachments": [
{
"name": "mssgs-logs-20260803-141205.log",
"content_base64": "MjAyNi0wOC0wMyAxNDoxMjowNSBbV1NdIGNvbm5lY3RlZAo=",
"mime_type": "text/plain"
}
]
}| Alan | Tür | Ne yapar |
|---|---|---|
name | string | Dosyanın indirildiğinde alacağı ad. Zorunlu. Bir yol verilirse yalnızca son parçası kalır. |
content_base64 | string | Dosyanın baytları base64 olarak, ham ya da bir data: URI’si biçiminde. mssgs dosyayı saklar ve mesajda yalnızca bir bağlantı tutar. |
mime_type | string | content_base64 içeriğinin türü. Varsayılan text/plain. |
url | string | mssgs’te zaten barındırılan bir dosya: bir /static/... yolu ya da bir https://mss.gs/... URL’si. |
content_base64 ya da url alanlarından tam olarak birini gönder. İkisi birden ya da hiçbiri hatadır.| Limit | Değer |
|---|---|
| Mesaj başına dosya | 5 |
| Çözüldükten sonra dosya başına boyut | 8 MB |
| Dosya adı | 200 karakter |
| İsteğin tamamı | Yaklaşık 10 MB. Base64 bir dosyayı üçte bir büyütür, bu yüzden yaklaşık 7 MB’tan büyük tek bir dosya sığmaz. |
url neden yalnızca mssgs adreslerini kabul ediyor
Bir webhook URL’si çoğu zaman başka panolara yapıştırılır. Sızan bir URL, birinin her üyenin uygulamasına kendi seçtiği bir sunucudan dosya çektirmesine izin vermemeli. Dosyan başka bir yerdeyse onu content_base64 olarak gönder, mssgs barındırsın.
Başarısız bir yükleme mesajı başarısız kılmaz
Dosyalar önceden kontrol edilir ama sonradan yüklenir. Bir yükleme başarısız olursa o dosya dışarıda kalır ve mesajın geri kalanı hata vermeden yine gönderilir: dosyayı kaybetmek raporu kaybetmekten iyidir. Bir dosya önemliyse ulaştığını kontrol et.
Komut satırından bir dosya
BODY='{"attachments":[{"name":"report.csv","content_base64":"'"$(base64 < report.csv | tr -d '\n')"'","mime_type":"text/csv"}]}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MSSGS_WEBHOOK_SECRET" | sed 's/^.* //')
printf '%s' "$BODY" | curl -sS -X POST "$MSSGS_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-H "X-Mssgs-Signature: sha256=$SIG" \
--data-binary @-İstekleri imzalama
Gizli anahtarı olan bir webhook yalnızca onu bildiğini kanıtlayan istekleri kabul eder ve masaüstü uygulamasında oluşturulan bir webhook’un her zaman bir gizli anahtarı vardır (ayarlarındaki Webhook Secret). Ham istek gövdesini gizli anahtarla HMAC-SHA256 kullanarak imzala ve küçük harfli hex özeti X-Mssgs-Signature başlığında sha256=<hex> olarak gönder.
import crypto from 'node:crypto';
const body = JSON.stringify({ content: 'Deploy finished' });
const signature = crypto.createHmac('sha256', process.env.MSSGS_WEBHOOK_SECRET)
.update(body)
.digest('hex');
await fetch(process.env.MSSGS_WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Mssgs-Signature': `sha256=${signature}`
},
body
});401 ve {"error": "INVALID_SIGNATURE"} alır. Yalnızca gizli anahtarı olmayan bir webhook, örneğin MCP üzerinden webhook_secret olmadan oluşturulan bir webhook, imzasız istekleri kabul eder.GitHub’ın kendi X-Hub-Signature-256 başlığı da kabul edilir, bu yüzden aynı gizli anahtara sahip bir GitHub webhook’u olduğu gibi çalışır. İmzada zaman damgası yoktur, dolayısıyla yakalanmış bir isteğin yeniden gönderilmesini engellemez: asıl önemli sır URL’nin kendisi olarak kalır.
Yanıtlar ve hatalar
Gönderilen bir mesaj, id’si ve onu 30 dakika boyunca güncellemek ya da silmek için bir callback_url ile döner.
{
"success": true,
"message_id": "aZZ1a2b-...",
"callback_url": "https://mss.gs/api/v1/trigger-callback/8f14e45f-...",
"stream_url": "https://mss.gs/api/v1/instant/6b1e...c0?token=a1b2c3d4-..."
}error kodu olarak taşır. Durum kodu ne olursa olsun, error anahtarı olan her gövdeyi başarısızlık olarak say.HTTP/1.1 200 OK
Content-Type: application/json
{ "error": "ATTACHMENT_TOO_LARGE" }const res = await fetch(webhookUrl, { method: 'POST', headers, body });
const reply = await res.json().catch(() => null);
// A rejected payload still comes back as 200: read the body.
if (!res.ok || (reply && reply.error)) {
throw new Error(`webhook rejected: ${reply?.error ?? res.status}`);
}Mesajda düğmeler varsa yanıtta bir stream_url de bulunur: o mesaja gelen yanıtların, tepkilerin ve düğme basışlarının canlı akışı. 10 dakika, "sse_event_extended_timeout": true gönderirsen bir saat açık kalır. Canlı güncellemeler sayfasına bak.
Durum kodları
| Durum | Ne zaman |
|---|---|
401 | Webhook’un bir gizli anahtarı var ve imza eksik ya da yanlış. |
403 | Bu webhook o kanala mesaj gönderemez. |
404 | Bu URL’de bir webhook yok. |
413 | İstek çok büyük. |
429 | Çok fazla istek. Yavaşla ve tekrar dene. |
502 | Mesaj iletilemedi. Tekrar dene. |
Hata kodları
| Kod | Anlamı |
|---|---|
MISSING_CONTENT | Gönderilecek bir şey yok: metin, kart ve dosya yok. |
INVALID_MESSAGE_CONTAINER | message_container bir nesne değil. |
INVALID_MESSAGE_CONTAINER_TYPE | Kart türü embed_message ya da system_message değil. |
MISSING_MESSAGE_CONTAINER_DESCRIPTION | Bir kartın, yükleme kartı değilse, bir açıklamaya ihtiyacı vardır. |
MISSING_MESSAGE_CONTAINER_LOADER_TEXT | Bir yükleme kartının loader_text alanına ihtiyacı vardır. |
INVALID_WEBHOOK_BINDING | Bu webhook o kanala mesaj gönderemez. |
INVALID_SIGNATURE | İmza başlığı eksik ya da yanlış. |
REQUEST_BODY_TOO_LARGE | İstek boyut limitinin üzerinde. |
PUBLISH_FAILED | Mesaj iletilemedi. |
INVALID_ACTIONS_FORMAT, INVALID_ACTION_MISSING_FIELDS, DUPLICATE_ACTION_ID, INVALID_TRIGGERS_FORMAT, INVALID_TRIGGER_MISSING_ACTION, INVALID_TRIGGER_ACTION_NOT_ALLOWED | Bir düğmede sorun var. Düğmeler sayfasına bak. |
Dosya hataları
| Kod | Anlamı |
|---|---|
INVALID_ATTACHMENTS_FORMAT | attachments bir liste değil ya da bir öğesi nesne değil. |
TOO_MANY_ATTACHMENTS | Beşten fazla dosya. |
MISSING_ATTACHMENT_NAME | Bir dosyanın adı yok. |
INVALID_ATTACHMENT_NAME | Addan geriye kullanılabilir bir şey kalmıyor, örneğin ... |
MISSING_ATTACHMENT_SOURCE | Ne url ne de content_base64 var. |
AMBIGUOUS_ATTACHMENT_SOURCE | Hem url hem de content_base64 var. |
INVALID_ATTACHMENT_BASE64 | base64 çözülemiyor. |
ATTACHMENT_TOO_LARGE | Bir dosya çözüldükten sonra 8 MB’ı aşıyor. |
INVALID_ATTACHMENT_URL | url bir mssgs adresi değil. |
Limitler
| Limit | Değer |
|---|---|
| İstek boyutu | Yaklaşık 10 MB |
| Mesaj başına dosya | 5 dosya, her biri en fazla 8 MB |
| Kart açıklaması | En fazla 50.000 bayt. 1.000 bayt aşıldığında üyeler başlangıcı ve bir Show more düğmesi görür. |
| Mesajı sonradan güncelleme | callback_url üzerinden 30 dakika |
| Düğmeli bir mesajın canlı akışı | 10 dakika ya da istek üzerine bir saat |
İstekler hız sınırına tabidir. 429 aldığında yeniden göndermeden önce bekle ve art arda gelen uyarıları tek bir mesajda topla.
GitHub, UniFi ve App Store Connect
Bu servislerden birini bir webhook URL’sine yönlendir; mssgs onu tanır ve sen hiçbir payload yazmadan düzgün bir kart paylaşır. Entegrasyonlar sayfasına bak. Bunlara {"success": true} ile ve callback URL olmadan yanıt verilir.
| Kaynak | Nasıl tanınır | Ne paylaşır |
|---|---|---|
| GitHub | x-github-event başlığı | Push’lar, pull request’ler ve incelemeler, issue’lar ve yorumlar, dallar ve etiketler, sürümler. Bir issue ya da pull request’te art arda gelen değişiklikler tek bir kartta toplanır. |
| UniFi Protect | protect-alarm-manager user agent değeri | Kapı zili, hareket ve kameralarının algıladığı kişiler, araçlar ya da paketler. |
| App Store Connect | Bildirim gövdesi ya da x-apple-signature başlığı | App Store Connect bildirimleri. |