Webhooks
HeptaCert, belirli olaylar gerçekleştiğinde kayıtlı endpoint'inize imzalı bir HTTP POST isteği göndererek sistemlerinizi gerçek zamanlı olarak tetikler. Polling yapmak yerine olayların size gelmesini sağlar.
Nasıl Çalışır?
Endpoint kaydedin
Admin paneli → Webhooks sayfasından (veya API/CLI ile) bir URL ve dinlemek istediğiniz olayları seçin. HeptaCert size endpoint'e özel bir secret üretir.
Olay gerçekleşir
Sertifika yayımlanması gibi bir olay tetiklendiğinde HeptaCert, o olaya abone tüm aktif endpoint'lere POST isteği gönderir.
İmzayı doğrulayın
Gövdeyi (raw body) endpoint secret'ınızla HMAC-SHA256 ile imzalayıp X-HeptaCert-Signature başlığıyla karşılaştırın.
2xx dönün
10 saniye içinde 2xx yanıt verin. Aksi halde HeptaCert yeniden dener (aşağıya bakın).
Olaylar
Şu an aşağıdaki olaylar yayımlanır. Bir endpoint, bu olayların herhangi bir alt kümesine veya * ile tümüne abone olabilir.
| Olay | Tetiklenme |
|---|---|
cert.issued | Bir sertifika yayımlandığında |
cert.revoked | Bir sertifika iptal edildiğinde |
cert.bulk_completed | Toplu sertifika üretimi işi tamamlandığında |
cert.expiring_soon | Bir sertifikanın son kullanma tarihi yaklaştığında |
crm.profile_updated | Bir CRM kişi profili güncellendiğinde |
crm.lead_score_changed | Bir kişinin lead skoru değiştiğinde |
Tüm olaylara abone olmak için events listesinde tek bir "*" değeri gönderin. Yeni olay tipleri eklendiğinde otomatik olarak almaya başlarsınız.
Payload Formatı
Her istek şu zarf (envelope) yapısında JSON gönderir:
{
"event": "cert.issued",
"timestamp": "2026-09-15T10:30:00.000000+00:00",
"data": {
"certificate_id": 9001,
"public_id": "abc123xyz",
"attendee_name": "Ahmet Yılmaz",
"attendee_email": "ahmet@example.com",
"event_id": 42,
"event_name": "Python Summit 2026",
"verify_url": "https://heptacert.com/verify/abc123xyz"
}
}event— olay tipi (yukarıdaki tablodan).timestamp— ISO 8601, UTC. İmza güvenliği için bu değeriX-HeptaCert-Timestampile karşılaştırabilirsiniz.data— olaya özel yük. Olay tipine göre alanlar değişir.
İstek Başlıkları
Her teslimat şu başlıkları içerir:
| Başlık | Açıklama |
|---|---|
Content-Type | Her zaman application/json |
X-HeptaCert-Event | Olay tipi (örn. cert.issued) |
X-HeptaCert-Signature | sha256=<hex> formatında HMAC imzası |
X-HeptaCert-Timestamp | Payload zaman damgası |
X-HeptaCert-Attempt | Kaçıncı deneme olduğu (1–3) |
İmza formatı sha256= ön ekiyle gelir. Karşılaştırma yaparken ya beklenen değerinize aynı ön eki ekleyin ya da gelen başlıktan sha256= kısmını çıkarın. Çıplak hex ile karşılaştırma her zaman başarısız olur.
İmza Doğrulama
İmza, ham istek gövdesinin (parse edilmemiş byte'ların) endpoint secret'ınızla alınmış HMAC-SHA256 değeridir. Gövdeyi JSON'a çevirmeden önce ham haliyle doğrulayın — yeniden serialize etmek byte'ları değiştirip imzayı bozar.
import hashlib
import hmac
def verify_webhook(raw_body: bytes, signature_header: str, secret: str) -> bool:
# signature_header: "sha256=abcdef..."
expected = "sha256=" + hmac.new(
secret.encode(), raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header or "")FastAPI ile:
from fastapi import FastAPI, Request, HTTPException, Header
app = FastAPI()
@app.post("/webhooks/heptacert")
async def receive(request: Request, x_heptacert_signature: str = Header(None)):
raw = await request.body()
if not verify_webhook(raw, x_heptacert_signature, WEBHOOK_SECRET):
raise HTTPException(status_code=401, detail="Invalid signature")
payload = await request.json()
if payload["event"] == "cert.issued":
... # CRM'e bildir, Slack mesajı gönder, vb.
return {"ok": True}Sabit-zamanlı karşılaştırma kullanın (hmac.compare_digest, crypto.timingSafeEqual, hash_equals). Normal == karşılaştırması timing attack'lara açıktır.
Yeniden Deneme Politikası
Endpoint'iniz 2xx dışında yanıt verirse veya 10 saniye içinde yanıt vermezse HeptaCert teslimatı yeniden dener:
| Deneme | Bekleme (öncesinde) |
|---|---|
| 1 | — (hemen) |
| 2 | 2 saniye |
| 3 | 4 saniye |
Toplam 3 deneme yapılır (exponential backoff). Üçü de başarısız olursa teslimat failed olarak kaydedilir. Her teslimat denemesi — başarılı veya başarısız — teslimat kayıtlarına (webhook deliveries) yazılır; admin panelinden geçmişi inceleyebilirsiniz.
Yeniden denemeler kısa aralıklıdır (saniyeler), saat/gün değil. Endpoint'iniz uzun süre kapalı kalırsa o olaylar kaçırılır. Kritik veri için ek olarak periyodik bir senkronizasyon (örn. GET /admin/events/{id}/certificates) düşünün.
İdempotanlık
Yeniden denemeler nedeniyle aynı olayı birden fazla kez alabilirsiniz. İşleyicinizi idempotent yapın: data içindeki certificate_id gibi benzersiz kimlikleri kullanarak daha önce işlenmiş olayları atlayın.
Güvenlik: SSRF Koruması
HeptaCert, webhook hedef URL'lerini doğrular ve özel/iç ağ adreslerine teslimat yapmaz. Şu hedefler reddedilir:
localhost,127.0.0.1ve loopback adresleri- Özel aralıklar (
10.0.0.0/8,192.168.0.0/16,172.16.0.0/12) - Link-local, reserved ve multicast adresler
Bu, webhook sisteminin iç servislere istek yapmak için kötüye kullanılmasını (SSRF) önler. Endpoint'iniz herkese açık (public) bir adreste olmalıdır.
Webhook'ları Yönetme
Admin panelinin yanı sıra API ve CLI ile de yönetebilirsiniz:
# CLI
hc webhooks list
hc webhooks create https://myapp.com/hooks/heptacert \
--events "cert.issued,cert.revoked"
hc webhooks delete 3MCP araçlarıyla (AI asistanları): list_webhooks, create_webhook, delete_webhook.
Lokal Geliştirme
Lokal endpoint'inizi internete açmak için bir tünel kullanın (HeptaCert özel adreslere teslimat yapmadığı için localhost doğrudan çalışmaz):
ngrok http 3000
# https://xxxx.ngrok.io → localhost:3000Üretilen public URL'yi webhook hedefi olarak kaydedin, ardından bir test olayı tetikleyin (örn. bir test sertifikası yayımlayın) ve isteğin geldiğini doğrulayın.