Webhook
Olaylar sistemine push edilir: imzalı payload, yeniden deneme, doğrulama.
Webhook, bir şey olduğunda Kerte’nin senin sunucuna imzalı bir HTTP POST göndermesidir. Sürekli sorgulamak (polling) yerine olayı anında alırsın.
Konsolda Yönetim → Webhooks’tan bir uç (endpoint) URL’i tanımlar, hangi olayları istediğini seçersin. Kerte sana bir imza anahtarı (secret) verir.
Olaylar
| Olay | Ne zaman |
|---|---|
employee.synced | İşyeri çalışan senkronu bitti |
tesvik.calculation.completed | Teşvik hesaplaması tamamlandı |
tesvik.error.detected | Hatalı teşvik tespit edildi |
e-vizite.report.created | Yeni istirahat raporu senkron edildi |
e-vizite.approval.changed | Rapor onay durumu değişti |
subscription.updated | Abonelik/kapsam değişti |
invoice.paid | Fatura ödendi |
Payload
Gövde her zaman aynı zarfı taşır; olaya özel alanlar data içindedir.
{
"id": "evt_2b9f…",
"type": "tesvik.calculation.completed",
"createdAt": "2026-09-12T10:00:00Z",
"data": {
"workplaceId": "wp_…",
"period": "2026-08",
"total": 128450.75
}
}
Başlıklar:
X-Kerte-Event: tesvik.calculation.completed
X-Kerte-Delivery: dl_7c1a…
X-Kerte-Signature: t=1734560000,v1=5f2b…e9
Content-Type: application/json
İmza doğrulama
İmza, t (unix saniye) ve gövdenin ham hâli üzerinden hesaplanır: HMAC-SHA256(secret, "{t}.{rawBody}"), hex.
Ham gövdeyi al
İmza ayrıştırılmamış gövde üzerinden hesaplanır. Framework’ün JSON’u parse etmeden önce ham metni yakala (req.rawBody).
İmzayı yeniden üret
Başlıktaki t ile ham gövdeyi . ile birleştir, endpoint secret’ıyla HMAC-SHA256 al.
Sabit-zamanlı karşılaştır
Ürettiğin değeri başlıktaki v1 ile sabit zamanlı karşılaştır (timingSafeEqual). Eşleşmezse isteği reddet.
Tazeliği kontrol et
t şimdiden 5 dakikadan eskiyse reddet: yakalanmış bir isteğin tekrar oynatılmasını (replay) engeller.
Node örneği:
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(rawBody, header, secret) {
const parts = Object.fromEntries(
header.split(",").map((kv) => kv.split("=")),
);
const expected = createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1 ?? "");
if (a.length !== b.length || !timingSafeEqual(a, b)) return false;
// Tazelik: 5 dk
return Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
}
PHP örneği:
[$t, $v1] = [null, null];
foreach (explode(',', $sigHeader) as $p) {
[$k, $val] = explode('=', $p, 2);
if ($k === 't') $t = $val; if ($k === 'v1') $v1 = $val;
}
$expected = hash_hmac('sha256', "$t.$rawBody", $secret);
if (!hash_equals($expected, $v1 ?? '')) http_response_code(400);
Yeniden deneme
Ucun 2xx dönerse teslimat başarılı sayılır. Aksi halde Kerte üstel geri çekilmeyle 5 kez dener. Uç üst üste başarısız olursa otomatik olarak duraklatılır ve konsolda uyarı görürsün.
Idempotency
Aynı olay nadiren birden çok kez ulaşabilir (yeniden deneme). id (olay) ya da X-Kerte-Delivery başlığını bir kez işlediğini kaydet; tekrar gelirse atla.
En iyi pratikler
- İmzayı her istekte doğrula; imzasız/yanlış imzalı isteği
400ile reddet. - Secret’ı sızdırma; konsoldan istediğin an döndür (rotate).
- Yalnız ihtiyacın olan olaylara abone ol.
- Uç adresini panelden test-gönderimle doğrula.