FastComments.com

ווב-הוקים

עם FastComments ניתן לקרוא לנקודת קצה של API בכל פעם שתגובה מתווספת, מתעדכנת או נמחקת מהמערכת שלנו.

אנו מממשים זאת באמצעות webhooks אסינכרוניים על גבי HTTP/HTTPS.

מהם ווב-הוקים Internal Link

Webhook הוא מנגנון, או אינטגרציה, בין שתי מערכות שבה ה"מפיק" (FastComments) שולח אירוע שה"צרכן" (אתה) צורך באמצעות קריאת API.

אירועים ומשאבים נתמכים Internal Link

FastComments תומך ב-webhooks עבור משאב ה-Comment בלבד.

אנו תומכים ב-webhooks ליצירת תגובה, הסרה, ולעדכון.

כל אחד מאלה נחשב לאירוע נפרד במערכת שלנו ולכן יש לו סמנטיקה ומבנים שונים עבור אירועי ה-webhook.

כל מספר של נקודות קצה יכול להירשם לאותו אירוע, מהלוח המחוונים או דרך ה-API (see Managing Webhooks via the API). כל webhook נמסר באופן עצמאי.

בדיקה Internal Link

הדפים החדשים ועמודי עריכת ה-webhook כוללים כפתור Send Test Payload ששולח בקשה לכתובת ה-URL הנוכחית בטופס, בין אם נשמרה ובין אם לא. אירועי ה-Create וה-Update שולחים אובייקט WebhookComment דמה, בעוד שבדיקת Delete תשלח גוף בקשה דמה הכולל רק מזהה (ID).

אימות Payloads

בעת בדיקת אינטגרציית ה-webhook שלכם, ודאו שהבקשות הנכנסות כוללות את הכותרות הבאות:

  1. X-FastComments-Timestamp - חותמת זמן Unix (שניות)
  2. X-FastComments-Signature - חתימת HMAC-SHA256

Webhooks שנוצרו לפני הצגת סכמת החתימה מקבלים גם כותרת token המכילה את ה-API Secret שלכם. Webhooks חדשים לא.

השתמשו באימות חתימת ה-HMAC כדי לוודא שה-payloads אמיתיים.

כלי בדיקה

ניתן להשתמש בכלים כמו webhook.site או ngrok לבחינת payloads נכנסים של webhook במהלך הפיתוח.

סוגי אירועים

  • אירוע Create: מופעל כאשר נוצרת תגובה חדשה.
  • אירוע Update: מופעל כאשר תגובה נערכת.
  • אירוע Delete: מופעל כאשר תגובה נמחקת.

כל webhook קשור לאירוע אחד ולשיטת HTTP אחת (POST, PUT או DELETE). כל אירוע כולל את נתוני התגובה המלאים בגוף הבקשה (ראו מבני נתונים לפורמט ה-payload).

מבני נתונים Internal Link

המבנה היחיד שנשלח באמצעות webhooks הוא אובייקט 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. לכל אובייקט ברשימה זו יש את המבנה הבא.

אובייקט ה-Mentions של ה-Webhook
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 יש את המבנה הבא. ראו את מדריך ה-Badges לסוגי התגים.

אובייקט ה-Badge של ה-Webhook
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 עבור כל סוג אירוע webhook בלוח הניהול:

  • אירוע Create: POST או PUT (ברירת מחדל: PUT)
  • אירוע Update: POST או PUT (ברירת מחדל: PUT)
  • אירוע Delete: DELETE, POST, או PUT (ברירת מחדל: DELETE)

מכיוון שכל הבקשות מכילות מזהה, פעולות ה-Create וה-Update הן אידמפוטנטיות כברירת מחדל (PUT). חזרה על אותה בקשת Create או Update לא אמורה ליצור אובייקטים כפולים בצד שלכם.

כותרות בקשה

כל בקשת webhook כוללת את הכותרות הבאות:

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

ראו אבטחה וטוקני API למידע על אימות חתימת ה-HMAC.

אבטחה וטוקני API Internal Link

בקשות webhook של FastComments כוללות מספר מנגנוני אימות לצורך אבטחה.

Headers שנשלחים

