FastComments.com

Webhooks

FastComments ile sistemimizde bir yorum eklendiğinde, güncellendiğinde veya kaldırıldığında bir API endpoint'i çağırmak mümkündür.

Bunu HTTP/HTTPS üzerinden asenkron webhooks ile gerçekleştiriyoruz.

Webhooks Nedir Internal Link

Webhook, iki sistem arasında bir mekanizma veya entegrasyon olup "üretici" (FastComments) bir olay tetikler ve "tüketici" (Siz) bu olayı bir API çağrısı ile tüketir.

Desteklenen Olaylar ve Kaynaklar Internal Link

FastComments yalnızca Yorum kaynağı için webhook'ları destekler.

Yorum oluşturma, silme ve güncelleme için webhook'ları destekliyoruz.

Bunların her biri sistemimizde ayrı olaylar olarak kabul edilir ve bu nedenle webhook olayları için farklı anlamlar ve yapılar içerir.

Dashboard'dan veya API üzerinden (API aracılığıyla Webhook'ları Yönetmeye bakın) aynı olaya birden fazla uç nokta abone olabilir. Her webhook bağımsız olarak teslim edilir.

Test Internal Link

Yeni webhook ekleme ve düzenleme sayfalarında, formda o an bulunan URL'ye kaydedilmiş olup olmadığına bakılmaksızın istek gönderen bir Send Test Payload düğmesi bulunur. Create ve Update olayları sahte bir WebhookComment nesnesi gönderirken, Delete testi yalnızca bir ID içeren sahte bir istek gövdesi gönderir.

Payload'ları Doğrulama

Webhook entegrasyonunuzu test ederken, gelen isteklerin aşağıdaki başlıkları içerdiğini doğrulayın:

  1. X-FastComments-Timestamp - Unix zaman damgası (saniye)
  2. X-FastComments-Signature - HMAC-SHA256 imzası

İmza şeması tanıtılmadan önce oluşturulmuş webhooks, API Secret'ınızı içeren bir token başlığı da alır. Yeni webhooks bunu almaz.

Payload'ların orijinal olduğundan emin olmak için HMAC imza doğrulamasını kullanın.

Test Araçları

Geliştirme sırasında gelen webhook payload'larını incelemek için webhook.site veya ngrok gibi araçları kullanabilirsiniz.

Olay Türleri

  • Create Event: Yeni bir yorum oluşturulduğunda tetiklenir.
  • Update Event: Bir yorum düzenlendiğinde tetiklenir.
  • Delete Event: Bir yorum silindiğinde tetiklenir.

Her webhook tek bir olaya ve tek bir HTTP metoduna (POST, PUT veya DELETE) bağlıdır. Her olay, istek gövdesinde tam yorum verisini içerir (payload formatı için Veri Yapıları bölümüne bakın).

Veri Yapıları Internal Link

Webhooklar aracılığıyla gönderilen tek yapı, aşağıda TypeScript ile özetlenen WebhookComment nesnesidir.

WebhookComment Nesnesinin Yapısı

"Create" Olayının Yapısı

"create" olayının istek gövdesi bir WebhookComment nesnesidir.

"Update" Olayının Yapısı

"update" olayının istek gövdesi bir WebhookComment nesnesidir.

"Delete" Olayının Yapısı

"delete" olayının istek gövdesi bir WebhookComment nesnesidir.

14 Kasım 2023 itibarıyla değişiklik
Daha önce "delete" olayının istek gövdesi yalnızca yorum kimliğini (id) içeriyordu. Artık silme anındaki yorumun tamamını içerir.

Her anahtar gövdede her zaman bulunur. Yorumun bir alan için değeri olmadığında gövde null taşır (booleans için false, listeler için []), böylece bir teslimatın şekli yorumdan yoruma asla değişmez.

