FastComments.com

Вебхуки

За допомогою FastComments можна викликати кінцеву точку API щоразу, коли коментар додається, оновлюється або видаляється з нашої системи.

Ми реалізуємо це за допомогою асинхронних вебхуків через HTTP/HTTPS.

Що таке вебхуки Internal Link

Вебхук — це механізм або інтеграція між двома системами, де "виробник" (FastComments) ініціює подію яку "споживач" (Ви) обробляє через виклик API.

Підтримувані події та ресурси Internal Link

FastComments підтримує вебхуки лише для ресурсу Comment.

Ми підтримуємо вебхуки для створення, видалення та оновлення коментарів.

Кожен з цих випадків розглядається як окрема подія у нашій системі, і тому має різну семантику та структуру вебхук‑подій.

Будь-яка кількість кінцевих точок може підписатися на одну й ту ж подію, з панелі керування або через API (див. Управління вебхуками через API). Кожен вебхук доставляється незалежно.

Тестування Internal Link

На сторінках створення та редагування вебхуків є кнопка Send Test Payload, яка надсилає запит на URL, який наразі вказано у формі, незалежно від того, чи було його збережено. Події Create та Update надсилають тестовий об'єкт WebhookComment, а тестування Delete надсилає тестове тіло запиту лише з ID.

Перевірка Payload-ів

Під час тестування інтеграції вебхуків переконайтеся, що вхідні запити містять такі заголовки:

  1. X-FastComments-Timestamp - Unix-мітка часу (секунди)
  2. X-FastComments-Signature - підпис HMAC-SHA256

Вебхуки, створені до впровадження схеми підписів, також отримують заголовок token, що містить ваш API Secret. Нові вебхуки — ні.

Використовуйте перевірку підпису HMAC, щоб переконатися, що payload-и автентичні.

Інструменти тестування

Для перегляду вхідних payload-ів вебхуків під час розробки можна використовувати такі інструменти, як webhook.site або ngrok.

Типи подій

  • Подія Create: спрацьовує, коли створюється новий коментар.
  • Подія Update: спрацьовує, коли коментар редагується.
  • Подія Delete: спрацьовує, коли коментар видаляється.

Кожен вебхук прив'язаний до однієї події та одного HTTP-методу (POST, PUT або DELETE). Кожна подія містить повні дані коментаря в тілі запиту (див. Структури даних для формату payload-а).

Структури даних 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 /** Ідентифікатор коментаря. **/
4 id: string
5 /** Ідентифікатор або URL, що ідентифікує гілку коментарів. Нормалізовано. **/
6 urlId: string
7 /** URL, що вказує на місце, де було залишено коментар. **/
8 url: string | null
9 /** Ідентифікатор користувача, який залишив коментар. Для SSO — з префіксом tenant id. **/
10 userId: string | null
11 /** Email користувача, який залишив коментар. **/
12 commenterEmail: string | null
13 /** Ім'я користувача, що відображається у віджеті коментарів. Для SSO може бути displayName. **/
14 commenterName: string
15 /** Необроблений текст коментаря. **/
16 comment: string
17 /** Текст коментаря після обробки. **/
18 commentHTML: string
19 /** Зовнішній ідентифікатор коментаря. **/
20 externalId: string | null
21 /** Ідентифікатор батьківського коментаря. **/
22 parentId: string | null
23 /** UTC-дата, коли було залишено коментар. **/
24 date: UTC_ISO_DateString
25 /** Сумарна карма (up - down) голосів. **/
26 votes: number
27 votesUp: number
28 votesDown: number
29 /** True, якщо користувач був авторизований під час коментування, або верифікував коментар, або верифікував свою сесію, коли коментар було залишено. **/
30 verified: boolean
31 /** UTC-дата верифікації коментаря. **/
32 verifiedDate: UTC_ISO_DateString | null
33 /** Чи позначив модератор коментар як перевірений. **/
34 reviewed: boolean
35 /** Розташування або base64-кодування аватара. Base64 — лише якщо таке значення було передано через SSO. **/
36 avatarSrc: string | null
37 /** Чи було коментар вручну або автоматично позначено як спам? **/
38 isSpam: boolean
39 /** Чи було коментар автоматично позначено як спам? **/
40 aiDeterminedSpam: boolean
41 /** Чи є в коментарі зображення? **/
42 hasImages: boolean
43 /** Номер сторінки, на якій знаходиться коментар, для сортування "Most Relevant". **/
44 pageNumber: number | null
45 /** Номер сторінки, на якій знаходиться коментар, для сортування "Oldest First". **/
46 pageNumberOF: number | null
47 /** Номер сторінки, на якій знаходиться коментар, для сортування "Newest First". **/
48 pageNumberNF: number | null
49 /** Чи було коментар схвалено автоматично чи вручну? **/
50 approved: boolean
51 /** Код локалі (формат: en_us) користувача на момент написання коментаря. **/
52 locale: string | null
53 /** @mentions, написані в коментарі, які було успішно розпізнано. Порожньо, якщо їх немає. **/
54 mentions: CommentUserMention[]
55 /** Домен, з якого надійшов коментар. **/
56 domain: string | null
57 /** Ідентифікатори груп модерації, пов'язані з цим коментарем. Порожньо, якщо їх немає. **/
58 moderationGroupIds: string[]
59 /** Значки, що відображаються поруч з ім'ям коментатора в цьому коментарі, станом на момент створення події. Порожньо, якщо їх немає. **/
60 badges: CommentUserBadgeInfo[]
61}
62

