FastComments.com

Webhooks

Са FastComments-ом могуће је позвати API endpoint кад год се коментар дода, ажурира или уклони из нашег система.

Ово остварујемо помоћу асинхроних webhooks преко HTTP/HTTPS.

Šta su webhook-ovi Internal Link

Webhook је механизам, или интеграција, између два система где "произвођач" (FastComments) покреће догађај који "потрошач" (Ви) прима путем API позива.

Podržani događaji i resursi Internal Link

FastComments подржава вебхук‑ове само за ресурс Коментар.

Подржавамо вебхук‑ове за креирање коментара, брисање и ажурирање.

Сваки од ових се сматра посебним догађајем у нашем систему и због тога има различиту семантику и структуре за вебхук догађаје.

Било који број крајњих тачака може да се претплати на исти догађај, преко контролне табле или преко API‑ја (погледајте Управљање вебхук‑овима преко API‑ја). Сваки вебхук се испоручује независно.

Testiranje Internal Link

Нове и странице за уређивање веб‑хукова имају дугме Send Test Payload које шаље захтев на URL који је тренутно у формулару, без обзира да ли је сачуван. Догађаји Create и Update шаљу фиктивни WebhookComment објекат, док тестирање Delete шаље фиктивно тело захтева са само ID‑јем.

Верификација Подаци

При тестирању интеграције вашег веб‑хука, проверите да долазни захтеви садрже следећа заглавља:

  1. X-FastComments-Timestamp – Unix временска ознака (секунде)
  2. X-FastComments-Signature – HMAC‑SHA256 потпис

Веб‑хукеви креирани пре увођења шеме потписа такође добијају заглавље token које садржи ваш API тајни кључ. Нови веб‑хукеви то не раде.

Користите верификацију HMAC потписа да бисте осигурали да су подаци аутентични.

Алати за тестирање

Можете користити алате као што су webhook.site или ngrok за преглед долазних веб‑хук података током развоја.

Типови Догађаја

  • Create Event: Окида се када се креира нови коментар.
  • Update Event: Окида се када се коментар уреди.
  • Delete Event: Окида се када се коментар избрише.

Сваки веб‑хук је повезан са једним догађајем и једном HTTP методом (POST, PUT или DELETE). Сваки догађај укључује пуне податке о коментару у телу захтева (погледајте Data Structures за формат података).

Strukture podataka Internal Link

Једина структура која се шаље путем вебхукова је објекат WebhookComment, приказан у TypeScript-у испод.

Структура објекта WebhookComment

Структура догађаја „Create"

Тело захтева за догађај „create" је објекат WebhookComment.

Структура догађаја „Update"

Тело захтева за догађај „update" је објекат WebhookComment.

Структура догађаја „Delete"

Тело захтева за догађај „delete" је објекат WebhookComment.

Промена од 14. новембра 2023.
Раније је тело захтева за догађај „delete" садржало само id коментара. Сада садржи цео коментар у тренутку брисања.

Сваки кључ је увек присутан у телу. Када коментар нема вредност за неко поље, тело носи null (или false за логичке вредности и [] за листе), тако да облик испоручене поруке никада не варира од коментара до коментара.

Објекат 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

Када су корисници означени у коментару, информација се чува у листи под називом mentions. Сваки објекат у тој листи има следећу структуру.

Објекат 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

Сваки унос у листи badges има следећу структуру. Погледајте водич за значке за типове значки.

Објекат 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 методе

Можете конфигурисати HTTP метод за сваки тип вебхук догађаја у админ панелу:

  • Create Event: POST или PUT (подразумевано: PUT)
  • Update Event: POST или PUT (подразумевано: PUT)
  • Delete Event: DELETE, POST или PUT (подразумевано: DELETE)

Пошто сви захтеви садрже ID, операције Create и Update су подразумевано идемпотентне (PUT). Поновљање истог Create или Update захтева не би требало да креира дупле објекте на вашој страни.

Заглавља захтева

Сваки вебхук захтев укључује следећа заглавља:

ЗаглављеОпис
Content-Typeapplication/json
tokenВаша API тајна
X-FastComments-TimestampUnix временски печат (секунде) када је захтев потписан
X-FastComments-SignatureHMAC-SHA256 потпис (sha256=<hex>)

Погледајте Безбедност и API токени за информације о верификацији HMAC потписа.

Bezbednost i API tokeni Internal Link

FastComments webhook захтеви укључују више механизама аутентификације ради безбедности.

Заглавља која се шаљу

ЗаглављеОпис
tokenВаш API Secret (ради уназадне компатибилности)
X-FastComments-TimestampUnix временска ознака (у секундама) када је захтев потписан
X-FastComments-SignatureHMAC-SHA256 потпис payload-а

Верификација HMAC потписа (Препоручено)

