HomeDeveloper centerDeveloper center

Yanitly Kurumsal Webhook Entegrasyonu

Yanıtly webhook configuration guide. Event types, security, retry and error handling.

10 dikey sektör (E-Ticaret, Klinik, Otel, Restoran, Spor, Emlak, Ses AI, CRM vb.) için 50+ anlık olay bildirimi, RFC 2104 HMAC-SHA256 replay-attack korumalı çift imza ve sıfır kesintili anahtar rotasyonu.

Overview

Yanitly Webhook motoru, platformunuzda gerçekleşen her önemli aksiyonu (yeni sipariş, randevu onayı, sesli arama analizi, lead yakalama veya destek devri) anında harici ERP, CRM veya sunucularınıza güvenle iletir.

  • Milisecond Latency

    CloudEvents 1.0 standart formatında alt-saniyelik JSON teslimatı

  • Replay-Attack Koruması

    300s toleranslı t=...,v1=... HMAC-SHA256 imzası

  • Sıfır-Kesintili Rotasyon

    24 saat çift-imza ile kesintisiz gizli anahtar değişimi

10 Sektör & 50+ Doğrulanmış Olay Kataloğu

Şirketinizin sektörüne özel tasarlanmış olayları dinleyebilir, dilerseniz ecommerce.* gibi sektörel wildcard veya * genel joker karakteriyle tüm olayları tek uç noktada toplayabilirsiniz.

E-Ticaret & Perakende (E-Commerce) ecommerce.*

ecommerce.order.created
Müşteri yeni bir sipariş verdiğinde tetiklenir.
ecommerce.order.paid
Sipariş ödemesi başarıyla tamamlandığında tetiklenir.
ecommerce.order.shipped
Sipariş kargoya verildiğinde ve takip kodu atandığında tetiklenir.
ecommerce.order.delivered
Kargo müşteriye teslim edildiğinde tetiklenir.
ecommerce.cart.abandoned
Kullanıcı sepetine ürün ekleyip satın almayı tamamlamadığında tetiklenir.
ecommerce.cart.recovered
Yapay zeka hatırlatması ile terk edilen sepet satışa dönüştüğünde tetiklenir.
ecommerce.return.requested
Müşteri iade veya değişim talebi oluşturduğunda tetiklenir.
ecommerce.inventory.low_stock
Ürün stoğu kritik eşiğin altına indiğinde tetiklenir.

Klinik, Sağlık & Randevu (Clinic & Healthcare) clinic.*

clinic.appointment.booked
Hasta yeni bir randevu oluşturduğunda tetiklenir.
clinic.appointment.confirmed
Hasta veya klinik yetkilisi randevuyu teyit ettiğinde tetiklenir.
clinic.appointment.rescheduled
Randevu tarihi/saati ertelendiğinde tetiklenir.
clinic.appointment.cancelled
Randevu iptal edildiğinde tetiklenir.
clinic.reminder.confirmed
Hasta gelen hatırlatma mesajına "Geliyorum" yanıtı verdiğinde tetiklenir.
clinic.treatment.created
Yeni bir tedavi protokolü veya fiyat teklifi oluşturulduğunda tetiklenir.

Otel & Konaklama (Hotel & Hospitality) hotel.*

hotel.reservation.created
Yeni bir oda rezervasyonu oluşturulduğunda tetiklenir.
hotel.reservation.confirmed
Rezervasyon depozitosu alınıp kesinleştiğinde tetiklenir.
hotel.guest.checked_in
Misafir otele giriş yaptığında (check-in) tetiklenir.
hotel.concierge.requested
Misafir oda servisi, transfer veya ek hizmet talep ettiğinde tetiklenir.

Restoran & Yeme-İçme (Restaurant & Dining) restaurant.*

restaurant.booking.created
Masa rezervasyonu talebi oluşturulduğunda tetiklenir.
restaurant.guest.seated
Misafir masaya oturtulduğunda tetiklenir.
restaurant.table.assigned
Rezervasyona özel masa atandığında tetiklenir.

