Skip to main content
Webhook’lar; transfer oluşturma, başarılı tamamlanma ve başarısızlık olaylarını sunucunuza HTTP POST ile gönderir. EFT/FAST işlemlerinin asenkron yapısı nedeniyle webhook entegrasyonu pratikte zorunludur — processing veya delivered durumdaki transferin son sonucunu webhook ile yakalarsınız.

Akış

Endpoint kuralları

Webhook hedef endpoint’iniz aşağıdaki kurallara uymalıdır:
HTTPS zorunlu — HTTP URL’leri reddedilir.
Public erişilebilir — özel ağ veya VPN arkasında olamaz.
15 saniye içinde HTTP 2xx döner — uzun süren işler için iş kuyruğa atılmalıdır.
Idempotent çalışır — aynı X-Payven-Event-Id ile aynı olay birden fazla kez gelebilir.
İmzayı doğrular — sahte istekleri reddeder. Bkz. İmza Doğrulama.

İstek formatı

POST /webhooks/payven HTTP/1.1
Host: example.com
Content-Type: application/json
X-Payven-Event:        transfer.succeeded
X-Payven-Event-Id:     evt_8e3f5c129a7b4c8dbc4e
X-Payven-Delivery-Id:  9f1c8e76-2a3b-4f12-9c8d-12cb24a8a8a8
X-Payven-Signature:    sha256=4f1d8c92ab7e3bcf9...
X-Payven-Timestamp:    1714742400
{
  "id":         "evt_8e3f5c129a7b4c8dbc4e",
  "type":       "transfer.succeeded",
  "created_at": "2026-05-03T12:34:58.123+00:00",
  "data": {
    "transfer_id":   "8e3f5c12-9a7b-4c8d-bc4e-2c963f66afa6",
    "external_id":   "PAYROLL-001",
    "status":        "completed",
    "amount":        1500000,
    "currency":      "TRY",
    "transfer_type": "fast",
    "receipt_no":    "TRF-20260503-0001",
    "sent_date":     "2026-05-03T12:34:58.000+00:00",
    "processed_date":"2026-05-03T12:34:59.234+00:00"
  }
}
HeaderAçıklama
X-Payven-EventOlay tipi (transfer.created, transfer.succeeded, transfer.failed)
X-Payven-Event-IdOlay kimliği — aynı olay birden fazla teslim edilse bile aynı kalır. Idempotent handler’ınızda bu değeri kullanın.
X-Payven-Delivery-IdTeslim kimliği — her teslim denemesinde farklıdır.
X-Payven-SignatureRequest body’nin HMAC-SHA256 imzası (sha256=<hex>)
X-Payven-Timestampİmzalanan Unix zaman damgası (saniye). Replay saldırılarına karşı 5 dk tolerans dışındaki istekleri reddedin.

Abone olma

curl -X POST https://transfer.payven.com.tr/api/v1/webhooks \
  -H "Authorization: Bearer $PAYVEN_TOKEN" \
  -H "X-Tenant-Id: $TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://example.com/webhooks/payven-transfers",
    "events": ["transfer.created", "transfer.succeeded", "transfer.failed"]
  }'
Yanıttaki secret değerini saklayın — imza doğrulamasında kullanacaksınız.
secret değeri yalnızca bu yanıtta bir kez döner. Liste/detay endpoint’lerinde gizlenir. Hemen secret manager’ınıza kaydedin. Kaybedilirse POST /webhooks/{id}/rotate-secret ile yenileyin.

Yeniden deneme

İlk denemede 2xx dönmezse Payven otomatik olarak yeniden dener:
DenemeBekleme süresi
1Hemen
21 dakika
35 dakika
430 dakika
52 saat
624 saat
Tüm bekleme süreleri ±%20 jitter ile uygulanır. 6. denemeden sonra teslim “kalıcı başarısız” olarak işaretlenir; konsoldan manuel olarak yeniden tetiklenebilir. Detay: Webhook Yeniden Deneme.

At-least-once teslim

Aynı olay birden fazla kez gelebilir. Sebepler:
  • Sizin endpoint’iniz timeout / 5xx döndü → retry
  • Network kesintisi → response kaybı → retry
  • Konsoldan manuel replay yapıldı
Bu nedenle handler’larınızı idempotent yazın:
async function handleTransferWebhook(req, res) {
  const eventId = req.headers["x-payven-event-id"];

  // Veritabanında bu eventId daha önce işlendi mi?
  if (await db.processedEvents.exists(eventId)) {
    return res.status(200).end();   // ack but skip
  }

  const event = req.body;
  if (event.type === "transfer.succeeded") {
    await markPayrollPaid(event.data.external_id, event.data.receipt_no);
  } else if (event.type === "transfer.failed") {
    await flagPayrollForReview(event.data.external_id, event.data);
  }

  await db.processedEvents.insert({ id: eventId, processedAt: new Date() });
  res.status(200).end();
}

Sonraki adımlar

Olay Kataloğu

3 olay tipi ve payload alanlarının detayı.

İmza Doğrulama

HMAC-SHA256 verifikasyon kodu (5 dilde).