FastComments.com

Webhooks

Sa FastComments moguće je pozvati API endpoint kad god se komentar doda, ažurira ili ukloni iz našeg sistema.

To ostvarujemo asinhronim webhooks preko HTTP/HTTPS.

Šta su Webhook-ovi Internal Link

A Webhook je mehanizam, odnosno integracija, između dva sistema gde "proizvođač" (FastComments) okida događaj koji "potrošač" (Vi) preuzima putem API poziva.

Podržani događaji i resursi Internal Link

FastComments podržava webhook‑ove samo za resurs Komentar.

Podržavamo webhook‑ove za kreiranje komentara, brisanje i ažuriranje.

Svaki od ovih smatra se posebnim događajem u našem sistemu i kao takav ima različitu semantiku
i strukture za webhook događaje.

Bilo koji broj krajnjih tačaka može da se pretplati na isti događaj, putem kontrolne table ili kroz API
(vidi Upravljanje webhook‑ovima putem API‑ja). Svaki webhook se isporučuje nezavisno.

Testiranje Internal Link

Stranice za kreiranje i izmenu webhook-a imaju dugme Send Test Payload koje šalje zahtev na URL koji je trenutno u formi, bez obzira na to da li je sačuvan ili ne. Create i Update događaji šalju lažni WebhookComment objekat, dok testiranje Delete-a šalje lažni request body sa samo ID-jem.

Verifikacija Payload-a

Kada testirate svoju webhook integraciju, proverite da dolazni zahtevi uključuju sledeće zaglavlja:

  1. X-FastComments-Timestamp - Unix vremenski pečat (sekunde)
  2. X-FastComments-Signature - HMAC-SHA256 potpis

Webhook-ovi kreirani pre uvođenja šeme potpisa takođe primaju token zaglavlje koje sadrži vaš API Secret. Novi webhook-ovi to ne primaju.

Koristite HMAC verifikaciju potpisa da biste osigurali da su payload-i autentični.

Alati za testiranje

Možete koristiti alate kao što su webhook.site ili ngrok da biste pregledali dolazne webhook payload-e tokom razvoja.

Tipovi događaja

  • Create Event: Aktivira se kada se kreira novi komentar.
  • Update Event: Aktivira se kada se komentar izmeni.
  • Delete Event: Aktivira se kada se komentar obriše.

Svaki webhook je vezan za jedan događaj i jednu HTTP metodu (POST, PUT ili DELETE). Svaki događaj uključuje kompletne podatke o komentaru u request body-ju (vidite Data Structures za format payload-a).

Strukture podataka Internal Link

Jedina struktura koja se šalje putem webhukova je objekat WebhookComment, prikazan u TypeScript-u ispod.

Struktura objekta WebhookComment

Struktura "create" događaja

Telo zahteva "create" događaja je objekat WebhookComment.

Struktura "update" događaja

Telo zahteva "update" događaja je objekat WebhookComment.

Struktura "delete" događaja

Telo zahteva "delete" događaja je objekat WebhookComment.

Promena od 14. novembra 2023.
Ranije je telo zahteva "delete" događaja sadržalo samo id komentara. Sada sadrži ceo komentar u trenutku brisanja.

Svaki ključ je uvek prisutan u telu. Kada komentar nema vrednost za neko polje, telo nosi null (ili false za boolean vrednosti i [] za liste), tako da oblik isporuke nikada ne varira od komentara do komentara.