Headerתיאור
tokenה-API Secret שלך (לתאימות לאחור)
X-FastComments-Timestampחותמת זמן Unix (שניות) שבה הבקשה נחתמה
X-FastComments-Signatureחתימת HMAC-SHA256 של ה-payload

אימות חתימת HMAC (מומלץ)

אנו ממליצים בחום לאמת את חתימת ה-HMAC כדי לוודא ש-payloads של webhook הם אותנטיים ולא הושחתו.

פורמט החתימה: sha256=<hex-encoded-signature>

כיצד החתימה מחושבת:

  1. שרשור: timestamp + "." + JSON_payload_body
  2. חישוב HMAC-SHA256 תוך שימוש ב-API Secret שלך כמפתח
  3. קידוד התוצאה ב-hex

דוגמת אימות (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;
    }

    // Verify timestamp is recent (within 5 minutes)
    const now = Math.floor(Date.now() / 1000);
    if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
        return false;  // Replay attack prevention
    }

    // Verify signature
    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

    # Verify timestamp is recent
    now = int(time.time())
    if abs(now - int(timestamp)) > 300:
        return False

    # Verify signature
    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;
    }

    // Verify timestamp is recent (within 5 minutes)
    $now = time();
    if (abs($now - intval($timestamp)) > 300) {
        return false;
    }

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

    return hash_equals($expectedSignature, $signature);
}

אימות מדור קודם

ה-header של token המכיל את ה-API Secret שלך עדיין נשלח לצורך תאימות לאחור. עם זאת, אנו ממליצים לעבור לאימות HMAC לשיפור האבטחה, מכיוון שהוא מגן מפני התקפות שידור חוזר (replay attacks).

ניהול ווב-הוקים דרך ה-API Internal Link

ניתן לנהל Webhooks גם דרך ה-REST API. כך מתממשקויות כמו Zapier נרשמות לאירועי תגובות מבלי לגעת בלוח הבקרה, והדבר עוקב אחר תבנית REST Hooks: הרשמה, קבלת אירועים, ביטול הרשמה.

מנויי API חיים לצד ה-webhooks המוגדרים בלוח הבקרה. אירוע תגובה נשלח לכל webhook שתואם לדומיין שלו, כל אחד כמשלוח נפרד, באשר דרך שנוצר ה-webhook.

אימות

כל בקשה דורשת את מפתח ה-API שלך בכותרת x-api-key (או בפרמטר השאילתה API_KEY) ואת מזהה ה-tenant שלך בפרמטר השאילתה 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

מחזיר כל webhook עבור ה-tenant, כולל אלה המנוהלים בלוח הבקרה ("source": "dashboard"). ניתן לסנן לפי event, domain או source.

ביטול הרשמה

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

מחיקת מנוי משליכה גם את כל האירועים שעדיין ממתינים בתור עבורו. רק מנויים שנוצרו דרך ה-API ניתנים למחיקה בדרך זו; webhook של לוח בקרה, או מזהה שאינו קיים בחשבונך, מחזירים 404 עם קוד not-found. Webhooks של לוח הבקרה נערכים בדף Webhooks.

מטענים וחתימה

משלוחים משתמשים באותו מטען כמו 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 מתייחס לכך כביטול הרשמה: המנוי נמחק יחד עם האירועים הממתינים בתור שלו, ולא מנסים משלוחים נוספים. Webhooks המוגדרים בלוח הבקרה לעולם לא נמחקים אוטומטית; עבורם 410 הוא כישלון רגיל. כל סטטוס כישלון אחר מנוסה שוב ובסופו של דבר משבית את ה-webhook, כפי שמתואר ב-How it Works & Handling Retries.

לוח הבקרה

מנויי API מופיעים ברשימת Webhooks עם המקור API, שם מנהל יכול לערוך, להשבית, להפעיל מחדש או למחוק אותם.

לסיכום

זה מסיים את תיעוד ה-Webhooks שלנו.

אנו מקווים שתמצאו את אינטגרציית ה-Webhook של FastComments קלה להבנה ומהירה להקמה.

אם אתם מרגישים שזיהיתם חוסרים בתיעוד שלנו, הודיעו לנו למטה.