---
title: "Webhook’lar: bir mssgs kanalına mesaj gönder"
description: "CI’dan, izleme araçlarından ya da bir betikten tek HTTP isteğiyle bir mssgs kanalına mesaj ya da kart gönder. Biçimler, dosyalar, imzalama ve limitler."
canonical: https://docs.mss.gs/tr/webhooks
language: tr
---

# 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önder** Düz metin ya da başlığı, rengi, markdown’ı, alanları ve görselleri olan bir kart.

- **Dosya ekle** Mesaj başına en fazla beş dosya: loglar, raporlar, ekran görüntüleri.

- **Düğme ekle** Bağlantılar ya da kartı değiştiren veya servisine ulaşan düğmeler.

- **Sonradan değiştir** Yanıt, mesajı güncellemek ya da silmek için bir callback URL içerir.

Uygulamada

#### Build #1847 başarılı

CI’dan tek istek, #deploys kanalında tek kart. En üstteki ad, webhook’a verdiğin addır.

- [Hızlı başlangıç](#quick-start)

- [Neler gönderebilirsin](#format)

- [Dosyalar](#attachments)

- [İmzalama](#signing)

- [Yanıtlar ve hatalar](#responses)

- [Limitler](#limits)

- [GitHub, UniFi, App Store](#special)

## 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:

```url
https://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.

```bash
BODY='{"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_url verir.

```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.

```json
{
  "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ı](https://docs.mss.gs/tr/bots) sayfasında.

```json
{
  "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" }
    ]
  }
}
```

#### Build #1847 başarılı

### Düğmeler

Mesajın altına düğme koymak için bir actions dizisi ekle. Nasıl çalıştıkları [düğmeler](https://docs.mss.gs/tr/buttons) 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.

```json
{
  "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. |

| 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

```bash
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.

```javascript
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
});
```

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.

```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-..."
}
```

```http
HTTP/1.1 200 OK
Content-Type: application/json

{ "error": "ATTACHMENT_TOO_LARGE" }
```

```javascript
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](https://docs.mss.gs/tr/live-updates) 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](https://docs.mss.gs/tr/buttons) 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](https://mss.gs/tr/integrations) 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. |

## Geliştirmeye devam et
