İçeriğe geç
Destek

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.

  1. Bir webhook yapılandırırsınız - Bir URL ve hangi olayların dinleneceğini belirtirsiniz
  2. Bir olay gerçekleşir - Örneğin bir yayın bir mağazaya teslim edilir
  3. LabelGrid bir POST isteği gönderir - Sunucunuz olay verilerini alır
  4. Sisteminiz bunu işler - Olaya göre iş akışlarını otomatikleştirin

  1. Sağ üst köşedeki profil simgenize tıklayın
  2. Açılır menüden Webhooks seçeneğini seçin

  1. Create Webhook düğmesine tıklayın
  2. Bu webhook’u tanımlamak için bir Name girin
  3. Bildirimleri almak istediğiniz URL’yi girin
  4. Bu webhook’u hangi Events öğelerinin tetikleyeceğini seçin
  5. Create düğmesine tıklayın

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

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.completedBir yayın bir kanala başarıyla teslim edildiğinde tetiklenir
delivery.failedBir kanala teslimat başarısız olduğunda tetiklenir
takedown.completedBir kaldırma (takedown) talebi tamamlandığında tetiklenir
release.review.status_changedBir yayının inceleme durumu değiştiğinde tetiklenir
release.distributedBir yayın dağıtıldığında tetiklenir
payment.statement_readyBir ödeme hesap özeti görüntülenmeye hazır olduğunda tetiklenir

Tek bir webhook için birden fazla olay seçebilir ya da farklı olay türleri için ayrı webhook’lar oluşturabilirsiniz.


Webhook listesi şunları gösterir:

SütunAçıklama
NameAtadığınız webhook adı
URLBildirimlerin gönderildiği adres
EventsYapılandırılan olay sayısı
StatusAktif veya Pasif
Success / FailBaşarılı ve başarısız teslimat sayısı
Last TriggeredWebhook’un en son ne zaman çağrıldığı
  1. Webhook satırındaki Edit işlemine tıklayın
  2. Adı, URL’yi veya olayları değiştirin
  3. Save düğmesine tıklayın

Bir webhook’u silmeden aktif durumunu değiştirin:

  • Active - Webhook bildirimleri alır
  • Inactive - Webhook duraklatılmıştır, bildirim gönderilmez
  1. Webhook satırındaki Delete işlemine tıklayın
  2. Silme işlemini onaylayın

Production ortamında bir webhook’a güvenmeden önce test edin:

  1. Webhook’unuzdaki Test işlemine tıklayın
  2. LabelGrid, URL’nize bir test yükü gönderir
  3. Uç noktanızın bunu doğru şekilde alıp işlediğini kontrol edin

Webhook etkinliğini izleyin ve sorunları giderin:

  1. Bir webhook’taki View Logs işlemine tıklayın
  2. Tüm webhook teslimatlarının geçmişini görün

Her günlük kaydı şunları gösterir:

AlanAçıklama
Event TypeBu teslimatı hangi olayın tetiklediği
Response StatusSunucunuzdan dönen HTTP durum kodu
Durationİsteğin ne kadar sürdüğü
AttemptYeniden deneme sayısı
TimestampTeslimatın ne zaman gerçekleştiği

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": {
// Event-specific data
}
}

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


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.

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,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "complete"
}
}
AlanTürAçıklama
distro_queue_idintegerBu teslimat denemesi için dahili kuyruk ID’si
release_idintegerTeslim edilen yayın
release_catstring | nullYayın katalog referansınız
outlet_idintegerHedef kanalın ID’si
outlet_namestring | nullOkunabilir kanal adı (ör. "Spotify")
statusstringBu olay için her zaman "complete"

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,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "error",
"message": "Outlet rejected the delivery: missing ISRC."
}
}
AlanTürAçıklama
statusstringerror, fault, rejected, batch_exception değerlerinden biri
messagestring | nullKanaldan veya dağıtım süreç hattından gelen başarısızlık nedeni

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,
"release_cat": "ABC123",
"outlet_id": 12,
"outlet_name": "Spotify",
"status": "complete",
"takedown": true
}
}

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,
"release_cat": "ABC123",
"release_title": "Summer EP",
"delivery_status": "distributed"
}
}

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,
"release_cat": "ABC123",
"release_title": "Summer EP",
"previous_status": "to_review",
"new_status": "approved"
}
}
AlanTürAçıklama
previous_statusstringÖnceki durum. draft, to_review, approved, rejected, require_changes, audit değerlerinden biri
new_statusstringYeni durum. Aynı değer kümesi

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"
}
}
AlanTürAçıklama
payment_request_idintegerDahili ödeme talebi ID’si
invoice_numberstringHesap özetine ait fatura referansı
periodstring | nullDönem sonu tarihi (ISO 8601 tarihi, YYYY-MM-DD)
amountnumbercurrency cinsinden hesap özeti tutarı
total_due_usdnumberUSD’ye çevrilmiş hesap özeti toplamı
currencystringISO 4217 para birimi kodu (varsayılan USD)

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.