Коли користувачів згадують у коментарі, інформація зберігається у списку під назвою mentions. Кожен об'єкт у цьому списку має таку структуру.

Об'єкт згадок вебхука
Copy CopyRun External Link
1
2interface CommentUserMention {
3 /** Ідентифікатор користувача. Для SSO-користувачів він містить префікс з вашим tenant id. **/
4 id: string
5 /** Кінцевий текст тега @mention, включно з символом @. **/
6 tag: string
7 /** Оригінальний текст тега @mention, включно з символом @. **/
8 rawTag: string
9 /** Тип згаданого користувача. user = акаунт FastComments.com. sso = SSOUser. **/
10 type: 'user'|'sso'
11 /** Якщо користувач відмовився від сповіщень, це значення все одно буде true. **/
12 sent: boolean
13}
14

Кожен елемент списку badges має таку структуру. Типи значків дивіться в посібнику зі значками.

Об'єкт значка вебхука
Copy CopyRun External Link
1
2interface CommentUserBadgeInfo {
3 /** Ідентифікатор значка, наданого цьому користувачу. **/
4 id: string
5 /** Тип значка. **/
6 type: number
7 /** Опис значка, що відображається при наведенні курсора. **/
8 description: string
9 /** Текст, що відображається на значку. **/
10 displayLabel?: string | null
11 /** Зображення значка, якщо воно використовується. **/
12 displaySrc?: string | null
13 backgroundColor?: string | null
14 borderColor?: string | null
15 textColor?: string | null
16 /** Додатковий CSS-клас, застосований до значка. **/
17 cssClass?: string | null
18}
19

HTTP-методи

Ви можете налаштувати HTTP-метод для кожного типу події вебхука в адмін-панелі:

  • Подія Create: POST або PUT (за замовчуванням: PUT)
  • Подія Update: POST або PUT (за замовчуванням: PUT)
  • Подія Delete: DELETE, POST або PUT (за замовчуванням: DELETE)

Оскільки всі запити містять ID, операції Create та Update є ідемпотентними за замовчуванням (PUT). Повторення того самого запиту Create або Update не повинно створювати дублікати об'єктів на вашому боці.

Заголовки запиту

Кожен запит вебхука містить такі заголовки:

ЗаголовокОпис
Content-Typeapplication/json
tokenВаш API Secret
X-FastComments-TimestampUnix-мітка часу (у секундах), коли запит було підписано
X-FastComments-SignatureПідпис HMAC-SHA256 (sha256=<hex>)

Інформацію про перевірку підпису HMAC дивіться в розділі Безпека та API-токени.

Безпека та токени API Internal Link

FastComments webhook requests include multiple authentication mechanisms for security.

Відправлені заголовки

ЗаголовокОпис
tokenВаш API Secret (для зворотної сумісності)
X-FastComments-TimestampUnix-часова мітка (секунди) коли запит був підписаний
X-FastComments-SignatureHMAC-SHA256 підпис навантаження

Перевірка підпису HMAC (рекомендовано)

Ми настійно рекомендуємо перевіряти підпис HMAC, щоб переконатися, що навантаження вебхука є автентичними і не були підроблені.

Формат підпису: 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;  // Запобігання повторній атаці
    }

    // Перевірити підпис
    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 для підвищеної безпеки, оскільки вона захищає від повторних атак.

Керування вебхуками через API Internal Link

Вебхуки також можна керувати через REST API. Саме так інтеграції, як-от Zapier, підписуються на події коментарів, не торкаючись панелі керування, і це відповідає шаблону REST Hooks: підписка, отримання подій, відписка.

Підписки через API живуть поруч з вебхуками, налаштованими в панелі керування. Подія коментаря доставляється кожному вебхуку, що відповідає її домену, кожен як окрема доставка, незалежно від того, як було створено вебхук.

Автентифікація

Кожен запит потребує ваш API Key у заголовку 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"
}
ПолеОбов'язковеОпис
urlТакАбсолютна URL-адреса http або https.
eventТакcomment-created, comment-updated або comment-deleted.
domainНіДомен з конфігурації вашого облікового запису. За замовчуванням *, що отримує події для кожного домену.
methodНіPOST (за замовчуванням), PUT або 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 на ту саму подію та домен повертає наявну підписку, а не створює дублікат, тому клієнт може безпечно повторювати запит. Кожен tenant може мати до 50 підписок через API.

Список

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

Повертає всі вебхуки для tenant, включно з тими, що керуються в панелі керування ("source": "dashboard"). Фільтруйте за event, domain або source.

Відписка

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

Видалення підписки також відкидає будь-які події, які ще очікують у черзі для неї. Лише підписки, створені через API, можна видалити таким чином; вебхук з панелі керування або id, якого не існує у вашому обліковому записі, відповідає 404 з кодом not-found. Вебхуки панелі керування редагуються на сторінці Webhooks.

Корисні навантаження та підпис

Доставки використовують те саме корисне навантаження, що й вебхуки панелі керування (див. 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 є зрозумілою та швидкою у налаштуванні.

Якщо ви вважаєте, що виявили будь-які прогалини в нашій документації, повідомте нас нижче.