FastComments.com

Webhooks

Με το FastComments είναι δυνατό να κληθεί ένα API endpoint κάθε φορά που ένα σχόλιο προστίθεται, ενημερώνεται ή αφαιρείται από το σύστημά μας.

Αυτό το επιτυγχάνουμε με ασύγχρονα webhooks μέσω HTTP/HTTPS.

Τι είναι τα Webhooks Internal Link

Ένα Webhook είναι ένας μηχανισμός, ή μια ενσωμάτωση, μεταξύ δύο συστημάτων όπου ο "παραγωγός" (FastComments) πυροδοτεί ένα συμβάν που ο "καταναλωτής" (Εσείς) καταναλώνει μέσω κλήσης API.

Υποστηριζόμενα Γεγονότα & Πόροι Internal Link

Το FastComments υποστηρίζει webhooks μόνο για τον πόρο Comment.

Υποστηρίζουμε webhooks για τη δημιουργία, την αφαίρεση και την ενημέρωση σχολίων.

Κάθε ένα από αυτά θεωρείται ξεχωριστό γεγονός στο σύστημά μας και ως εκ τούτου έχει διαφορετική σημασιολογία και δομή για τα γεγονότα webhook.

Οποιοσδήποτε αριθμός τελικών σημείων μπορεί να εγγραφεί στο ίδιο γεγονός, είτε από τον πίνακα ελέγχου είτε μέσω του API (δείτε τη Διαχείριση Webhooks μέσω του API). Κάθε webhook παραδίδεται ανεξάρτητα.

Δοκιμή Internal Link

Οι νέες και οι σελίδες επεξεργασίας webhook διαθέτουν ένα κουμπί Send Test Payload που στέλνει ένα αίτημα στη διεύθυνση URL που βρίσκεται αυτή τη στιγμή στη φόρμα, ανεξάρτητα από το αν έχει αποθηκευτεί. Τα γεγονότα Create και Update στέλνουν ένα ψεύτικο αντικείμενο WebhookComment, ενώ η δοκιμή Delete θα στείλει ένα ψεύτικο σώμα αιτήματος με μόνο ένα ID.

Επαλήθευση Φορτίων

Κατά τη δοκιμή της ενσωμάτωσης webhook, επαληθεύστε ότι τα εισερχόμενα αιτήματα περιλαμβάνουν τις ακόλουθες κεφαλίδες:

  1. X-FastComments-Timestamp - Χρονική σήμανση Unix (δευτερόλεπτα)
  2. X-FastComments-Signature - Υπογραφή HMAC-SHA256

Τα webhooks που δημιουργήθηκαν πριν εισαχθεί το σχήμα υπογραφής λαμβάνουν επίσης μια κεφαλίδα token που περιέχει το API Secret σας. Τα νέα webhooks δεν το κάνουν.

Χρησιμοποιήστε την επαλήθευση υπογραφής HMAC για να διασφαλίσετε ότι τα φορτία είναι αυθεντικά.

Εργαλεία Δοκιμής

Μπορείτε να χρησιμοποιήσετε εργαλεία όπως το webhook.site ή το ngrok για να ελέγξετε τα εισερχόμενα φορτία webhook κατά την ανάπτυξη.

Τύποι Συμβάντων

  • Create Event: Ενεργοποιείται όταν δημιουργείται ένα νέο σχόλιο.
  • Update Event: Ενεργοποιείται όταν ένα σχόλιο επεξεργάζεται.
  • Delete Event: Ενεργοποιείται όταν ένα σχόλιο διαγράφεται.

Κάθε webhook συνδέεται με ένα γεγονός και μία μέθοδο HTTP (POST, PUT ή DELETE). Κάθε γεγονός περιλαμβάνει τα πλήρη δεδομένα του σχολίου στο σώμα του αιτήματος (δείτε το Data Structures για τη μορφή του φορτίου).

Δομές Δεδομένων Internal Link

Η μόνη δομή που αποστέλλεται μέσω webhooks είναι το αντικείμενο WebhookComment, περιγραφόμενο παρακάτω σε TypeScript.

Η Δομή του Αντικειμένου WebhookComment

Η Δομή του Γεγονότος "Create"

Το σώμα του αιτήματος του γεγονότος "create" είναι ένα αντικείμενο WebhookComment.

Η Δομή του Γεγονότος "Update"

Το σώμα του αιτήματος του γεγονότος "update" είναι ένα αντικείμενο WebhookComment.

Η Δομή του Γεγονότος "Delete"

Το σώμα του αιτήματος του γεγονότος "delete" είναι ένα αντικείμενο WebhookComment.

Αλλαγή από 14 Νοεμβρίου 2023
Πριν, το σώμα του αιτήματος του γεγονότος "delete" περιείχε μόνο το αναγνωριστικό του σχολίου. Τώρα περιλαμβάνει ολόκληρο το σχόλιο τη στιγμή της διαγραφής.

Κάθε κλειδί είναι πάντα παρόν στο σώμα. Όταν το σχόλιο δεν έχει τιμή για ένα πεδίο, το σώμα μεταφέρει null (ή false για boolean και [] για λίστες), ώστε η δομή μιας παράδοσης να μην διαφέρει ποτέ από σχόλιο σε σχόλιο.

Το αντικείμενο 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
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 guide για τους τύπους σήματος.

Το αντικείμενο Σήματος 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 Event: POST ή PUT (προεπιλογή: PUT)
  • Update Event: POST ή PUT (προεπιλογή: PUT)
  • Delete Event: DELETE, POST ή PUT (προεπιλογή: DELETE)

Δεδομένου ότι όλα τα αιτήματα περιέχουν ένα ID, οι λειτουργίες Create και Update είναι ιδεομετρικές από προεπιλογή (PUT). Η επανάληψη του ίδιου αιτήματος Create ή Update δεν πρέπει να δημιουργεί διπλότυπα αντικείμενα στην πλευρά σας.