Objekat WebhookComment
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** The id of the comment. **/
4 id: string
5 /** The id or URL that identifies the comment thread. Normalized. **/
6 urlId: string
7 /** The URL that points to where the comment was left. **/
8 url: string | null
9 /** The user id that left the comment. If SSO, prefixed with tenant id. **/
10 userId: string | null
11 /** The email of the user left the comment. **/
12 commenterEmail: string | null
13 /** The name of the user that shows in the comment widget. With SSO, can be displayName. **/
14 commenterName: string
15 /** Raw comment text. **/
16 comment: string
17 /** Comment text after parsing. **/
18 commentHTML: string
19 /** Comment external id. **/
20 externalId: string | null
21 /** The id of the parent comment. **/
22 parentId: string | null
23 /** The UTC date when the comment was left. **/
24 date: UTC_ISO_DateString
25 /** Combined karma (up - down) of votes. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** True if the user was logged in when they commented, or their verified the comment, or if they verified their session when the comment was left. **/
30 verified: boolean
31 /** The UTC date when the comment was verified. **/
32 verifiedDate: UTC_ISO_DateString | null
33 /** If a moderator marked the comment reviewed. **/
34 reviewed: boolean
35 /** The location, or base64 encoding, of the avatar. Will only be base64 if that was the value passed with SSO. **/
36 avatarSrc: string | null
37 /** Was the comment manually or automatically marked as spam? **/
38 isSpam: boolean
39 /** Was the comment automatically marked as spam? **/
40 aiDeterminedSpam: boolean
41 /** Are there images in the comment? **/
42 hasImages: boolean
43 /** The page number the comment is on for the "Most Relevant" sort direction. **/
44 pageNumber: number | null
45 /** The page number the comment is on for the "Oldest First" sort direction. **/
46 pageNumberOF: number | null
47 /** The page number the comment is on for the "Newest First" sort direction. **/
48 pageNumberNF: number | null
49 /** Was the comment approved automatically or manually? **/
50 approved: boolean
51 /** The locale code (format: en_us) of the user when the comment was written. **/
52 locale: string | null
53 /** The @mentions written in the comment that were successfully parsed. Empty when there are none. **/
54 mentions: CommentUserMention[]
55 /** The domain the comment is from. **/
56 domain: string | null
57 /** The moderation group ids associated with this comment. Empty when there are none. **/
58 moderationGroupIds: string[]
59 /** The badges shown next to the commenter's name on this comment, as of when the event was created. Empty when there are none. **/
60 badges: CommentUserBadgeInfo[]
61}
62

Kada su korisnici označeni u komentaru, informacija se čuva u listi pod nazivom mentions. Svaki objekat u toj listi ima sledeću strukturu.

Objekat Webhook Mentions
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** The user id. For SSO users, this will have your tenant id prefixed. **/
4 id: string
5 /** The final @mention tag text, including the @ symbol. **/
6 tag: string
7 /** The original @mention tag text, including the @ symbol. **/
8 rawTag: string
9 /** What type of user was tagged. user = FastComments.com account. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** If the user opts out of notifications, this will still be set to true. **/
12 sent: boolean
13}
14

Svaki unos u listi badges ima sledeću strukturu. Pogledajte vodič za Badges za tipove bedževa.

Objekat Webhook Badge
Copy CopyRun External Link
1
2interface CommentUserBadgeInfo {
3 /** The id of the badge awarded to this user. **/
4 id: string
5 /** The badge type. **/
6 type: number
7 /** The badge description, shown when hovering over the badge. **/
8 description: string
9 /** The text shown on the badge. **/
10 displayLabel?: string | null
11 /** The image shown for the badge, if it uses one. **/
12 displaySrc?: string | null
13 backgroundColor?: string | null
14 borderColor?: string | null
15 textColor?: string | null
16 /** An extra CSS class applied to the badge. **/
17 cssClass?: string | null
18}
19

HTTP metode

Možete konfigurisati HTTP metodu za svaki tip webhook događaja u admin panelu:

  • Create Event: POST ili PUT (podrazumevano: PUT)
  • Update Event: POST ili PUT (podrazumevano: PUT)
  • Delete Event: DELETE, POST ili PUT (podrazumevano: DELETE)

Pošto svi zahtevi sadrže ID, Create i Update operacije su idempotentne po podrazumevanoj postavci (PUT). Ponavljanje istog Create ili Update zahteva ne bi trebalo da kreira duplirane objekte na vašoj strani.

Zaglavlja zahteva

Svaki webhook zahtev uključuje sledeća zaglavlja:

HeaderDescription
Content-Typeapplication/json
tokenYour API Secret
X-FastComments-TimestampUnix timestamp (seconds) when the request was signed
X-FastComments-SignatureHMAC-SHA256 signature (sha256=<hex>)

Pogledajte Bezbednost i API tokeni za informacije o verifikaciji HMAC potpisa.

Bezbednost i API tokeni Internal Link

FastComments webhook zahtevi uključuju više mehanizama autentifikacije radi bezbednosti.

Zaglavlja koja se šalju

ZaglavljeOpis
tokenVaš API Secret (za unazadnu kompatibilnost)
X-FastComments-TimestampUnix timestamp (sekunde) kada je zahtev potpisan
X-FastComments-SignatureHMAC-SHA256 potpis payload-a

Verifikacija HMAC potpisa (Preporučeno)

Toplo preporučujemo verifikaciju HMAC potpisa kako biste osigurali da su webhook payload-ovi autentični i da nisu izmenjeni.

Format potpisa: sha256=<hex-encoded-signature>

Kako se potpis izračunava:

  1. Sastavite: timestamp + "." + JSON_payload_body
  2. Izračunajte HMAC-SHA256 koristeći vaš API Secret kao ključ
  3. Hex-enkodirajte rezultat