Sesli Asistan & Telefon AI (Yanitly SIP / OpenAI Live) voice.*

voice.call.started
Gelen veya giden sesli yapay zeka araması başladığında tetiklenir.
voice.call.ended
Sesli arama sonlandığında süre ve temel metriklerle tetiklenir.
voice.call.summary_ready
Yapay zeka görüşme özeti, duygu analizi ve aksiyon maddeleri hazırlandığında tetiklenir.
voice.call.human_escalation
Arayan kişi canlı bir temsilciye aktarılmak istediğinde tetiklenir.

Çekirdek Destek & Sohbet (Core Support) core.*

core.conversation.created
Yeni bir sohbet oturumu açıldığında tetiklenir.
core.conversation.closed
Konuşma çözüme kavuşturulup kapatıldığında tetiklenir.
core.message.received
Ziyaretçiden yeni mesaj geldiğinde tetiklenir.
core.handover.requested
Ziyaretçi temsilciye devir istediğinde tetiklenir.
core.ticket.created
Yeni bir destek bileti oluşturulduğunda tetiklenir.

CRM & Müşteri Zekası (CRM & Intelligence) crm_ai.*

crm.lead.captured
Sohbet veya formdan yeni potansiyel müşteri yakalandığında tetiklenir.
crm.lead.score_changed
Yapay zeka lead skorunu (soğuk/ılık/sıcak) güncellediğinde tetiklenir.
ai.churn_risk.flagged
Müşteri mesajında memnuniyetsizlik veya ayrılma riski tespit edildiğinde tetiklenir.

CloudEvents 1.0 Standart Zarf Yapısı

Tüm giden webhook bildirimleri CNCF CloudEvents 1.0 spesifikasyonuna uygundur. Bu sayede AWS EventBridge, GCP Eventarc, Zapier ve kurumsal mesajlaşma kuyruklarıyla doğrudan tak-çalıştır uyumluluk sağlar:

Code example
{
  "specversion": "1.0",
  "id": "evt_01J8Y4V9X8Z6B2M0W1C3D4E5F6",
  "type": "ecommerce.order.created",
  "source": "https://api.yanitly.com/v1/tenants/ten_998877",
  "time": "2026-09-27T00:15:30.124Z",
  "datacontenttype": "application/json",
  "tenant_id": "ten_998877",
  "sector": "ecommerce",
  "api_version": "2026-09-26",
  "data": {
    "orderId": "ord_100234",
    "orderNumber": "TR-2026-8819",
    "totalAmount": 3499.50,
    "currency": "TRY",
    "customer": {
      "id": "cust_5544",
      "name": "Merve Demir",
      "email": "[email protected]",
      "phone": "+905321112233"
    },
    "items": [
      {
        "sku": "MONT-DERI-01",
        "name": "Hakiki Deri Ceket",
        "quantity": 1,
        "unitPrice": 3499.50
      }
    ],
    "status": "paid"
  }
}

RFC 2104 HMAC-SHA256 Güvenlik & Replay Attack Koruması

Her webhook isteği HTTP başlığında Yanitly-Signature taşır. Formatı Stripe ve GitHub standartlarındadır:

Yanitly-Signature: t=1727384400,v1=5d41402abc4b2a76b9719d911017c592...

• t (Zaman Damgası): İsteğin üretildiği Unix zaman damgası (saniye). Sunucunuz gelen zaman damgası ile kendi saati arasında 300 saniyeden (5 dk) fazla fark varsa isteği reddetmelidir.

• v1 (İmza): HMAC-SHA256(gizli_anahtar, t + "." + ham_json_gövdesi) çıktısıdır.

• Sabit Zamanlı Karşılaştırma: Timing-attack açıklarını önlemek için imza doğrulaması mutlaka timingSafeEqual ile yapılmalıdır.

Doğrulama SDK Kod Örnekleri (Copy & Paste)

Sunucunuzun dilini seçerek hazır doğrulama fonksiyonunu doğrudan projenize entegre edebilirsiniz:

Code example
import crypto from 'node:crypto';
import express from 'express';

const app = express();

