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

The new and edit webhook pages have a Send Test Payload button that sends a request to the URL currently in the form, whether or not it has been saved. The Create and Update events send a dummy WebhookComment object, while testing Delete will send a dummy request body with just an ID.

Verifikacija payload‑ova

Kada testirate vašu webhook integraciju, proverite da dolazni zahtevi sadrže sledeća 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 rade.

Koristite verifikaciju HMAC potpisa da biste osigurali da su payload‑ovi autentični.

Alati za testiranje

Možete koristiti alate poput webhook.site ili ngrok da pregledate dolazne webhook payload‑ove tokom razvoja.

Tipovi događaja

  • Create Event: Pokreće se kada se kreira novi komentar.
  • Update Event: Pokreće se kada se komentar izmeni.
  • Delete Event: Pokreće 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 telu zahteva (pogledajte Data Structures za format payload‑a).

Strukture podataka Internal Link

The only structure sent via webhooks is the WebhookComment object, outlined in TypeScript below.

Struktura objekta WebhookComment

Struktura događaja „Create“

The "create" event request body is a WebhookComment object.

Struktura događaja „Update“

The "update" event request body is a WebhookComment object.

Struktura događaja „Delete“

The "delete" event request body is a WebhookComment object.

Izmena od 14. novembra 2023.
Prethodno je telo zahteva za događaj „delete“ 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 logičke vrednosti i [] za liste), tako da oblik isporuke nikada ne varira od jednog komentara do drugog.

Objekat WebhookComment
Copy CopyRun External Link
1
2interface WebhookComment {
3 /** ID komentara. **/
4 id: string
5 /** ID ili URL koji identifikuje nit komentara. Normalizovano. **/
6 urlId: string
7 /** URL koji pokazuje gde je komentar ostavljen. **/
8 url: string | null
9 /** ID korisnika koji je ostavio komentar. Ako je SSO, prefiks je ID zakupca. **/
10 userId: string | null
11 /** Email korisnika koji je ostavio komentar. **/
12 commenterEmail: string | null
13 /** Ime korisnika koje se prikazuje u vidžetu za komentar. Sa SSO, može biti displayName. **/
14 commenterName: string
15 /** Sirov tekst komentara. **/
16 comment: string
17 /** Tekst komentara nakon parsiranja. **/
18 commentHTML: string
19 /** Eksterni ID komentara. **/
20 externalId: string | null
21 /** ID nadređenog komentara. **/
22 parentId: string | null
23 /** UTC datum kada je komentar ostavljen. **/
24 date: UTC_ISO_DateString
25 /** Kombinovani karma (glasovi gore - dole). **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** Istina ako je korisnik bio prijavljen kada je komentarisao, ili je verifikovao komentar, ili je verifikovao sesiju kada je komentar ostavljen. **/
30 verified: boolean
31 /** UTC datum kada je komentar verifikovan. **/
32 verifiedDate: UTC_ISO_DateString | null
33 /** Ako je moderator označio komentar kao pregledan. **/
34 reviewed: boolean
35 /** Lokacija ili base64 kodiranje avatara. Biće base64 samo ako je to vrednost prosleđena sa SSO. **/
36 avatarSrc: string | null
37 /** Da li je komentar ručno ili automatski označen kao spam? **/
38 isSpam: boolean
39 /** Da li je komentar automatski označen kao spam? **/
40 aiDeterminedSpam: boolean
41 /** Da li u komentaru postoje slike? **/
42 hasImages: boolean
43 /** Broj stranice na kojoj se komentar nalazi za sortiranje „Najrelevantnije“. **/
44 pageNumber: number | null
45 /** Broj stranice na kojoj se komentar nalazi za sortiranje „Najstariji prvi“. **/
46 pageNumberOF: number | null
47 /** Broj stranice na kojoj se komentar nalazi za sortiranje „Najnoviji prvi“. **/
48 pageNumberNF: number | null
49 /** Da li je komentar odobren automatski ili ručno? **/
50 approved: boolean
51 /** Kod lokalizacije (format: en_us) korisnika kada je komentar napisan. **/
52 locale: string | null
53 /** @pomeni napisani u komentaru koji su uspešno parsirani. Prazno kada ih nema. **/
54 mentions: CommentUserMention[]
55 /** Domen iz kojeg je komentar. **/
56 domain: string | null
57 /** ID‑ovi grupa moderacije povezani sa ovim komentarom. Prazno kada ih nema. **/
58 moderationGroupIds: string[]
59}
60

When users are tagged in a comment, the information is stored in a list called mentions. Each object in that list has the following structure.

Objekat Webhook Mentions
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** ID korisnika. Za SSO korisnike, biće prefiksiran ID vašeg zakupca. **/
4 id: string
5 /** Konačni tekst @mention taga, uključujući @ simbol. **/
6 tag: string
7 /** Originalni tekst @mention taga, uključujući @ simbol. **/
8 rawTag: string
9 /** Koji tip korisnika je označen. user = FastComments.com nalog. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Ako se korisnik odjavi od obaveštenja, ovo će i dalje biti postavljeno na true. **/
12 sent: boolean
13}
14

HTTP Metode

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

  • Create događaj: POST ili PUT (podrazumevano: PUT)
  • Update događaj: POST ili PUT (podrazumevano: PUT)
  • Delete događaj: DELETE, POST ili PUT (podrazumevano: DELETE)

Pošto svi zahtevi sadrže ID, operacije Create i Update su po podrazumevanju idempotentne (PUT). Ponovljeni isti Create ili Update zahtev ne bi trebalo da kreira duple objekte na vašoj strani.

Zaglavlja zahteva

Svaki webhook zahtev uključuje sledeća zaglavlja:

ZaglavljeOpis
Content-Typeapplication/json
tokenVaša API tajna
X-FastComments-TimestampUnix vremenski žig (sekunde) kada je zahtev potpisan
X-FastComments-SignatureHMAC-SHA256 potpis (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.