Primer verifikacije (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;
    }

    // Proverite da je timestamp recentan (u roku od 5 minuta)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Prevencija replay napada
    }

    // Proverite potpis
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

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

Primer verifikacije (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

    # Proverite da je timestamp recentan
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Proverite potpis
    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}"

Primer verifikacije (PHP)

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

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

    // Proverite da je timestamp recentan (u roku od 5 minuta)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // Proverite potpis
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Nasleđena autentifikacija

Zaglavlje token koje sadrži vaš API Secret se i dalje šalje za unazadnu kompatibilnost. Međutim, preporučujemo migraciju na HMAC verifikaciju za poboljšanu bezbednost, jer štiti od replay napada.

Upravljanje webhook-ovima putem API-ja Internal Link

Webhooks se takođe mogu upravljati putem REST API-ja. Ovo je način na koji integracije poput Zapiera pretplaćuju na događaje komentara bez korišćenja kontrolne table, i prati obrazac REST Hooks: pretplata, primanje događaja, otkazivanje pretplate.

API pretplate postoje uz webhooks konfigurirane u kontrolnoj tabli. Događaj komentara se isporučuje svakom webhooku koji odgovara njegovom domenu, svaki kao zasebna isporuka, bez obzira kako je webhook kreiran.

Autentifikacija

Svaki zahtev zahteva vaš API ključ u zaglavlju x-api-key (ili u parametru upita API_KEY) i ID vašeg zakupca u parametru upita tenantId. Obe vrednosti su prikazane na stranici API tajne u kontrolnoj tabli.

Pretplata

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"
}
PoljeObaveznoOpis
urlYesApsolutni http ili https URL.
eventYescomment-created, comment-updated or comment-deleted.
domainNoDomena iz konfiguracije vašeg naloga. Podrazumevano je *, što prima događaje za svaki domen.
methodNoPOST (default), PUT or DELETE.

Odgovor sadrži pretplatu:

{
    "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"
    }
}

Ponovno pretplata na isti URL za isti događaj i domen vraća postojeću pretplatu umesto kreiranja duplikata, tako da klijent može bezbedno ponoviti zahtev. Svaki zakupac može imati može do 50 API pretplata.

Lista

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

Vraća sve webhookove za zakupca, uključujući i one upravljane u kontrolnoj tabli ("source": "dashboard"). Filtrirajte po event, domain ili source.

Otkaži pretplatu

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

Brisanje pretplate takođe odbacuje sve događaje koji su još u redu za nju. Samo pretplate kreirane putem API-ja mogu se izbrisati na ovaj način; webhook iz kontrolne table, ili ID koji ne postoji na vašem nalogu, odgovara sa 404 i kodom not-found. Webhookovi iz kontrolne table se uređuju na stranici Webhooks.

Payload-ovi i potpisivanje

Isporuke koriste isti payload kao webhookovi iz kontrolne table (pogledajte Data Structures) i potpisane su istim HMAC šemom (pogledajte Security & API Tokens). API pretplate nikada ne primaju zastarelo zaglavlje token, pa proverite zaglavlje X-FastComments-Signature.

Primeri payload-ova

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

Vraća najnovije komentare naloga u tačno onom obliku koji isporuka nosi, tako da integracija može prikazati stvarne uzorke podataka pre nego što prvi događaj stigne. event je opcionalan i samo se validira, pošto svaki događaj isporučuje isti objekat komentara. limit podrazumevano je 3 i prihvata vrednosti od 1 do 10. Troši 2 API kredita.

{
    "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
        }
    ]
}

Odgovor sa 410 Gone

Ako endpoint API pretplate odgovori HTTP 410 Gone, FastComments to tretira kao otkazivanje pretplate: pretplata se briše zajedno sa svojim događajima u redu, i ne pokušavaju se dalje isporuke. Webhookovi konfigurirani u kontrolnoj tabli se nikada ne brišu automatski; za njih je 410 običan neuspeh. Svaki drugi status greške se ponovo pokušava i na kraju onemogućava webhook, kako je opisano u sekciji How it Works & Handling Retries.

Kontrolna tabla

API pretplate se pojavljuju u listi Webhookova sa izvorom API, gde administrator može da ih uređuje, onemogući, ponovo omogući ili obriše.

Zaključno

Ovim se završava naša Webhooks dokumentacija.

Nadamo se da ćete smatrati da je FastComments Webhook integracija jednostavna za razumevanje i brza za postavljanje.

Ako smatrate da ste uočili neke nedostatke u našoj dokumentaciji, obavestite nas u nastavku.