WebhookComment Nesnesi
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** Yorumun kimliği (id). **/
4 id: string
5 /** Yorum iş parçacığını tanımlayan kimlik veya URL. Normalize edilmiştir. **/
6 urlId: string
7 /** Yorumun bırakıldığı yeri işaret eden URL. **/
8 url: string | null
9 /** Yorumu bırakan kullanıcının kimliği. SSO ise, kiracı (tenant) kimliği önekiyle gelir. **/
10 userId: string | null
11 /** Yorumu bırakan kullanıcının e-postası. **/
12 commenterEmail: string | null
13 /** Yorum widget'ında görünen kullanıcı adı. SSO ile, displayName olabilir. **/
14 commenterName: string
15 /** Ham yorum metni. **/
16 comment: string
17 /** Ayrıştırma sonrası yorum metni. **/
18 commentHTML: string
19 /** Yorumun harici kimliği. **/
20 externalId: string | null
21 /** Üst yorumun kimliği. **/
22 parentId: string | null
23 /** Yorumun bırakıldığı UTC tarihi. **/
24 date: UTC_ISO_DateString
25 /** Oyların birleşik karması (yukarı - aşağı). **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Kullanıcı yorum yaparken oturum açtıysa, yorumu doğruladıysa veya yorum bırakıldığında oturumunu doğruladıysa true. **/
30 verified: boolean
31 /** Yorumun doğrulandığı UTC tarihi. **/
32 verifiedDate: UTC_ISO_DateString | null
33 /** Bir moderatör yorumu incelenmiş olarak işaretlediyse. **/
34 reviewed: boolean
35 /** Avatarın konumu veya base64 kodlaması. Yalnızca SSO ile bu değer iletildiyse base64 olur. **/
36 avatarSrc: string | null
37 /** Yorum manuel veya otomatik olarak spam olarak işaretlendi mi? **/
38 isSpam: boolean
39 /** Yorum otomatik olarak spam olarak işaretlendi mi? **/
40 aiDeterminedSpam: boolean
41 /** Yorumda görseller var mı? **/
42 hasImages: boolean
43 /** "Most Relevant" sıralama yönü için yorumun bulunduğu sayfa numarası. **/
44 pageNumber: number | null
45 /** "Oldest First" sıralama yönü için yorumun bulunduğu sayfa numarası. **/
46 pageNumberOF: number | null
47 /** "Newest First" sıralama yönü için yorumun bulunduğu sayfa numarası. **/
48 pageNumberNF: number | null
49 /** Yorum otomatik mi yoksa manuel mi onaylandı? **/
50 approved: boolean
51 /** Yorum yazıldığında kullanıcının yerel ayar kodu (format: en_us). **/
52 locale: string | null
53 /** Yorumda yazılan ve başarıyla ayrıştırılan @mention'lar. Yoksa boştur. **/
54 mentions: CommentUserMention[]
55 /** Yorumun geldiği alan adı. **/
56 domain: string | null
57 /** Bu yorumla ilişkili moderasyon grubu kimlikleri. Yoksa boştur. **/
58 moderationGroupIds: string[]
59 /** Bu yorumda yorumcu adının yanında gösterilen rozetler, olayın oluşturulduğu andaki haliyle. Yoksa boştur. **/
60 badges: CommentUserBadgeInfo[]
61}
62

Kullanıcılar bir yorumda etiketlendiğinde, bilgi mentions adlı bir listede saklanır. Bu listedeki her nesne aşağıdaki yapıya sahiptir.

Webhook Mentions Nesnesi
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Kullanıcı kimliği. SSO kullanıcıları için, kiracı (tenant) kimliğiniz önekiyle gelir. **/
4 id: string
5 /** @ simgesi dahil, nihai @mention etiket metni. **/
6 tag: string
7 /** @ simgesi dahil, orijinal @mention etiket metni. **/
8 rawTag: string
9 /** Etiketlenen kullanıcı türü. user = FastComments.com hesabı. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Kullanıcı bildirimlerden çıkış yapmış olsa bile bu yine de true olarak ayarlanır. **/
12 sent: boolean
13}
14

badges listesindeki her girdi aşağıdaki yapıya sahiptir. Rozet türleri için Rozetler rehberine bakın.

Webhook Badge Nesnesi
Copy CopyRun External Link
1
2interface CommentUserBadgeInfo {
3 /** Bu kullanıcıya verilen rozetin kimliği. **/
4 id: string
5 /** Rozet türü. **/
6 type: number
7 /** Rozetin üzerine gelindiğinde gösterilen rozet açıklaması. **/
8 description: string
9 /** Rozet üzerinde gösterilen metin. **/
10 displayLabel?: string | null
11 /** Rozet bir görsel kullanıyorsa, gösterilen görsel. **/
12 displaySrc?: string | null
13 backgroundColor?: string | null
14 borderColor?: string | null
15 textColor?: string | null
16 /** Rozete uygulanan ek bir CSS sınıfı. **/
17 cssClass?: string | null
18}
19

HTTP Metotları

Her webhook olay türü için HTTP metodunu yönetim panelinde yapılandırabilirsiniz:

  • Create Olayı: POST veya PUT (varsayılan: PUT)
  • Update Olayı: POST veya PUT (varsayılan: PUT)
  • Delete Olayı: DELETE, POST veya PUT (varsayılan: DELETE)

