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
| Olay | Ne zaman tetiklenir | Ne için kullanılır |
|---|---|---|
| call.started | Ses oturumu açıldığında | CRM’de aramayı canlı işaretlemek |
| call.transcript | Her tamamlanan cümlede | Canlı döküm ekranı, duygu analizi |
| call.ended | Arama bittiğinde (her nedenle) | Kayıt bağlantısını saklamak, çıkarım çalıştırmak |
| call.error | Arama sırasında bir şey bozulduğunda | Operasyon uyarısı, kullanıcıya bildirim |
| call.transfer | Asistan aramayı insana aktardığında | Kuyruk 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şlendiHesap 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ınBu 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İmzayı doğrula; geçersizse 401 dön ve yükü hiç okuma.
- 2event_id ile tekilleştir; daha önce gördüysen 200 dönüp çık.
- 3Yükü kendi kuyruğuna yaz ve hemen 200 dön.
- 4Asıl işi (CRM güncelleme, e-posta, analiz) kuyruk işçisinde yap.
- 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.