Webhook'lar
Webhook’lar, LabelGrid hesabınızda bir olay gerçekleştiğinde gerçek zamanlı bildirimler almanızı sağlar. İş akışlarını otomatikleştirmek ve harici sistemlerle entegre olmak için webhook’ları kullanın.
Geliştiriciler için: Webhook’ları API üzerinden programatik olarak da yönetebilirsiniz. Uç noktalar ve örnekler için LabelGrid API Belgeleri sayfasına bakın.
Webhook’lar Nasıl Çalışır
Section titled “Webhook’lar Nasıl Çalışır”- Bir webhook yapılandırırsınız - Bir URL ve hangi olayların dinleneceğini belirtirsiniz
- Bir olay gerçekleşir - Örneğin bir yayın bir mağazaya teslim edilir
- LabelGrid bir POST isteği gönderir - Sunucunuz olay verilerini alır
- Sisteminiz bunu işler - Olaya göre iş akışlarını otomatikleştirin
Webhook’lara Erişim
Section titled “Webhook’lara Erişim”- Sağ üst köşedeki profil simgenize tıklayın
- Açılır menüden Webhooks seçeneğini seçin
Webhook Oluşturma
Section titled “Webhook Oluşturma”- Create Webhook düğmesine tıklayın
- Bu webhook’u tanımlamak için bir Name girin
- Bildirimleri almak istediğiniz URL’yi girin
- Bu webhook’u hangi Events öğelerinin tetikleyeceğini seçin
- Create düğmesine tıklayın
Webhook Gizli Anahtarı
Section titled “Webhook Gizli Anahtarı”Bir webhook oluşturduğunuzda bir gizli anahtar (secret key) alırsınız. Gelen isteklerin gerçekten LabelGrid’den geldiğini doğrulamak için bunu kullanın:
- Gizli anahtarı güvenli bir şekilde saklayın
- Gelen isteklerdeki imzayı doğrulayın
- Anahtar ele geçirilirse yeniden oluşturun
Kullanılabilir Olaylar
Section titled “Kullanılabilir Olaylar”Webhook’unuzu bu olayları dinleyecek şekilde yapılandırın. Olay Tanımlayıcısı (Event Identifier), yükün event özelliğinde ve X-Webhook-Event başlığında göreceğiniz değerdir:
| Olay Tanımlayıcısı | Açıklama |
|---|---|
delivery.completed | Bir yayın bir kanala başarıyla teslim edildiğinde tetiklenir |
delivery.failed | Bir kanala teslimat başarısız olduğunda tetiklenir |
takedown.completed | Bir kaldırma (takedown) talebi tamamlandığında tetiklenir |
release.review.status_changed | Bir yayının inceleme durumu değiştiğinde tetiklenir |
release.preflight.report_ready | Bekletmedeki bir yayının Preflight QC raporu alınmaya hazır olduğunda tetiklenir |
stream_radar.flag_created | Bir Stream Radar işareti oluşturulduğunda ya da çözülmüş bir işaret yeni bir tespitle yeniden açıldığında tetiklenir |
stream_radar.flag_resolved | Tespitler durduğu için bir Stream Radar işareti çözüldüğünde tetiklenir |
release.distributed | Bir yayın dağıtıldığında tetiklenir |
payment.statement_ready | Bir ödeme hesap özeti görüntülenmeye hazır olduğunda tetiklenir |
transcode.completed | Bir parçanın ses transkodlaması başarıyla tamamlandığında tetiklenir |
transcode.failed | Bir parçanın transkodlaması başarısız olduğunda veya eksik bittiğinde tetiklenir |
distribution.outlet.status_changed | Her kanal bazında dağıtım durumu geçişinde tetiklenir |
Tek bir webhook için birden fazla olay seçebilir ya da farklı olay türleri için ayrı webhook’lar oluşturabilirsiniz.
Bu listeyi programatik olarak da okuyabilirsiniz: GET /api/public/webhooklar/event-types, her olayı, payload anahtarlarını ve türlerini açıklayan bir data şemasıyla birlikte döndürür; böylece katı şema kullanan tüketiciler gelen doğrulamalarını önceden genişletebilir.
Webhook’ları Yönetme
Section titled “Webhook’ları Yönetme”Webhook’larınızı Görüntüleme
Section titled “Webhook’larınızı Görüntüleme”Webhook listesi şunları gösterir:
| Sütun | Açıklama |
|---|---|
| Name | Atadığınız webhook adı |
| URL | Bildirimlerin gönderildiği adres |
| Events | Yapılandırılan olay sayısı |
| Status | Aktif veya Pasif |
| Success / Fail | Başarılı ve başarısız teslimat sayısı |
| Last Triggered | Webhook’un en son ne zaman çağrıldığı |
Bir Webhook’u Düzenleme
Section titled “Bir Webhook’u Düzenleme”- Webhook satırındaki Edit işlemine tıklayın
- Adı, URL’yi veya olayları değiştirin
- Save düğmesine tıklayın
Etkinleştirme / Devre Dışı Bırakma
Section titled “Etkinleştirme / Devre Dışı Bırakma”Bir webhook’u silmeden aktif durumunu değiştirin:
- Active - Webhook bildirimleri alır
- Inactive - Webhook duraklatılmıştır, bildirim gönderilmez
Bir Webhook’u Silme
Section titled “Bir Webhook’u Silme”- Webhook satırındaki Delete işlemine tıklayın
- Silme işlemini onaylayın
Webhook’ları Test Etme
Section titled “Webhook’ları Test Etme”Production ortamında bir webhook’a güvenmeden önce test edin:
- Webhook’unuzdaki Test işlemine tıklayın
- LabelGrid, URL’nize bir test yükü gönderir
- Uç noktanızın bunu doğru şekilde alıp işlediğini kontrol edin
Webhook Günlüklerini Görüntüleme
Section titled “Webhook Günlüklerini Görüntüleme”Webhook etkinliğini izleyin ve sorunları giderin:
- Bir webhook’taki View Logs işlemine tıklayın
- Tüm webhook teslimatlarının geçmişini görün
Günlük Ayrıntıları
Section titled “Günlük Ayrıntıları”Her günlük kaydı şunları gösterir:
| Alan | Açıklama |
|---|---|
| Event Type | Bu teslimatı hangi olayın tetiklediği |
| Response Status | Sunucunuzdan dönen HTTP durum kodu |
| Duration | İsteğin ne kadar sürdüğü |
| Attempt | Yeniden deneme sayısı |
| Timestamp | Teslimatın ne zaman gerçekleştiği |
Webhook Yük Biçimi
Section titled “Webhook Yük Biçimi”Bir olay gerçekleştiğinde LabelGrid, URL’nize bir JSON yükü içeren bir POST isteği gönderir:
{ "event": "delivery.completed", "timestamp": "2026-05-05T10:00:00+00:00", "webhook_id": "123", "data": { // Olaya özgü veriler }}timestamp alanı ISO 8601 biçimini kullanır. webhook_id, yapılandırdığınız webhook’un ID’sidir (X-Webhook-Id başlığıyla eşleşir).
Olay Yükleri
Section titled “Olay Yükleri”data nesnesinin yapısı, event türüne göre değişir. Aşağıdaki tüm alan türleri, yükte serileştirildiği haliyle JSON türleridir.
delivery.completed
Section titled “delivery.completed”Bir yayın teslimatı kesin başarı durumuna ulaştığında, kanal başına bir kez tetiklenir.
{ "event": "delivery.completed", "timestamp": "2026-05-18T10:00:00+00:00", "webhook_id": "123", "data": { "distro_queue_id": 456, "release_id": 789, "label_id": 321, "release_cat": "ABC123", "outlet_id": 12, "outlet_name": "Spotify", "status": "complete" }}| Alan | Tür | Açıklama |
|---|---|---|
distro_queue_id | integer | Bu teslimat denemesi için dahili kuyruk ID’si |
release_id | integer | Teslim edilen yayın |
label_id | integer | Yayının sahibi olan etiket; böylece olayı ek bir arama yapmadan yönlendirebilirsiniz |
release_cat | string | null | Yayın katalog referansınız |
outlet_id | integer | null | Hedef kanalın ID’si |
outlet_name | string | null | Okunabilir kanal adı (ör. "Spotify") |
status | string | Bu olay için her zaman "complete" |
delivery.failed
Section titled “delivery.failed”Bir yayın teslimatı kesin başarısızlık durumuna ulaştığında, kanal başına bir kez tetiklenir. delivery.completed ile aynı yük, artı bir message alanı.
{ "event": "delivery.failed", "timestamp": "2026-05-18T10:00:00+00:00", "webhook_id": "123", "data": { "distro_queue_id": 456, "release_id": 789, "label_id": 321, "release_cat": "ABC123", "outlet_id": 12, "outlet_name": "Spotify", "status": "error", "message": "Outlet rejected the delivery: missing ISRC." }}| Alan | Tür | Açıklama |
|---|---|---|
status | string | error, fault, rejected, batch_exception değerlerinden biri |
message | string | null | Kanaldan veya dağıtım süreç hattından gelen başarısızlık nedeni |
takedown.completed
Section titled “takedown.completed”Bir kaldırma talebi başarılı olduğunda, kanal başına bir kez tetiklenir. delivery.completed ile aynı yapı, artı bir takedown: true bayrağı.
{ "event": "takedown.completed", "timestamp": "2026-05-18T10:00:00+00:00", "webhook_id": "123", "data": { "distro_queue_id": 456, "release_id": 789, "label_id": 321, "release_cat": "ABC123", "outlet_id": 12, "outlet_name": "Spotify", "status": "complete", "takedown": true }}release.distributed
Section titled “release.distributed”Yayın distributed teslimat durumuna geçtiğinde, yayın başına bir kez tetiklenir. Yalnızca distributed durumuna geçişte tetiklenir; yayın zaten dağıtılmışken sonraki kayıt işlemlerinde tetiklenmez.
{ "event": "release.distributed", "timestamp": "2026-05-18T10:00:00+00:00", "webhook_id": "123", "data": { "release_id": 789, "label_id": 321, "release_cat": "ABC123", "release_title": "Summer EP", "delivery_status": "distributed" }}release.review.status_changed
Section titled “release.review.status_changed”Bir yayın inceleme durumları arasında her geçiş yaptığında tetiklenir.
{ "event": "release.review.status_changed", "timestamp": "2026-05-18T10:00:00+00:00", "webhook_id": "123", "data": { "release_id": 789, "label_id": 321, "release_cat": "ABC123", "release_title": "Summer EP", "previous_status": "to_review", "new_status": "approved" }}| Alan | Tür | Açıklama |
|---|---|---|
previous_status | string | Önceki durum. draft, to_review, approved, rejected, require_changes, audit değerlerinden biri |
new_status | string | Yeni durum. Aynı değer kümesi |
review_issues | array (isteğe bağlı) | Yalnızca require_changes ve rejected geçişlerinde bulunur: dikkatinizi gerektiren sorunlar. Anahtar diğer tüm geçişlerde atlanır, bu yüzden her zaman mevcutmuş gibi davranmayın |
release.preflight.report_ready
Section titled “release.preflight.report_ready”İnceleme öncesi bekletmedeki bir yayının Preflight QC kalite raporu alınmaya hazır olduğunda tetiklenir. Hesabınızda Preflight QC eklentisini gerektirir.
{ "event": "release.preflight.report_ready", "timestamp": "2026-07-07T10:00:00+00:00", "webhook_id": "123", "data": { "release_id": 789, "label_id": 321, "release_cat": "ABC123", "release_title": "Summer EP", "generated_at": "2026-07-07T09:58:12+00:00", "profile": { "name": "quality_report", "version": 2 }, "counts": { "blocking": 1, "informational": 2, "requires_feedback": 1 } }}| Alan | Tür | Açıklama |
|---|---|---|
release_id | integer | Raporun ait olduğu yayın |
label_id | integer | Yayının sahibi olan etiket |
release_cat | string | null | Yayın katalog referansınız |
release_title | string | null | Yayın başlığı |
generated_at | string | Denetimlerin ne zaman tamamlandığı (ISO 8601). Kalite raporu uç noktasının report.generated_at değeriyle eşleşir |
profile | object | Sayımların hesaplandığı kalite profili: {name, version} |
counts | object | Yalnızca toplu sayımlar: {blocking, informational, requires_feedback}. requires_feedback sayımı diğer ikisiyle örtüşür |
stream_radar.flag_created
Section titled “stream_radar.flag_created”Bir Stream Radar işareti oluşturulduğunda tetiklenir; ister yepyeni bir işaret ister daha önce çözülmüş bir işaretin yeni bir tespitle yeniden açılması olsun. Hesabınızda Stream Radar eklentisini gerektirir. transition alanı iki durumu birbirinden ayırt eder: yeni bir işaret için published, yeniden etkin olan bir işaret için reopened.
{ "event": "stream_radar.flag_created", "timestamp": "2026-07-07T10:00:00+00:00", "webhook_id": "123", "data": { "flag_id": 4501, "dsp": "spotify", "isrc": "USRC12345678", "release_id": 789, "track_id": 654, "severity": "high", "status": "active", "transition": "published", "first_detected_at": "2026-07-06T00:00:00+00:00", "last_detected_at": "2026-07-07T00:00:00+00:00", "estimated_affected_streams": 12500, "published_at": "2026-07-07T09:58:12+00:00", "resolved_at": null }}| Alan | Tür | Açıklama |
|---|---|---|
flag_id | integer | İşaretin kararlı tanımlayıcısı; Stream Radar uç noktalarındaki id ile eşleşir |
dsp | string | Desenin görüldüğü platform (ör. spotify) |
isrc | string | Söz konusu kaydın ISRC’si |
release_id | integer | Kaydın ait olduğu yayın |
track_id | integer | null | ISRC, parçalarınızdan birine kesin olarak eşleştiğinde ilgili parça |
severity | string | low, medium veya high |
status | string | Bu olay için active |
transition | string | Yeni bir işaret için published, çözülmüş bir işaret yeniden etkin olduğunda reopened |
first_detected_at | string | null | Desenin bu parça ve platform için ilk görüldüğü an (ISO 8601) |
last_detected_at | string | null | En son tespit (ISO 8601) |
estimated_affected_streams | integer | null | Kaç dinlenmenin söz konusu olduğuna dair bir tahmin |
published_at | string | İşaretin size ilk bildirildiği an (ISO 8601) |
resolved_at | string | null | İşaret etkinken null |
stream_radar.flag_resolved
Section titled “stream_radar.flag_resolved”Tespitler durduğu için bir Stream Radar işareti çözüldüğünde tetiklenir. Stream Radar eklentisini gerektirir. stream_radar.flag_created ile aynı alanlar (transition olmadan); status değeri resolved olarak ayarlanır ve resolved_at doldurulur.
{ "event": "stream_radar.flag_resolved", "timestamp": "2026-07-14T10:00:00+00:00", "webhook_id": "123", "data": { "flag_id": 4501, "dsp": "spotify", "isrc": "USRC12345678", "release_id": 789, "track_id": 654, "severity": "high", "status": "resolved", "first_detected_at": "2026-07-06T00:00:00+00:00", "last_detected_at": "2026-07-12T00:00:00+00:00", "estimated_affected_streams": 18700, "published_at": "2026-07-07T09:58:12+00:00", "resolved_at": "2026-07-14T09:55:03+00:00" }}payment.statement_ready
Section titled “payment.statement_ready”Bir ödeme hesap özeti oluşturulup görüntülenmeye hazır olduğunda tetiklenir.
{ "event": "payment.statement_ready", "timestamp": "2026-05-18T10:00:00+00:00", "webhook_id": "123", "data": { "payment_request_id": 1024, "invoice_number": "INV-2026-001", "period": "2026-04-30", "amount": 1234.56, "total_due_usd": 1234.56, "currency": "USD" }}| Alan | Tür | Açıklama |
|---|---|---|
payment_request_id | integer | Dahili ödeme talebi ID’si |
invoice_number | string | Hesap özetine ait fatura referansı |
period | string | null | Dönem sonu tarihi (ISO 8601 tarihi, YYYY-MM-DD) |
amount | number | currency cinsinden hesap özeti tutarı |
total_due_usd | number | USD’ye çevrilmiş hesap özeti toplamı |
currency | string | ISO 4217 para birimi kodu (varsayılan USD) |
transcode.completed ve transcode.failed
Section titled “transcode.completed ve transcode.failed”Bir parçanın ses transkodlaması tamamlandığında tetiklenir. transcode.completed başarı durumunda tetiklenir; transcode.failed, transkodlama başarısız olduğunda veya eksik bittiğinde tetiklenir. İkisi de aynı payload yapısını paylaşır.
{ "event": "transcode.completed", "timestamp": "2026-07-07T10:00:00+00:00", "webhook_id": "123", "data": { "release_id": 789, "label_id": 321, "track_id": 654, "transcoder_queue_id": 987, "status": "complete", "status_message": "transcode_complete", "files": [ { "asset_type_id": 2, "status": "complete" } ] }}| Alan | Tür | Açıklama |
|---|---|---|
release_id | integer | Parçanın ait olduğu yayın |
label_id | integer | Yayının sahibi olan etiket |
track_id | integer | Transkodlanan parça |
transcoder_queue_id | integer | Dahili transkodlama kuyruğu ID’si |
status | string | Ham kuyruk durumu: complete, error veya incomplete |
status_message | string | Güvenli, numaralandırılmış neden kodu: transcode_complete, transcode_error veya transcode_incomplete |
files | array | Parça için dosya bazında ayrıntı: transkodlanan her dosya için {asset_type_id, status} |
distribution.outlet.status_changed
Section titled “distribution.outlet.status_changed”Yalnızca delivery.completed, delivery.failed ve takedown.completed ile kapsanan son durumlarda değil, her kanal bazında dağıtım durumu geçişinde tetiklenir (örneğin scheduled → transcoding → batched → complete). Bu olay, tasarımı gereği ayrıntılıdır: yalnızca tam kanal bazında ilerlemeyi istiyorsanız abone olun.
{ "event": "distribution.outlet.status_changed", "timestamp": "2026-07-07T10:00:00+00:00", "webhook_id": "123", "data": { "distro_queue_id": 456, "release_id": 789, "label_id": 321, "release_cat": "ABC123", "outlet_id": 12, "outlet_name": "Spotify", "previous_status": "transcoding", "status": "batched" }}| Alan | Tür | Açıklama |
|---|---|---|
distro_queue_id | integer | Bu teslimat için dahili kuyruk ID’si |
release_id | integer | Dağıtılmakta olan yayın |
label_id | integer | Yayının sahibi olan etiket |
release_cat | string | null | Yayın katalog referansınız |
outlet_id | integer | null | Hedef kanalın ID’si |
outlet_name | string | null | Okunabilir kanal adı |
previous_status | string | null | Önceki durum; satırda tanınan bir önceki durum yoksa null |
status | string | Yeni durum |
Webhook İmzalarını Doğrulama
Section titled “Webhook İmzalarını Doğrulama”Her webhook teslimatı, gerçekten LabelGrid’den geldiğini doğrulayabilmeniz için imzalanır. Olayı işlemeden önce imzayı her zaman doğrulayın.
İstek Başlıkları
Section titled “İstek Başlıkları”Her webhook POST isteği şu başlıkları içerir:
| Başlık | Açıklama |
|---|---|
X-Webhook-Signature | Ham istek gövdesinin HMAC-SHA256 değeri, küçük harfli onaltılık, algoritma öneki olmadan |
X-Webhook-Timestamp | Gövdedeki timestamp özelliğinin kolaylık olsun diye eklenen bir kopyası. İmza kapsamında değildir — bir teslimatın güncel olup olmadığına karar vermek için bunu asla kullanmayın. |
X-Webhook-Event | Olay tanımlayıcısı (ör. delivery.completed) |
X-Webhook-Id | Teslimatı alan webhook yapılandırmasının ID’si (teslimat başına bir ID değildir) |
User-Agent | LabelGrid-Webhooks/1.0 |
Content-Type | application/json |
Algoritma
Section titled “Algoritma”- Algoritma: HMAC-SHA256
- Kodlama: Küçük harfli onaltılık (hexadecimal)
- Önek: Yok. Değer yalnızca onaltılık özettir,
sha256=...değildir - İmzalanan içerik: Ham JSON istek gövdesinin tamamı — ve başka hiçbir şey. Hiçbir başlık imzalanmaz.
Gövde kendi timestamp özelliğini taşır, dolayısıyla o değer imzayla korunur. X-Webhook-Timestamp başlığı ise yalnızca bu değerin kolaylık olsun diye gönderilen bir kopyasıdır; bir teslimatı ele geçiren saldırgan, imzayı geçersiz kılmadan bu başlığı dilediği gibi değiştirebilir. Bu nedenle güncellik kontrolleri timestamp değerini ayrıştırılmış gövdeden okumalıdır, asla başlıktan değil.
Doğrulama Adımları
Section titled “Doğrulama Adımları”- JSON ayrıştırma veya herhangi bir dönüşüm yapmadan önce ham istek gövdesini okuyun. Ayrıştırılmış JSON’u yeniden serileştirmek farklı baytlar üretebilir ve imzayı bozabilir.
HMAC-SHA256(raw_body, your_webhook_secret)değerini hesaplayın ve küçük harfli onaltılık özeti alın.- Sabit zamanlı (constant-time) bir karşılaştırma kullanarak
X-Webhook-Signatureile karşılaştırın. Eşleşmiyorsa burada durun. - Gövdeyi ancak şimdi ayrıştırın ve
timestampözelliği yineleme (replay) tolerans pencerenizden eskiyse isteği reddedin; 5 dakika öneririz. Bu değer imzalandığı için, saldırgan onu tazeleyip ele geçirdiği bir teslimatı güncel gösteremez.
Her yeniden deneme yeni bir timestamp ile baştan imzalanır; bu yüzden 5 dakikalık bir pencere, geri çekilme çizelgesinin ne kadar ilerisinde gelirse gelsin meşru bir yeniden denemeyi asla reddetmez.
PHP Örneği
Section titled “PHP Örneği”$rawBody = file_get_contents('php://input');$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $rawBody, $webhookSecret);
if (! hash_equals($expected, $signature)) { http_response_code(401); exit('Invalid signature');}
// Baytların gerçekliği kanıtlandıktan sonra ayrıştırın.$payload = json_decode($rawBody, true);
// Güncellik, gövdedeki İMZALANMIŞ zaman damgasından gelir;// asla X-Webhook-Timestamp başlığından değil.if (! isset($payload['timestamp']) || abs(time() - strtotime($payload['timestamp'])) > 300) { http_response_code(401); exit('Stale delivery');}
// ... olayı işleyin (aşağıdaki "Tekrarlanan Teslimatları Ele Alma" bölümüne bakın)http_response_code(200);Node.js Örneği
Section titled “Node.js Örneği”const crypto = require('crypto');
// Express: ham gövdeyi herhangi bir JSON middleware'inden ÖNCE yakalayınapp.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { const rawBody = req.body; // Buffer const signature = req.header('X-Webhook-Signature') || '';
const expected = crypto .createHmac('sha256', webhookSecret) .update(rawBody) .digest('hex');
const sigBuf = Buffer.from(signature, 'hex'); const expBuf = Buffer.from(expected, 'hex');
if (sigBuf.length !== expBuf.length || !crypto.timingSafeEqual(sigBuf, expBuf)) { return res.status(401).send('Invalid signature'); }
// Baytların gerçekliği kanıtlandıktan sonra ayrıştırın. const payload = JSON.parse(rawBody.toString('utf8'));
// Güncellik, gövdedeki İMZALANMIŞ zaman damgasından gelir; // asla X-Webhook-Timestamp başlığından değil. const sentAt = new Date(payload.timestamp).getTime();
if (Number.isNaN(sentAt) || Math.abs(Date.now() - sentAt) > 5 * 60 * 1000) { return res.status(401).send('Stale delivery'); }
// ... olayı işleyin (aşağıdaki "Tekrarlanan Teslimatları Ele Alma" bölümüne bakın) res.sendStatus(200);});Python Örneği
Section titled “Python Örneği”import hmac, hashlib, jsonfrom datetime import datetime, timezone
raw_body = request.get_data() # Flask: bayt dizisi, JSON ayrıştırmasından öncesignature = request.headers.get('X-Webhook-Signature', '')
expected = hmac.new( webhook_secret.encode('utf-8'), raw_body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, signature): return ('Invalid signature', 401)
payload = json.loads(raw_body) # baytlar doğrulandıktan sonra ayrıştırın
delivery_time = datetime.fromisoformat(payload['timestamp']) # İMZALANMIŞ değer, asla başlık değilif abs((datetime.now(timezone.utc) - delivery_time).total_seconds()) > 300: return ('Stale delivery', 401)
return ('', 200) # olayı işleyin, sonra onay yanıtı verinSık Yapılan Hatalar
Section titled “Sık Yapılan Hatalar”- Güncelliği
X-Webhook-Timestampbaşlığına göre kontrol etmek. Bu başlık imzalanmaz. Bir teslimatı ele geçiren herkes, aynı gövde ve imzayı taze bir başlık değeriyle sonsuza dek yeniden oynatabilir ve başlığa dayalı bir kontrolü her seferinde geçer. Bunun yerinetimestampdeğerini ayrıştırılmış gövdeden okuyun; imzalanan değer odur. - Karma (hash) almadan önce gövdeyi yeniden serileştirmek. JSON’u otomatik ayrıştıran çerçeveler (Express
express.json(), Laravel’in varsayılan istek gövdesi) orijinal baytları kaybeder. Önce ham gövdeyi yakalayın. - Sabit zamanlı olmayan bir karşılaştırma kullanmak (
==,===). Zamanlama saldırılarına açıktır; her zamanhash_equals(PHP),crypto.timingSafeEqual(Node),hmac.compare_digest(Python) ya da dilinizdeki karşılığını kullanın. sha256=öneki beklemek. Başlık değeri, öneksiz, yalnızca onaltılık özettir.- Güncellik kontrolünü atlamak. Bu kontrol olmadan, ele geçirilen bir teslimat uç noktanıza karşı süresiz olarak yeniden oynatılabilir.
X-Webhook-Iddeğerine teslimat kimliği gibi güvenmek. Bu değer tek tek teslimatı değil, webhook yapılandırmasını tanımlar ve ayrıca imzalanmaz.
Tekrarlanan Teslimatları Ele Alma
Section titled “Tekrarlanan Teslimatları Ele Alma”Webhook teslimatı en az bir kez ilkesiyle çalışır: uç noktanızın gerçekten işlediği bir teslimat, 2xx yanıtınız kaybolduysa veya 10 saniyelik zaman aşımından sonra ulaştıysa yeniden gelebilir; LabelGrid o teslimatı yeniden dener. İmza doğrulaması bir isteğin gerçek olduğunu kanıtlar; daha önce işlemediğiniz bir istek olduğunu kanıtlamaz.
Teslimatlar teslimat başına benzersiz bir ID taşımaz; bu yüzden kendi idempotency anahtarınızı imzalanmış yükten türetin. Olay türü ile data içindeki tanımlayıcılar genellikle yeterlidir — örneğin delivery.completed ile distro_queue_id ya da transcode.completed ile track_id. Bir olayı işlerken anahtarı kaydedin ve daha önce kaydettiğiniz her şeyi yok sayın.
Bu anahtar olarak imzayı veya timestamp değerini kullanmayın. Her deneme gönderildiği anda yeniden imzalanır; dolayısıyla zaten işlediğiniz bir olayın yeniden denemesi farklı bir timestamp ve farklı bir imzayla gelir — anahtar, olayın kendi tanımlayıcılarından gelmelidir.
Bunu yukarıdaki güncellik kontrolüyle birleştirin: güncellik, ele geçirilen bir teslimatın ne kadar süre yeniden oynatılabilir kalacağını sınırlar; idempotency ise tekrarın bir yeniden denemeden mi yoksa pencere içindeki bir saldırgandan mı geldiğine bakmaksızın zararsız olmasını sağlar.
Sınırlar ve Güvenilirlik
Section titled “Sınırlar ve Güvenilirlik”İstek Sınırları
Section titled “İstek Sınırları”| Sınır | Değer |
|---|---|
| İstek zaman aşımı | 10 saniye |
| Azami yük boyutu | 64 KB |
| Kullanıcı başına azami webhook sayısı | 10 |
Uç noktanız 10 saniye içinde yanıt vermezse, teslimat başarısız sayılır ve yeniden denenir.
Yeniden Deneme Çizelgesi
Section titled “Yeniden Deneme Çizelgesi”Uç noktanız 2xx dışında bir durum döndürürse veya zaman aşımına uğrarsa, LabelGrid üstel geri çekilme (exponential backoff) ile yeniden dener:
| Deneme | Yeniden denemeden önceki bekleme |
|---|---|
| 1 → 2 | 30 saniye |
| 2 → 3 | 1 dakika |
| 3 → 4 | 2 dakika |
| 4 → 5 | 4 dakika |
| 5 → 6 | 8 dakika |
| 6 → 7 | 16 dakika |
| 7 → 8 | 32 dakika |
| 8 → 9 | 64 dakika |
| 9 → 10 | 128 dakika |
Her aralık 0-30 saniyelik bir oynama (jitter) içerir. 10 denemeden (toplam yaklaşık 4,5 saat) sonra teslimat kalıcı olarak başarısız kaydedilir ve bir daha denenmez.
Otomatik Devre Dışı Bırakma
Section titled “Otomatik Devre Dışı Bırakma”Bir webhook’un uç noktası tekrar tekrar başarısız olursa — aralarında tek bir başarılı teslimat olmadan art arda gelen başarısız teslimatlar — LabelGrid, olayları açıkça alamayan bir uç noktayı yeniden denemeyi bırakmak için webhook’u otomatik olarak devre dışı bırakır. Başarısızlık sayacı her başarılı teslimatta sıfırlanır; bu nedenle ara sıra yaşanan bir aksaklık bir webhook’u asla devre dışı bırakmaz, yalnızca sürekli ve kesintisiz başarısızlık bunu yapar.
Bir webhook bu şekilde devre dışı bırakıldığında, sahibine bir e-posta gönderilir. E-posta; webhook’un adını, uç noktasının URL’sini ve devre dışı bırakmayı tetikleyen hata türünü belirtir — örneğin bir bağlantı zaman aşımı ya da tekrarlanan HTTP hataları.
Yeniden etkinleştirme self servistir: uç noktanızı düzeltin, ardından webhook’u Profil → Webhooks altından yeniden açın. Devre dışı bırakılan bir webhook’u yeniden etkinleştirmek başarısızlık sayacını sıfırlar. Webhook listesi her webhook’un aktif durumunu ve güncel başarısızlık sayısını gösterir; böylece sorunlu bir uç noktayı bir bakışta fark edebilirsiniz.
Güvenilirlik için En İyi Uygulamalar
Section titled “Güvenilirlik için En İyi Uygulamalar”- Hızlı bir şekilde (10 saniye içinde) bir 2xx yanıtı döndürün
- Yanıtı verdikten sonra verileri eşzamansız olarak işleyin
- Her istekte imzayı doğrulayın (bkz. Webhook İmzalarını Doğrulama)
- İşleyicinizi idempotent hale getirin — teslimat en az bir kez ilkesiyle çalışır (bkz. Tekrarlanan Teslimatları Ele Alma)
- Webhook listesinde başarısızlık sayınızı izleyin
- Kaçırılan olayları araştırırken teslimat günlüklerini kontrol edin
Kullanım Senaryoları
Section titled “Kullanım Senaryoları”Otomatik Bildirimler
Section titled “Otomatik Bildirimler”- Yayınlar yayına girdiğinde Slack mesajları gönderin
- Teslimatlar başarısız olduğunda ekibinize e-posta gönderin
- Dahili panoları güncelleyin
İş Akışı Otomasyonu
Section titled “İş Akışı Otomasyonu”- Yayınlar dağıtıldığında pazarlama kampanyalarını tetikleyin
- Yeni içerik hazır olduğunda web sitenizi güncelleyin
- Durumu harici proje yönetimi araçlarıyla eşitleyin
İzleme ve Uyarı
Section titled “İzleme ve Uyarı”- Teslimat hataları için anında uyarı alın
- Dağıtım ilerlemesini gerçek zamanlı takip edin
- İnceleme durumu değişikliklerini izleyin
Sorun Giderme
Section titled “Sorun Giderme”Webhook Olayları Almıyor
Section titled “Webhook Olayları Almıyor”- Durumu kontrol edin - Webhook aktif mi?
- URL’yi doğrulayın - Uç noktaya internetten erişilebiliyor mu?
- Olayları kontrol edin - Doğru olaylar seçili mi?
- Günlükleri inceleyin - Kayıtlı bir hata var mı?
Yüksek Başarısızlık Sayısı
Section titled “Yüksek Başarısızlık Sayısı”- Uç noktanızı kontrol edin - 200 OK döndürüyor mu?
- Yanıt süresini kontrol edin - Zaman aşımı içinde yanıt veriyor mu?
- Hata mesajlarını inceleyin - Sorun ne?
- Manuel test edin - Bir test webhook’u gönderin
Gizli Anahtarı Yeniden Oluşturma
Section titled “Gizli Anahtarı Yeniden Oluşturma”Webhook gizli anahtarınız ele geçirilirse:
- Webhook ayarlarında Regenerate Secret düğmesine tıklayın
- Uygulamanızı yeni gizli anahtarla güncelleyin
- Eski gizli anahtar anında çalışmayı durdurur
Yardıma mı ihtiyacınız var?
Section titled “Yardıma mı ihtiyacınız var?”Webhook’larla ilgili sorularınız varsa destek ekibimizle iletişime geçin.
LabelGrid’i henüz kullanmıyor musunuz?
Az önce okuduklarınızın tamamı platformumuzda mevcut.
LabelGrid’in neler yapabileceğini keşfedin →