Tüm istekler bir kimlik (ID) içerdiğinden, Create ve Update işlemleri varsayılan olarak idempotenttir (PUT). Aynı Create veya Update isteğini tekrarlamak, sizin tarafınızda yinelenen nesneler oluşturmamalıdır.

İstek Başlıkları

Her webhook isteği aşağıdaki başlıkları içerir:

BaşlıkAçıklama
Content-Typeapplication/json
tokenAPI Gizli Anahtarınız (API Secret)
X-FastComments-Timestampİsteğin imzalandığı Unix zaman damgası (saniye)
X-FastComments-SignatureHMAC-SHA256 imzası (sha256=<hex>)

HMAC imzasını doğrulama hakkında bilgi için Güvenlik ve API Tokenları sayfasına bakın.

Güvenlik ve API Token'ları Internal Link

FastComments webhook istekleri güvenlik için birden fazla kimlik doğrulama mekanizması içerir.

Gönderilen Başlıklar

HeaderAçıklama
tokenAPI Gizli Anahtarınız (geriye dönük uyumluluk için)
X-FastComments-Timestampİsteğin imzalandığı Unix zaman damgası (saniye)
X-FastComments-SignatureGönderinin HMAC-SHA256 imzası

HMAC İmza Doğrulaması (Önerilen)

Webhook gönderilerinin orijinal ve değiştirilmemiş olduğunu sağlamak için HMAC imzasını doğrulamanızı şiddetle tavsiye ederiz.

İmza Formatı: sha256=<hex-encoded-signature>

İmzanın nasıl hesaplandığı:

  1. Birleştir: timestamp + "." + JSON_payload_body
  2. Anahtar olarak API Gizli Anahtarınızı kullanarak HMAC-SHA256 hesaplayın
  3. Sonucu hexadecimal (hex) olarak kodlayın

Doğrulama Örneği (Node.js)

const crypto = require('crypto');

function verifyWebhookSignature(req, apiSecret) {
    const timestamp = req.headers['x-fastcomments-timestamp'];
    const signature = req.headers['x-fastcomments-signature'];

    if (!timestamp || !signature) {
        return false;
    }

    // Zaman damgasının güncel olduğunu doğrula (5 dakika içinde)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Tekrar oynatma (replay) saldırılarını önlemek için
    }

    // İmzayı doğrula
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

    return signature === `sha256=${expectedSignature}`;
}

Doğrulama Örneği (Python)

import hmac
import hashlib
import time
import json

def verify_webhook_signature(headers, body, api_secret):
    timestamp = headers.get('X-FastComments-Timestamp')
    signature = headers.get('X-FastComments-Signature')

    if not timestamp or not signature:
        return False

    # Zaman damgasının güncel olduğunu doğrula
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # İmzayı doğrula
    payload = json.dumps(body, separators=(',', ':'))
    message = f"{timestamp}.{payload}"
    expected = hmac.new(
        api_secret.encode(),
        message.encode(),
        hashlib.sha256
    ).hexdigest()

    return signature == f"sha256={expected}"

Doğrulama Örneği (PHP)

function verifyWebhookSignature($headers, $body, $apiSecret) {
    $timestamp = $headers['X-FastComments-Timestamp'] ?? null;
    $signature = $headers['X-FastComments-Signature'] ?? null;

    if (!$timestamp || !$signature) {
        return false;
    }

    // Zaman damgasının güncel olduğunu doğrula (5 dakika içinde)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // İmzayı doğrula
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Eski Kimlik Doğrulama

token başlığı, API Gizli Anahtarınızı içeren, geriye dönük uyumluluk için hâlâ gönderilmektedir. Ancak, tekrar oynatma saldırılarına karşı koruma sağladığı için geliştirilmiş güvenlik için HMAC doğrulamasına geçmenizi öneririz.

API üzerinden Webhook'ları Yönetme Internal Link

Webhooks ayrıca REST API üzerinden yönetilebilir. Bu, Zapier gibi entegrasyonların kontrol paneline dokunmadan yorum olaylarına abone olmasını sağlar ve REST Hooks desenini izler: abone ol, olayları al, aboneliği iptal et.

API abonelikleri, kontrol panelinde yapılandırılmış webhooks'ların yanında bulunur. Bir yorum olayı, alanına uyan her webhook'a, webhook'un nasıl oluşturulduğuna bakılmaksızın, ayrı bir teslimat olarak gönderilir.

Kimlik Doğrulama

Her istek, x-api-key başlığında (veya API_KEY sorgu parametresinde) API Anahtarınızı ve tenantId sorgu parametresinde kiracı kimliğinizi gerektirir. Her ikisi de kontrol panelindeki API Gizli Sayfası'nda gösterilir.

Abone Ol

POST https://fastcomments.com/api/v1/webhooks?tenantId=YOUR_TENANT_ID
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
    "url": "https://hooks.zapier.com/hooks/catch/123/abc",
    "event": "comment-created"
}
AlanGerekliAçıklama
urlEvetMutlak bir http veya https URL'si.
eventEvetcomment-created, comment-updated or comment-deleted.
domainHayırHesap yapılandırmanızdaki bir alan adı. Varsayılan * olup, her alan adı için olayları alır.
methodHayırPOST (default), PUT or DELETE.