Снажно препоручујемо верификацију HMAC потписа како бисте били сигурни да су webhook payload-ови аутентични и да нису измењени.

Формат потписа: sha256=<hex-encoded-signature>

Како се потпис израчунава:

  1. Конкатенирајте: timestamp + "." + JSON_payload_body
  2. Израчунајте HMAC-SHA256 користећи ваш API Secret као кључ
  3. Хекс-енкодирајте резултат

Пример верификације (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;
    }

    // Проверите да ли је временска ознака свежа (у року од 5 минута)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Превенција replay напада
    }

    // Проверите потпис
    const payload = JSON.stringify(req.body);
    const expectedSignature = crypto
        .createHmac('sha256', apiSecret)
        .update(`${timestamp}.${payload}`)
        .digest('hex');

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

Пример верификације (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

    # Проверите да ли је временска ознака свежа
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Проверите потпис
    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}"

Пример верификације (PHP)

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

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

    // Проверите да ли је временска ознака свежа (у року од 5 минута)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

    // Проверите потпис
    $payload = json_encode($body, JSON_UNESCAPED_SLASHES);
    $message = $timestamp . '.' . $payload;
    $expectedSignature = 'sha256=' . hash_hmac('sha256', $message, $apiSecret);

    return hash_equals($expectedSignature, $signature);
}

Наслеђена аутентификација

Заглавље token које садржи ваш API Secret и даље се шаље ради уназадне компатибилности. Међутим, препоручујемо прелазак на HMAC верификацију због побољшане безбедности јер штити од replay напада.

Upravljanje webhook-ovima putem API-ja Internal Link

Webhooks такође могу да се управљају преко REST API‑ја. Ово је начин на који интеграције попут Zapier‑а претплаћу се на догађаје коментара без коришћења контролне табле, и прати шаблон REST Hooks: претплата, примање догађаја, одјава.

API претплате постоје паралелно са вебхук‑овима подешеним у контролној табли. Догађај коментара се испоручује сваком вебхуку који одговара његовом домену, сваки као посебна испорука, без обзира како је вебхук креиран.

Аутентификација

Сваки захтев захтева ваш API кључ у заглављу x-api-key (или у параметру упита API_KEY) и ваш tenant ID у параметру упита tenantId. Оба су приказана на страници API Secret у контролној табли.

Претплата

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"
}
ПољеОбавезноОпис
urlYesАпсолутни http или https URL.
eventYescomment-created, comment-updated or comment-deleted.
domainNoДомен из конфигурације вашег налога. Подразумевано је *, који прима догађаје за сваки домен.
methodNoPOST (default), PUT or DELETE.

Одговор садржи претплату:

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

Претплата истог URL‑а на исти догађај и домен поново враћа постојећу претплату уместо креирања дупликата, тако да клијент може безбедно поново покушати. Сваки закупац може имати до 50 API претплата.

Листа

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

Враћа све вебхук‑ове за закупца, укључујући оне управљане у контролној табли ("source": "dashboard"). Филтрирајте помоћу event, domain или source.

Одјава

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

Брисање претплате такође одбацује све догађаје који су још у реду за њу. Само претплате креиране преко API‑ја могу се брисати на овај начин; вебхук из контролне табле, или ID који не постоји у вашем налогу, одговара са 404 и кодом not-found. Вебхук‑ови из контролне табле се уређују на страници Webhooks.

Тела захтева и потписивање

Испоруке користе исти payload као вебхук‑ови из контролне табле (види Data Structures) и потписане су истим HMAC шемом (види Security & API Tokens). API претплате никада не примају наследни token заглавље, па проверите X-FastComments-Signature заглавље уместо тога.

Пример тела захтева

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

Враћа најновије коментаре налога у тачно истом облику у коме их испорука носи, тако да интеграција може приказати прави пример података пре него што стигне први догађај. event је опционо и само се верификује, јер сваки догађај испоручује исти објекат коментара. limit подразумевано је 3 и прихвата вредности од 1 до 10. Потрошња је 2 API кредита.

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

Ако крајња тачка API претплате одговори HTTP статусом 410 Gone, FastComments то сматра одјавом: претплата се брише заједно са својим догађајима у реду, и даље се не покушавају испоруке. Вебхук‑ови подешени у контролној табли се никада аутоматски не бришу; за њих 410 представља уобичајени неуспех. Сваки други статус неуспеха се поново покушава и на крају онемогућава вебхук, као што је описано у How it Works & Handling Retries.

Контролна табла

API претплате се појављују у листи Webhooks са извором API, где администратор може да их уреди, онемогући, поново омогући или избрише.

У закључку

Овим се завршава наша Webhooks документација.

Надамо се да ће вам интеграција FastComments Webhook бити лака за разумевање и брза за подешавање.

Ако сматрате да сте пронашли било какве недостатке у нашој документацији, јавите нам у наставку.