Κεφαλίδες Αιτήματος

Κάθε αίτημα webhook περιλαμβάνει τις ακόλουθες κεφαλίδες:

ΚεφαλίδαΠεριγραφή
Content-Typeapplication/json
tokenΤο μυστικό API σας
X-FastComments-TimestampΧρονική σήμανση Unix (δευτερόλεπτα) όταν υπογράφηκε το αίτημα
X-FastComments-SignatureΥπογραφή HMAC-SHA256 (sha256=<hex>)

Δείτε την ενότητα Security & API Tokens για πληροφορίες σχετικά με την επαλήθευση της υπογραφής HMAC.

Ασφάλεια & Διακριτικά API Internal Link

Τα αιτήματα webhook του FastComments περιλαμβάνουν πολλαπλούς μηχανισμούς ελέγχου ταυτότητας για λόγους ασφαλείας.

Headers που Αποστέλλονται

HeaderΠεριγραφή
tokenΤο API Secret σας (για συμβατότητα με παλαιότερες εκδόσεις)
X-FastComments-TimestampUnix timestamp (δευτερόλεπτα) κατά τη στιγμή της υπογραφής του αιτήματος
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.

Διαχείριση Webhooks μέσω του API Internal Link

Τα Webhooks μπορούν επίσης να διαχειριστούν μέσω του REST API. Έτσι γίνονται συνδρομές σε συμβάντα σχολίων από ενσωματώσεις όπως το Zapier χωρίς να αγγίζεται το dashboard, και ακολουθεί το μοτίβο REST Hooks: συνδρομή, λήψη συμβάντων, κατάργηση συνδρομής.

Οι συνδρομές μέσω API συνυπάρχουν με τα webhooks που ρυθμίζονται στο dashboard. Ένα συμβάν σχολίου παραδίδεται σε κάθε webhook που ταιριάζει με το domain του, το καθένα ως ξεχωριστή παράδοση, ανεξάρτητα από το πώς δημιουργήθηκε το webhook.

Πιστοποίηση

Κάθε αίτημα απαιτεί το API Key σας στην επικεφαλίδα x-api-key (ή την παράμετρο API_KEY στο query string) και το tenant ID σας στην παράμετρο tenantId του query string. Και τα δύο εμφανίζονται στη σελίδα API Secret στο dashboard.

Συνδρομή

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ΌχιΈνα domain από τη ρύθμιση του λογαριασμού σας. Προεπιλογή είναι το *, το οποίο λαμβάνει συμβάντα για κάθε 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 στο ίδιο συμβάν και domain επιστρέφει την υπάρχουσα συνδρομή αντί να δημιουργήσει διπλότυπο, ώστε ένας client να μπορεί να επαναλάβει το αίτημα με ασφάλεια. Κάθε tenant μπορεί να έχει έως 50 συνδρομές μέσω API.

Λίστα

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

Επιστρέφει κάθε webhook για τον tenant, συμπεριλαμβανομένων εκείνων που διαχειρίζονται στο dashboard ("source": "dashboard"). Φιλτράρετε με event, domain ή source.

Κατάργηση συνδρομής

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

Η διαγραφή μιας συνδρομής απορρίπτει επίσης τυχόν συμβάντα που βρίσκονται ακόμα σε ουρά για αυτήν. Μόνο συνδρομές που δημιουργήθηκαν μέσω API μπορούν να διαγραφούν με αυτόν τον τρόπο· ένα webhook του dashboard, ή ένα id που δεν υπάρχει στον λογαριασμό σας, απαντά με 404 και κωδικό not-found. Τα webhooks του dashboard επεξεργάζονται στη σελίδα Webhooks.

Payloads και υπογραφή

Οι παραδόσεις χρησιμοποιούν το ίδιο payload με τα webhooks του dashboard (βλ. Data Structures) και υπογράφονται με το ίδιο σχήμα HMAC (βλ. Security & API Tokens). Οι συνδρομές μέσω API δεν λαμβάνουν ποτέ την παλαιά επικεφαλίδα token, οπότε επαληθεύστε την επικεφαλίδα X-FastComments-Signature αντί αυτής.

Δείγματα payloads

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 credits.

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

Αν το endpoint μιας συνδρομής μέσω API απαντήσει με HTTP 410 Gone, το FastComments το ερμηνεύει ως κατάργηση συνδρομής: η συνδρομή διαγράφεται μαζί με τα συμβάντα της σε ουρά και δεν γίνονται περαιτέρω προσπάθειες παράδοσης. Τα webhooks που ρυθμίζονται στο dashboard δεν διαγράφονται ποτέ αυτόματα· για αυτά ένα 410 είναι μια συνηθισμένη αποτυχία. Κάθε άλλη κατάσταση αποτυχίας επαναλαμβάνεται και τελικά απενεργοποιεί το webhook, όπως περιγράφεται στο How it Works & Handling Retries.

Dashboard

Οι συνδρομές μέσω API εμφανίζονται στη λίστα Webhooks με πηγή API, όπου ένας διαχειριστής μπορεί να τις επεξεργαστεί, να τις απενεργοποιήσει, να τις επανενεργοποιήσει ή να τις διαγράψει.

Συμπερασματικά

Με αυτό ολοκληρώνεται η τεκμηρίωση των Webhooks.

Ελπίζουμε να βρείτε την ενσωμάτωση Webhook του FastComments εύκολη στην κατανόηση και γρήγορη στη ρύθμιση.

Εάν πιστεύετε ότι έχετε εντοπίσει κενά στην τεκμηρίωσή μας, ενημερώστε μας παρακάτω.