Yanıt, aboneliği içerir:

{
    "status": "success",
    "webhook": {
        "id": "66f1c4c1e7a2b3d4f5a6b7c8",
        "url": "https://hooks.zapier.com/hooks/catch/123/abc",
        "event": "comment-created",
        "domain": "*",
        "method": "POST",
        "source": "api",
        "enabled": true,
        "createdAt": "2026-09-08T12:00:00.000Z"
    }
}

Aynı URL'yi aynı olay ve alan adına tekrar abone etmek, bir kopya oluşturmak yerine mevcut aboneliği döndürür, böylece bir istemci güvenle yeniden deneyebilir. Her kiracı en fazla 50 API aboneliğine sahip olabilir.

Liste

GET https://fastcomments.com/api/v1/webhooks?tenantId=YOUR_TENANT_ID

Kiracı için kontrol panelinde yönetilenler dahil olmak üzere tüm webhook'ları döndürür ("source": "dashboard"). event, domain veya source ile filtreleyin.

Aboneliği İptal Et

DELETE https://fastcomments.com/api/v1/webhooks/SUBSCRIPTION_ID?tenantId=YOUR_TENANT_ID

Bir aboneliği silmek, ona hâlâ kuyrukta bekleyen olayları da iptal eder. Bu şekilde yalnızca API üzerinden oluşturulan abonelikler silinebilir; kontrol paneli webhook'u veya hesabınızda bulunmayan bir kimlik, 404 yanıtını not-found koduyla verir. Kontrol paneli webhook'ları Webhooks sayfasında düzenlenir.

Yükler ve İmzalama

Teslimatlar, kontrol paneli webhook'larıyla aynı yükü kullanır (Data Structures bölümüne bakın) ve aynı HMAC şemasıyla imzalanır (Security & API Tokens bölümüne bakın). API abonelikleri asla eski token başlığını almaz, bu yüzden X-FastComments-Signature başlığını doğrulayın.

Örnek Yükler

GET https://fastcomments.com/api/v1/webhooks/sample-payloads?tenantId=YOUR_TENANT_ID&event=comment-created&limit=3

Hesabın en son yorumlarını, teslimatın taşıdığı tam biçimde döndürür, böylece bir entegrasyon ilk olay gelmeden gerçek örnek verileri gösterebilir. event isteğe bağlıdır ve sadece doğrulanır, çünkü her olay aynı yorum nesnesini taşır. limit varsayılan olarak 3'tür ve 1 ile 10 arasında kabul eder. 2 API kredisi maliyetlidir.

{
    "status": "success",
    "payloads": [
        {
            "id": "66f1c4c1e7a2b3d4f5a6b7c8",
            "urlId": "https://example.com/blog/hello-world",
            "commenterName": "Jane Reader",
            "comment": "Great article!",
            "date": "2026-09-08T12:00:00.000Z",
            "approved": true
        }
    ]
}

410 Gone Yanıtı

Bir API aboneliğinin uç noktası HTTP 410 Gone yanıtı verirse, FastComments bunu bir abonelik iptali olarak değerlendirir: abonelik, kuyrukta bekleyen olaylarıyla birlikte silinir ve başka teslimat denenmez. Kontrol panelinde yapılandırılmış webhook'lar otomatik olarak silinmez; onlar için 410 sıradan bir hatadır. Diğer tüm hata durumları yeniden denenir ve sonunda webhook devre dışı bırakılır, How it Works & Handling Retries bölümünde açıklandığı gibi.

Kontrol Paneli

API abonelikleri, Webhooks listesinde API kaynağıyla görünür; burada bir yönetici onları düzenleyebilir, devre dışı bırakabilir, yeniden etkinleştirebilir veya silebilir.

Sonuç olarak

Bu, Webhooks belgelerimizin sonudur.

Umarız FastComments Webhook entegrasyonunu anlaşılması kolay ve kurulumu hızlı bulursunuz.

Belgelerimizde herhangi bir boşluk tespit ettiğinizi düşünüyorsanız, lütfen aşağıdan bize bildirin.