Her webhook POST isteği şu başlıkları içerir:

BaşlıkAçıklama
X-Webhook-SignatureHam istek gövdesinin HMAC-SHA256 değeri, küçük harfli onaltılık, algoritma öneki olmadan
X-Webhook-TimestampTeslimatın ISO 8601 zaman damgası (gövdedeki timestamp özelliğiyle aynı değer)
X-Webhook-EventOlay tanımlayıcısı (ör. delivery.completed)
X-Webhook-IdTeslimatı alan webhook’un ID’si
User-AgentLabelGrid-Webhooks/1.0
Content-Typeapplication/json
  • 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ı (gövdenin kendisi zaten zaman damgasını bir özellik olarak içerdiğinden, zaman damgası örtük olarak imzalanır)
  1. 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.
  2. HMAC-SHA256(raw_body, your_webhook_secret) değerini hesaplayın ve küçük harfli onaltılık özeti alın.
  3. Sabit zamanlı (constant-time) bir karşılaştırma kullanarak X-Webhook-Signature ile karşılaştırın.
  4. (Önerilir) X-Webhook-Timestamp, yineleme (replay) tolerans pencerenizden eskiyse isteği reddedin; 5 dakika öneririz.
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$expected = hash_hmac('sha256', $rawBody, $webhookSecret);
if (! hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
// Reject deliveries older than 5 minutes
if (abs(time() - strtotime($timestamp)) > 300) {
http_response_code(401);
exit('Stale delivery');
}
$payload = json_decode($rawBody, true);
// ... process the event
http_response_code(200);
const crypto = require('crypto');
// Express: capture raw body BEFORE any JSON middleware
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const rawBody = req.body; // Buffer
const signature = req.header('X-Webhook-Signature') || '';
const timestamp = req.header('X-Webhook-Timestamp') || '';
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');
}
if (Math.abs(Date.now() - new Date(timestamp).getTime()) > 5 * 60 * 1000) {
return res.status(401).send('Stale delivery');
}
const payload = JSON.parse(rawBody.toString('utf8'));
// ... process the event
res.sendStatus(200);
});
import hmac, hashlib
from datetime import datetime, timezone
raw_body = request.get_data() # Flask: bytes, before any JSON parsing
signature = request.headers.get('X-Webhook-Signature', '')
timestamp = request.headers.get('X-Webhook-Timestamp', '')
expected = hmac.new(
webhook_secret.encode('utf-8'),
raw_body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(expected, signature):
return ('Invalid signature', 401)
delivery_time = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
if abs((datetime.now(timezone.utc) - delivery_time).total_seconds()) > 300:
return ('Stale delivery', 401)
return ('', 200) # process the event, then ack
  • 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 zaman hash_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.
  • Zaman damgası kontrolünü atlamak. Bu kontrol olmadan, sızdırılan bir imza süresiz olarak yeniden oynatılabilir.

SınırDeğer
İstek zaman aşımı10 saniye
Azami yük boyutu64 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.

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:

DenemeYeniden denemeden önceki bekleme
1 → 230 saniye
2 → 31 dakika
3 → 42 dakika
4 → 54 dakika
5 → 68 dakika
6 → 716 dakika
7 → 832 dakika
8 → 964 dakika
9 → 10128 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.

Bir webhook kümülatif olarak 100 başarısız teslimat biriktirirse otomatik olarak devre dışı bırakılır. Uç noktanızı düzelttikten sonra webhook listesinden manuel olarak yeniden etkinleştirin. Devre dışı bırakılan bir webhook’u yeniden etkinleştirmek, başarısızlık sayacını sıfırlar.

  • 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)
  • 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

  • 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
  • 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
  • Teslimat hataları için anında uyarı alın
  • Dağıtım ilerlemesini gerçek zamanlı takip edin
  • İnceleme durumu değişikliklerini izleyin

  1. Durumu kontrol edin - Webhook aktif mi?
  2. URL’yi doğrulayın - Uç noktaya internetten erişilebiliyor mu?
  3. Olayları kontrol edin - Doğru olaylar seçili mi?
  4. Günlükleri inceleyin - Kayıtlı bir hata var mı?
  1. Uç noktanızı kontrol edin - 200 OK döndürüyor mu?
  2. Yanıt süresini kontrol edin - Zaman aşımı içinde yanıt veriyor mu?
  3. Hata mesajlarını inceleyin - Sorun ne?
  4. Manuel test edin - Bir test webhook’u gönderin

Webhook gizli anahtarınız ele geçirilirse:

  1. Webhook ayarlarında Regenerate Secret düğmesine tıklayın
  2. Uygulamanızı yeni gizli anahtarla güncelleyin
  3. Eski gizli anahtar anında çalışmayı durdurur

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 →