With FastComments it's possible to invoke an API endpoint whenever a comment gets added, updated, or removed from our system.

We accomplish this with asynchronous webhooks over HTTP/HTTPS.

What are Webhooks Internal Link

A Webhook is a mechanism, or an integration, between two systems where the "producer" (FastComments) fires an event that the "consumer" (You) consumes via an API call.

Supported Events & Resources Internal Link

FastComments supports webhooks for the Comment resource only.

We support webhooks for comment creation, removal, and on update.

Each of these are considered separate events in our system and as such have different semantics and structures for the webhook events.

Testing Internal Link

In the Webhooks admin there are Send Test Payload buttons for each event type (Create, Update, Delete). The Create and Update events send a dummy WebhookComment object, while testing Delete will send a dummy request body with just an ID.

The test will make two calls to verify the response code for "happy" (correct API Key) and "sad" (invalid API key) scenarios.

When the test sends an invalid API key you should return a status code of 401 for the test to pass completely. If you don't correctly check the value of the token, you'll see an error.

This is to ensure that you properly authenticate the request.

Data Structures Internal Link

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

The WebhookComment Object Structure

The "Create" Event Structure

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

The "Update" Event Structure

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

The "Delete" Event Structure

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

Change as of Nov 14th 2023
Previously the "delete" event request body only contained the comment id. It now contains the full comment at the time of deletion.
The WebhookComment Object
Copy CopyRun External Link
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
9 /** The user id that left the comment. If SSO, prefixed with tenant id. **/
10 userId?: string
11 /** The email of the user left the comment. **/
12 commenterEmail?: string
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
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 /** Date when the comment was verified. **/
32 verifiedDate?: number
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
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
45 /** The page number the comment is on for the "Oldest First" sort direction. **/
46 pageNumberOF: number
47 /** The page number the comment is on for the "Newest First" sort direction. **/
48 pageNumberNF: number
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
53 /** The @mentions written in the comment that were successfully parsed. **/
54 mentions?: CommentUserMention[]
55 /** The domain the comment is from. **/
56 domain?: string
57 /** The optional list of moderation group ids associated with this comment. **/
58 moderationGroupIds?: string[]|null

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.

The Webhook Mentions Object
Copy CopyRun External Link
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 = 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

HTTP Methods Used

Create and Update both use HTTP PUT and not POST!

Since all of our requests contain an ID, repeating the same Create or Update request should not create new objects on your side.

This means that these calls are idempotent and should be PUT events as per the HTTP specification.

Security & API Tokens Internal Link

In the request header we'll pass your API Secret in the parameter called "token".

If you do not properly check this parameter, your integration will not be marked Verified. This is a safeguard to ensure any integrations with FastComments are secure.

How it Works Internal Link

All changes to the Comment object in the system fire an event which ends up on a queue.

The initial webhook event is usually sent within six seconds of the event source occurring.

You can monitor this queue in the Webhooks admin in the event that your API goes down.

If a request to your API fails, we'll re-queue it on a schedule.

That schedule is 1 Minute * the retry count. If the call fails once, it'll try again in a minute. If it fails twice, it'll then wait two minutes, and so on. This is so that we don't overload your API if you are going down to load related reasons.

In Conclusion

This concludes our Webhooks documentation.

We hope you find the FastComments Webhook integration easy to understand and fast to set up.

If you feel you have identified any gaps in our documentation, let us know below.