// Ham JSON gövdesini (raw body) string olarak saklayın:
app.use(express.json({
  verify: (req, _res, buf) => {
    (req as typeof req & { rawBody?: string }).rawBody = buf.toString('utf-8');
  }
}));

function verifyYanitlySignature(
  rawBody: string,
  signatureHeader: string | undefined,
  secret: string,
  toleranceSeconds = 300 // 5 dakika replay attack toleransı
): boolean {
  if (!signatureHeader || !rawBody) return false;

  const parts = signatureHeader.split(',');
  const timestampPart = parts.find((p) => p.startsWith('t='));
  const signatureParts = parts.filter((p) => p.startsWith('v1='));

  if (!timestampPart || signatureParts.length === 0) return false;

  const timestamp = Number(timestampPart.slice(2));
  if (isNaN(timestamp)) return false;

  // Replay Attack Koruması
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - timestamp) > toleranceSeconds) {
    console.error('Webhook zaman damgası tolerans dışı (Replay attack şüphesi)');
    return false;
  }

  // Beklenen HMAC-SHA256 hesaplama: secret + "t.payload"
  const expectedSig = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`, 'utf-8')
    .digest('hex');

  // Sıfır-kesintili rotasyonda v1=yeni,v1=eski şeklinde birden fazla v1 gelebilir
  return signatureParts.some((part) => {
    const candidateSig = part.slice(3);
    if (candidateSig.length !== expectedSig.length) return false;
    return crypto.timingSafeEqual(
      Buffer.from(candidateSig),
      Buffer.from(expectedSig)
    );
  });
}

app.post('/api/webhooks/yanitly', (req, res) => {
  const signature = req.headers['yanitly-signature'] as string;
  const rawBody = (req as typeof req & { rawBody?: string }).rawBody;

  const isValid = verifyYanitlySignature(rawBody, signature, process.env.YANITLY_WEBHOOK_SECRET!);
  if (!isValid) {
    return res.status(401).json({ error: 'Invalid Yanitly-Signature' });
  }

  const { id, type, data, time, sector } = req.body;
  console.log(`[Yanitly Webhook] Olay: ${type} (ID: ${id}, Sektör: ${sector})`);

  // Asenkron işlem kuyruğuna alın ve hemen 200 dönün
  res.status(200).json({ received: true });
});

Sıfır-Kesintili (Zero-Downtime) 24h Anahtar Rotasyonu

Güvenlik gereği anahtarınızı yenilediğinizde sunucunuzun hemen yeni anahtara geçememe riskine karşın Yanitly, 24 saatlik geçiş süreci (grace period) tanır:

Akıllı Devre Kesici (Circuit Breaker) & DLQ Politikası

Sunucunuzda çökme veya uzun süreli kesinti yaşandığında sisteminizi gereksiz HTTP trafiğiyle boğmamak ve Yanitly kaynaklarını korumak için koruma mekanizmaları devrededir:

Üstel Geri Çekilme (Exponential Backoff):

Her başarısız denemede bekleme süresi katlanarak artar: 1. deneme hemen, 2. deneme 1 dk, 3. deneme 5 dk, 4. deneme 30 dk, 5. deneme 2 saat sonra yapılır.

100 Ardışık Başarısızlıkta Otomatik Kilit:

Uç nokta 100 ardışık istek boyunca aralıksız hata döndürürse devre kesici devreye girer (disabled_circuit_breaker). Sunucunuzu onardıktan sonra panelden "Devre Kesiciyi Sıfırla" butonuyla anında açabilirsiniz.

Teslimat Müfettişi (Delivery Inspector):

Gönderilen her isteğin HTTP durumu, tam giden/gelen gövdesi ve gecikme süresi (ms) panelinizde saklanır ve tek tıkla yeniden tetiklenebilir (redeliver).

Best Practices

  • Always verify signatures
  • Process webhook operations asynchronously
  • Return 200 response quickly, queue heavy operations
  • Check event ID for idempotent events
  • Monitor and store webhook logs
  • Keep your timeout under 30 seconds
  • Log and monitor error conditions