Webhook: arama olaylarını kendi sunucunuza

Arama başladı, bitti, döküm ve hata olaylarını gerçek zamanlı alın — HMAC imza doğrulama, yeniden deneme politikası ve idempotens deseni.

Güncellendi: 17 Ağustos 2026

Webhook, arama olaylarına yoklama (polling) yapmadan tepki vermenin yoludur. Platform sizin adresinize JSON gönderir, siz işi yapar ve 2xx dönersiniz. Bu kadar.

Kurulum

Asistan bazlı arama olayları için webhook adresini asistana yazın. Panelde Asistanlar → Düzenle → Webhook alanı da aynı işi yapar.

curl -X PATCH https://api.call2me.app/v1/agents/agent_abc123 \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"webhook_url": "https://sizin-sunucunuz.com/webhooks/call2me"}'

Olay tipleri

OlayNe zaman tetiklenirNe için kullanılır
call.startedSes oturumu açıldığındaCRM’de aramayı canlı işaretlemek
call.transcriptHer tamamlanan cümledeCanlı döküm ekranı, duygu analizi
call.endedArama bittiğinde (her nedenle)Kayıt bağlantısını saklamak, çıkarım çalıştırmak
call.errorArama sırasında bir şey bozulduğundaOperasyon uyarısı, kullanıcıya bildirim
call.transferAsistan aramayı insana aktardığındaKuyruk durumunu güncellemek

Yük yapısı

Her olay aynı zarfı taşır: type, call_id, agent_id ve timestamp alanları sabittir. Olaya özel alanlar data içine girer.

{
  "type": "call.ended",
  "call_id": "call_xyz789",
  "agent_id": "agent_abc123",
  "timestamp": "2026-08-17T14:23:11Z",
  "data": {
    "duration_ms": 134000,
    "status": "completed",
    "from": "+905321234567",
    "to": "+908502345678",
    "transcript_url": "https://api.call2me.app/v1/calls/call_xyz789/transcript",
    "recording_url": "https://api.call2me.app/v1/calls/call_xyz789/recording"
  }
}

İmza doğrulama

Her istek X-Call2Me-Signature: sha256=<hex> başlığını taşır. Ham gövde üzerinden webhook sırrınızla HMAC-SHA256 hesaplayıp karşılaştırın. Doğrulamadan hiçbir yükü işlemeyin — aksi halde sizin adresinizi bilen herkes sahte olay üretebilir.

import hmac, hashlib

def dogrula(govde: bytes, baslik: str, sir: str) -> bool:
    beklenen = hmac.new(sir.encode(), govde, hashlib.sha256).hexdigest()
    gelen = baslik.replace("sha256=", "")
    return hmac.compare_digest(beklenen, gelen)

Karşılaştırmayı mutlaka sabit zamanlı fonksiyonla yapın: Python’da hmac.compare_digest, Node’da crypto.timingSafeEqual. Düz == karşılaştırması zamanlama saldırısına açıktır.

Yeniden deneme davranışı

Adresiniz 5xx dönerse veya 10 saniyeden uzun yanıt vermezse platform artan aralıklarla yeniden dener:

1 dk → 5 dk → 30 dk → 2 saat → 6 saat → 24 saat
  • 24 saatin sonunda olay ölü mektup kuyruğuna düşer; panelden görüp yeniden gönderebilirsiniz.
  • 4xx yanıtları yeniden DENENMEZ — kalıcı ret sinyali olarak okunur.
  • İşi hemen yapmayın: 2xx dönüp işi arka planda kuyruğa alın, böylece zaman aşımına düşmezsiniz.

İdempotens — mükerrer işlemeyi engelleme

Her olayın kararlı bir event_id alanı vardır. Ağ kesintisinden sonra başarılı olan bir denemede aynı olay iki kez ulaşabilir (nadir ama mümkün). event_id üzerinden tekilleştirin.

if not redis.set(f"event:{event_id}", "1", nx=True, ex=86400):
    return  # bu olay zaten işlendi

Hesap düzeyi webhook

Yukarıdakiler asistan bazlı arama olaylarıydı. Hesap (tenant) düzeyinde tek bir webhook daha tanımlayabilirsiniz — özellikle headless ve mobil entegrasyonlar için faydalı.

curl -X PUT https://api.call2me.app/v1/webhooks \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"webhook_url": "https://sizin-uygulamaniz.com/hooks/call2me"}'
# → { "webhook_url": "...", "webhook_secret": "a1b2c3..." }   sırrı saklayın

Bu kanaldan iki olay gönderilir: headless bir sesli oturum bittiğinde voice_session.ended, bakiye eşiğin altına düştüğünde wallet.low_balance (varsayılan eşik $5, günde en çok bir kez).

{ "event": "voice_session.ended", "timestamp": "2026-08-17T10:00:00Z",
  "data": { "room_name": "agent_x_ab12", "agent_id": "agent_x",
            "external_user_id": "user_42", "duration_sec": 143.2,
            "cost_usd": 0.24, "ended_at": "2026-08-17T10:00:00Z" } }

{ "event": "wallet.low_balance", "timestamp": "2026-08-17T10:00:00Z",
  "data": { "balance_usd": 3.10, "threshold_usd": 5.0 } }

Ayarlanmış webhook adresini GET /v1/webhooks ile okuyabilirsiniz; sır maskelenir, yalnızca tanımlı olup olmadığı döner. Sırrı kaybederseniz PUT ile yeniden ayarlayın.

Üretimde ayakta kalan desen

  1. 1İmzayı doğrula; geçersizse 401 dön ve yükü hiç okuma.
  2. 2event_id ile tekilleştir; daha önce gördüysen 200 dönüp çık.
  3. 3Yükü kendi kuyruğuna yaz ve hemen 200 dön.
  4. 4Asıl işi (CRM güncelleme, e-posta, analiz) kuyruk işçisinde yap.
  5. 5Kalıcı hataları kendi tarafında logla — 4xx dönmek olayı kalıcı olarak kaybettirir.

Sık sorulanlar

Webhook adresini nasıl tanımlarım?

Asistan bazlı arama olayları için PATCH /v1/agents/{id} ile webhook_url alanını ayarlayın veya panelde Asistanlar → Düzenle ekranını kullanın. Hesap düzeyi olaylar için PUT /v1/webhooks.

Sunucum kapalıyken olay gelirse ne olur?

5xx ve zaman aşımı durumlarında olay artan aralıklarla yaklaşık 24 saat boyunca yeniden denenir (1 dk, 5 dk, 30 dk, 2 sa, 6 sa, 24 sa). Sonrasında ölü mektup kuyruğuna düşer ve panelden yeniden gönderilebilir.

İsteğin gerçekten platformdan geldiğini nasıl anlarım?

X-Call2Me-Signature başlığındaki HMAC imzasını doğrulayın: ham gövde üzerinden webhook sırrınızla SHA-256 HMAC hesaplayıp sabit zamanlı karşılaştırma yapın.

4xx dönerse yeniden denenir mi?

Hayır. 4xx kalıcı ret sinyalidir ve olay bir daha gönderilmez. Geçici bir sorununuz varsa 5xx dönün ki yeniden denenmeyi tetikleyin.

Aynı olay iki kez gelebilir mi?

Nadiren, evet — özellikle yanıtınız ulaşmadan bağlantı koptuğunda. Bu yüzden event_id üzerinden tekilleştirme yapmalısınız.

10 dakikada AI telefon asistanınızı kurun

Kod yok. Kart yok. Sadece bir telefon numarası.