Bir webhook, takımınızın etkinliğini olduğu anda sahip olduğunuz bir URL'ye gönderir. Denetim Günlüğü'nüze düşen her eylem; kendi sunucunuza, kendi botunuza veya bir iç araca imzalı bir JSON POST olarak iletilebilir: yoklama yok, dışa aktarma yok, paneli kazıma yok.
Bu sayfadaki her şeyi tek bir kural belirler. Bir webhook tam olarak takımınızın Etkinlik Günlüğü'nün gösterdiğini taşır, fazlasını değil. Kendi kapsamı olan paralel bir akış değil, makineler için daha zengin bir yük değil. Bu sayfada yoksa gövdede de yoktur.

📍 Nerede bulunur
Takımınızın kendi sayfasında Takım Ayarları → Webhook'lar. Takım başına en fazla üç uç nokta; her birinin kendi URL'si, kendi kategorileri ve kendi imza anahtarı vardır.
Kimler kurabilir: takım sahibi veya rolü Bir sunucuyu ekipten çıkarma iznini içeren bir üye. Bu, Etkinlik Günlüğü'nün kendisini açan kuralın aynısıdır: bir webhook o sayfanın gösterdiğini iletir, yani onu okumaya izinli olmak iletmeye izinli olmaktır. Bkz. Takım rolleri ve izinleri.
🎯 Neler gönderilir, neler asla gönderilmez
Kategorileri siz seçersiniz. Yalnızca işaretlediğiniz kategoriler iletilir:
| Kategori | Neleri kapsar |
|---|---|
| Özellikler | Bir özelliğin etkinleştirilmesi, devre dışı bırakılması veya ayarlarının kaydedilmesi |
| Sunucular | Takıma bir sunucunun eklenmesi veya çıkarılması |
| Takım | Takımın yeniden adlandırılması, rollerin düzenlenmesi, webhook'ların değiştirilmesi |
| Üyeler | Üyelerin davet edilmesi, eklenmesi, çıkarılması veya ayrılması |
| Moderasyon | Yaptırımlar, itirazlar, raporlar, biletler, temizlenen geçmişler |
| Abonelik | Takımdaki abonelik değişiklikleri |
| Faturalandırma | Takımdaki faturalandırma olayları |
| Platformun bu takım üzerindeki işlemleri | Bir platform yöneticisinin sunucularınızdan birine yaptığı işlem |
🚫 Üç şey asla iletilmez
- IP adresleri. Etkinlik Günlüğü'nde bir IP yalnızca ait olduğu kişiye gösterilir, başka kimseye değil. Bir webhook'un karşısında kontrol edilecek bir okuyucu yoktur, bu yüzden alan gönderilmez: yükten boşaltılmaz, kaldırılır.
- Sizinle ilgili olmayan arka ofis işlemleri. Platform genelindeki yönetim bir takım taşımaz, bu yüzden dağıtımdaki hiçbir şey ona ulaşamaz. Platformun bu takım üzerindeki işlemleri kategorisi yalnızca bir yöneticinin sizin sunucularınıza yaptığı şeydir.
- Kimlik bilgileri. Bir token, anahtar veya sır gibi görünen her alan, önce/sonra çiftinin her iki tarafında da
••••••••olarak gelir. Bu, sayfanın yaptığı maskelemeden bağımsız olarak çıkışta bir kez daha yapılır.
Oturum açmalar sunulmaz. Denetim kaydında bir auth kategorisi vardır ve yukarıdaki listede bilerek yoktur: oturum açma olaylarını üçüncü taraf bir sunucuya gözetimsiz ve süresiz göndermek, birinin açması gereken bir sayfada göstermekten farklı bir eylemdir. Daha sonra eklenebilir.
📦 Teslimat
Her teslimat, JSON gövdeli tek bir POST'tur:
{
"version": 1,
"delivery_id": "0a4b2f0e-8c6e-4a5f-9b3d-2f6c1e0d7a11",
"event": "server.feature.enabled",
"category": "feature",
"team": { "id": 12, "name": "Night Shift" },
"data": {
"id": 918273,
"action": "server.feature.enabled",
"category": "feature",
"description": "Enabled Starboard",
"actor_name": "Ava",
"actor_role": "moderator",
"is_admin_action": false,
"team_id": 12,
"team_name": "Night Shift",
"server_id": 4,
"server_name": "Night Shift HQ",
"subject_label": "Starboard",
"changes": { "threshold": { "before": 3, "after": 5 } },
"metadata": null,
"created_at": "2026-09-06T09:41:12+00:00"
}
}
Bu on beş alan data'nın tamamıdır: Etkinlik Günlüğü'nün gösterdiği aynı on beş alan, IP adresi hariç. Herhangi biri null olabilir: sunucusu olmayan bir eylem "server_id": null taşır, karşılaştırılacak bir şeyi olmayan bir eylem "changes": null taşır. Olay başına bir biçim varsaymak yerine bunları savunmacı biçimde okuyun.
version, zarf sürümüdür. Biçim büyüdüğünde alıcınızın tahmin yürütmek yerine buna göre dallanabilmesi için vardır.event, denetlenen eylemdir. Yüz otuzdan fazlası vardır ve liste platformla birlikte büyür: bir önek veyacategoryüzerinden eşleştirin, asla eksiksiz bir ad listesiyle değil.delivery_id, aynı olayın tüm yeniden denemelerinde sabittir. Yinelenenleri ayıklamayı mümkün kılan budur; aşağıya bakın.data, denetim girdisinin kendisidir; Etkinlik Günlüğü'nün gösterdiği nesnenin aynısı.
📨 Başlıklar
| Başlık | Değer |
|---|---|
User-Agent |
YAWBDB-Webhooks/1.0 |
X-YAWBDB-Event |
Eylem adı, gövdedeki event ile aynı |
X-YAWBDB-Delivery |
Teslimat kimliği, delivery_id ile aynı |
X-YAWBDB-Timestamp |
İstek oluşturulduğunda saniye cinsinden Unix zamanı |
X-YAWBDB-Signature |
v1= ardından onaltılık özet |
🔐 İmzayı doğrulama
Uç noktanızın URL'sini öğrenen herkes oraya her şeyi POST edebilir. İmza, bizim teslimatlarımızı onlarınkilerden ayırmanın yoludur.
Özet, zaman damgası, bir nokta ve ardından ham istek gövdesi üzerinde HMAC-SHA256'dır ve imza anahtarınızla anahtarlanır:
signed_string = X-YAWBDB-Timestamp + "." + raw_body
signature = "v1=" + hex( hmac_sha256(signed_string, secret) )
Üç ayrıntı yük taşıyıcıdır ve herhangi birini atlamak bir açık bırakır:
- Ham baytları imzalayın, herhangi bir JSON ayrıştırmasından önce. Gövdeyi yeniden serileştirmek onu değiştirir (anahtar sırası, kaçırılmış eğik çizgiler, unicode) ve özet eşleşmez.
- Zaman damgası imzalanan dizenin içindedir, yalnızca yanında değil. Yeniden oynatmaları reddetmenizi sağlayan budur: zaman damgası birkaç dakikadan eski bir teslimatı reddedin (beş dakika makul bir penceredir) ve bir saldırgan geçen hafta yakaladığı bir isteği yeniden gönderemez. Zaman damgası imzalı olduğundan onu düzenleyemez de.
- Sabit zamanda karşılaştırın. Düz bir
==ilk farklı baytta döner ve bu zamanlama farkı bir imzayı bayt bayt geri kazanmak için yeterlidir.hash_equals,crypto.timingSafeEqual,hmac.compare_digestkullanın; dilinizde ne deniyorsa.
PHP
$raw = file_get_contents('php://input');
$timestamp = (int) ($_SERVER['HTTP_X_YAWBDB_TIMESTAMP'] ?? 0);
$given = $_SERVER['HTTP_X_YAWBDB_SIGNATURE'] ?? '';
if (abs(time() - $timestamp) > 300) {
http_response_code(400); // too old, or clock is wrong
exit;
}
$expected = 'v1=' . hash_hmac('sha256', $timestamp . '.' . $raw, $secret);
if (!hash_equals($expected, $given)) {
http_response_code(401);
exit;
}
http_response_code(200); // accepted
Node.js (Express)
import crypto from 'node:crypto';
// The raw body is required - express.json() alone destroys it.
app.post('/yawbdb', express.raw({ type: 'application/json' }), (req, res) => {
const timestamp = Number(req.get('X-YAWBDB-Timestamp'));
const given = req.get('X-YAWBDB-Signature') ?? '';
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return res.sendStatus(400);
const expected = 'v1=' + crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${req.body}`)
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(given);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return res.sendStatus(401);
res.sendStatus(200);
});
v1= öneki şemayı adlandırır. Bir gün değişirse, öneki kontrol eden bir alıcı bilinmeyen bir şemayı sessizce yanlış okumak yerine bilerek reddedebilir.
🔑 Gizli anahtar
64 onaltılık karakter, sizin için üretilir, yalnızca bir kez gösterilir: uç noktayı oluşturduktan veya Yeni gizli anahtar'a bastıktan hemen sonra panelde. Sonrasında hiçbir şey onu geri okumaz: ne sayfa, ne API, ne de bir dışa aktarma. Kaybederseniz yenisini üretirsiniz.
Yenilemek, o andan itibaren gönderilen her şey için hemen etkili olur. Kuyruğa alınmış teslimatlar, kuyruk boşalana kadar eski anahtarla imzalanmış olarak gitmeye devam eder; bu yüzden kısa bir çakışma bekleyin ve önce alıcınızı güncelleyin.
🔁 Teslimat, yeniden denemeler ve yinelenenleri ayıklama
- Yalnızca bir
2xxalındı sayılır. Başka her şey (3xx,4xx,5xx) bir hatadır. Hızlı yanıt verin ve işi sonra yapın. - Yönlendirmeler izlenmez. Bir
302bir sıçrama değil, bir hatadır. Bize son URL'yi verin. - Zaman aşımları kısadır: bağlanmak için üç saniye, yanıt vermek için beş saniye. Bu bir bildirimdir, uzaktan yordam çağrısı değil: önce onaylayın, sonra işleyin.
- Dört deneme, 30 saniye, 2 dakika, sonra 10 dakika arayla: baştan sona kabaca on iki dakika. Bu bir dağıtımı karşılar, bir kesintiyi değil.
- Yeniden denemeler aynı
delivery_id'yi kullanır. HerPOST'u yeni sayan bir alıcı, ilk denememizin sizin tarafınızda başarılı olduğu ama bizim tarafımızda zaman aşımına uğradığı gün çift sayım yapar. Kimliği saklayın ve zaten işlediğinizi yok sayın. - Sıra garanti edilmez. Teslimatlar bağımsız olarak kuyruğa alınır; yeniden denenen bir teslimat, daha sonra gerçekleşen olaylardan sonra gelir. Sıra sizin için önemliyse
data.created_atkullanın.
⛔ Otomatik kapatma
Art arda 20 hatadan sonra uç nokta kapatılır ve panel bunu kartta belirtir. Yanıt vermeyi bırakan bir uç nokta genellikle kalıcı olarak bırakmıştır ve kimse bize haber vermeye gelmez; sonsuza kadar yeniden denemek, eylem başına süresiz bir istek ve bir geçmiş satırına mal olurdu.
Yeniden başlatmak için: alıcınızı düzeltin, ardından webhook'u Düzenle ile açın ve Olayları bu adrese ilet seçeneğini yeniden işaretleyin. Yeniden açmak sayacı sıfırlayan şeydir; böylece onarılmış bir uç nokta yeniden kararmaya bir hata uzaklıkta olmaz.
🧪 Test gönderme
Test gönder, uç noktanıza hemen gerçek, imzalı bir istek gönderir ve size durum kodunu ve gidiş-dönüş süresini gösterir. Bu bir simülasyon değildir: her gerçek teslimatın geçtiği aynı koddan, aynı başlıklarla geçer; böylece testi geçen bir uç nokta, testin hiç göndermediği bir başlık yüzünden üretim trafiğini reddedemez.
Test gövdesi "event": "panel.webhook.test" ve "category": "test" taşır, böylece alıcınız onu tanıyabilir.
Bir değil, iki varış bekleyin. Düğmeye basmak başlı başına denetlenen bir takım eylemidir. Bu yüzden uç noktanız test teslimatını alır ve Takım kategorisine abone ise bir an sonra
team.webhook.testediçin ikinci, sıradan bir teslimat daha alır. Bu doğrudur ve bir döngü değildir.
Bir test hiçbir zaman 20 hata sınırına sayılmaz ve onu hiçbir zaman sıfırlamaz. Bir uç noktayı hata ayıklamak onu kapatamaz.
📜 Son denemeler
Son denemeler, o uç nokta için son 20 denemeyi gösterir: ne zaman, hangi olay, kaçıncı deneme, durum kodu veya hata ve ne kadar sürdüğü. Hatalar, sunucunuzun yanıtladığı şeyden kısa bir alıntı taşır; bu da genellikle hayır diyenin kodunuz değil bir ters vekil sunucu olduğunu öğrenmenin en hızlı yoludur.
Denemeler 30 gün saklanır ve her gece temizlenir. Bu bir kayıt değil, hata ayıklama artığıdır: denetim kaydının kendi, çok daha uzun bir saklama süresi vardır.
🛡️ Göndermeyi reddettiğimiz yerler
Bir uç nokta URL'si herkese açık internete işaret etmelidir. Bir geri döngü adresine, özel bir aralığa, bağlantı-yerel bir adrese veya bir bulut meta verisi adresine çözülen bir URL reddedilir: onu kaydederken ve her bir gönderimden önce yeniden.
Zamanla önemli olan ikinci kontroldür. Yazıldığı gün herkese açık bir yere işaret eden bir ad, bir ay sonra 127.0.0.1'e işaret edebilir ve bir webhook var olduğu sürece tetiklenir. Bir ret, uç nokta için bir hata sayılır ve yeniden denenmez: çözümleyiciye aynı soruyu üç kez daha sormak hiçbir şeyi değiştirmez.
https uç noktasını tercih edin. İmza gövdeyi kimin gönderdiğini kanıtlar, gizlemez: düz http üzerinden etkinliğiniz açık gider.
💬 Doğrudan bir Discord veya Slack kanalına
Uç nokta olarak bir Discord webhook URL'si (https://discord.com/api/webhooks/…) yapıştırın; panel JSON zarfı yerine bir Discord mesajı gönderir: girdi başına bir embed, başlığı açıklama olan; olay, kategori, eylemi yapan, takım, sunucu, konu ve varsa değişiklikler kısa bir fark olarak. Zaman damgası girdinin zaman damgasıdır ve alt bilgi teslimat kimliğini taşır.
Embed, yukarıda anlatılan aynı zarftan oluşturulur, bu yüzden iki kuralını devralır: IP adresi yok, kimlik bilgileri maskeli. Bahsetmeler Discord tarafında kapatılmıştır; bu yüzden bir girdideki @everyone adlı bir kanal veya rol metin olarak gönderilir ve kimseyi etiketlemez. X-YAWBDB-* başlıkları ve imza yine gönderilir; Discord bunları yalnızca yok sayar.
Discord, kabul ettiği bir mesaja 204 No Content yanıtı verir; Son denemeler'deki yeşil bir satır da bunu gösterir.
Aynısı bir Slack gelen webhook URL'si (https://hooks.slack.com/services/…) için de geçerlidir: panel girdi başına bir Slack mesajı gönderir; açıklama kalın, ardından olgu başına bir satır, değişiklikler bir kod bloğunda ve altında zaman damgası ile teslimat kimliği. Aynı zarftan oluşturulur, bu yüzden aynı iki kural geçerlidir ve Slack'in kendi komutları için ayırdığı üç karakter (<, >, &) kaçırılır; böylece bir üyenin yazdığı bir ad asla @channel veya @here'e dönüşemez. Slack, kabul ettiği bir mesaja 200 ok yanıtı verir. Slack'in iş akışı ve tetikleyici URL'leri mesaj değildir: JSON zarfını korurlar ve bir iş akışı bunu kendi değişkenleriyle ayrıştırabilir.
💡 İnsanlar bununla ne yapıyor
- Takımınızın etkinliğini kendi Discord veya Slack kanalınıza gönderin: bir Discord veya Slack webhook URL'si olduğu gibi çalışır ya da filtrelemek ve yeniden biçimlendirmek için araya kendi alıcınızı koyun.
- Kaydı kendi günlük deponuza yansıtın ve panelin saklama süresinin ötesinde tutun.
- Mesai dışında bir moderasyon eylemi gerçekleştiğinde birini arayın.
- Bir özellik ayarı değiştiğinde bir derleme, bir eşitleme veya bir yedekleme tetikleyin.
🔗 Ayrıca bakın
- Denetim Günlüğü - kaydın neleri tuttuğu ve bilerek neleri tutmadığı
- Takım rolleri ve izinleri - sayfayı kimlerin açabileceği
- Sunucu Günlükleri - Discord tarafındaki günlük; farklı bir soruyu yanıtlayan farklı bir özellik