Skip to main content

Overview

A webhook is an HTTP request used to provide push notifications. LikeMinds sends webhook to update your systems about certain changes or events, such as when a user creates a conversation/post or tags someone in a chat.

To receive Likeminds webhooks, you need to set up a dedicated endpoint on your server as a webhook listener that can receive POST requests, then provide this endpoint URL to Likeminds.

Configuring Webhooks

Before you can start receiving webhooks from Likeminds, you need to follow these steps:

  1. Set up a Webhook Listener: You'll need to setup a Webhook endpoint with a valid URL which can accept POST data from incoming webhook events.

  2. Create an Auth Token using an Admin/CM account:

    • Call the POST /sdk/initiate Endpoint with your Admin/CM credentials:

      curl --location 'https://auth.likeminds.community/sdk/initiate'
      --header 'x-api-key: <YOUR API KEY>'
      --data '{
      "user_name": "<Name of User>",
      "user_unique_id": "<UUID of Admin/CM>"
      }'
    • Extract the access_token from the response body.

  3. Register a new webhook for your Organization:

    • Call the POST /webhook Endpoint to set the webhook url, status, and type:

      curl --location '<https://auth.likeminds.community/webhook>'
      --header 'Authorization: <auth_token>'
      --data '{
      "webhook_type": "<webhook_type>",
      "url": "<your_webhook_url>",
      "is_active": false
      }'

Webhook Retry Mechanism

In case of a non-200 HTTP status or timeout, LikeMinds will resend the webhook event. Here are the retry mechanism details:

  • Max retries: 3
  • Time interval: 1 second, 1 minute, and 1 hour.

If all three retries fail (excluding the initial trial), the webhook status will be set to inactive. You can set it back to active using the Update Webhook API.

Supported Webhook Events

Likeminds currently supports the following webhook event types:

Chat Webhooks

Webhook typeTrigger Event
chatroom.joinedA user has joined/followed a chatroom
chatroom.leftA user has left a chatroom
chatroom.user.taggedUser/s have been tagged in a chatroom conversation
chatroom.conversation.repliedA conversation in a chatroom is replied to
profile.createdA new profile/user is created in the community
notifications.chatAll Chat notifications and its payload

Feed Webhooks

Webhook typeTrigger Event
post.createdA new post is created
post.pinnedA post is pinned
post.likedA post is liked by a user
post.taggedA user is tagged in a post text
comment.addedA comment is added on a post
comment.taggedA user is tagged in a comment text
comment.reactA user has liked/reacted on a comment
notifications.feedAll feed notifications and its payload

Webhook Payload Structure

The payload structure for each webhook event type follows a consistent format, with some variations in the data object depending on the specific event type. The general structure is as follows:

{
"id": string, // Event ID
"created_at": int, // Webhook trigger time (Unix timestamp in Milliseconds)
"event": string, // Event name (e.g., "post.created", "chatroom.joined")
"source": string, // Source identifier (e.g., "LM_FEED", "LM_CHAT")
"data": {} // Event-specific data object
}

Defined Object Structures:

user

{
"user": {
"id": int, // User ID
"custom_title": string, // Custom title
"image_url": string, // User image URL
"is_guest": boolean, // Indicates if the user is a guest
"is_deleted": boolean, // If user is deleted
"name": string, // User name
"sdk_client_info": {
"community": number, // Community ID
"uuid": string // customer UUID
},
"uuid": string // LM UUID
}
}

post

{
"post": {
"_id": string, // Post ID
"attachments": [], // Attachments of post
"comment_ids": null | array, // comment IDs or null
"comments_count": number, // Number of comments
"community_id": number, // Community ID
"created_at": number, // Post creation time (Unix timestamp in ms)
"heading": string, // Post heading
"is_edited": boolean, // Indicates if the post has been edited
"is_liked": boolean, // Indicates if the user has liked the post
"is_pinned": boolean, // Indicates if the post is pinned
"is_repost": boolean, // Indicates if the post is a repost
"is_reposted_by_user": boolean, // Indicates if the post is reposted by the user
"is_saved": boolean, // Indicates if the post is saved
"likes_count": number, // Number of likes
"menu_items": [], // menu items
"repost_count": number, // Number of reposts
"text": string, // Post text content
"topics": [],
"updated_at": number, // Post update time (Unix timestamp in ms)
"uuid": string // LM UUID
}
}

comment

{
"comment": {
"_id": string, // Comment ID
"temp_id": string | null, // Temporary ID or null
"text": string, // Comment text
"level": int, // Comment level (e.g., 1 for root comment, 2 for reply to a root comment, etc.)
"uuid": string, // UUID of the commenter
"community_id": int, // Community ID
"post_id": string, // Post ID the comment belongs to
"is_liked": boolean, // Indicates if the user has liked the comment
"likes_count": int, // Number of likes on the comment
"comments_count": int, // Number of replies to the comment
"is_edited": boolean, // Indicates if the comment has been edited
"is_deleted": boolean, // Indicates if the comment has been deleted
"deleted_by": string, // User ID of the user who deleted the comment
"deleted_by_uuid": string, // UUID of the user who deleted the comment
"delete_reason": string, // Reason for deleting the comment
"parent_comment": {
// CommentResponse object (recursive structure for nested comments)
},
"replies": [
// Array of CommentResponse objects (replies to this comment)
],
"menu_items": [
{
"id": int, // Menu item ID
"title": string // Menu item title
}
],
"created_at": int, // Comment creation time (Unix timestamp in ms)
"updated_at": int // Comment update time (Unix timestamp in ms)
}
}

topic

{
"topic": {
"_id": string, // Topic ID
"name": string, // Topic name
"is_enabled": boolean, // Indicates if the topic is enabled
"priority": int, // Topic priority
"is_searchable": boolean, // Indicates if the topic is searchable
"parent_id": string, // Parent topic ID
"parent_name": string, // Parent topic name
"level": int, // Topic level (e.g., 0 for root topic, 1 for child-topic, etc.)
"widget_id": string // Widget ID associated with the topic
}
}

widget

{
"widget": {
"_id": string, // Widget ID
"parent_entity_id": string, // Parent entity ID
"parent_entity_type": string, // Parent entity type
"metadata": {
// Key-value pairs for widget metadata
},
"created_at": int, // Widget creation time (Unix timestamp in ms)
"updated_at": int // Widget update time (Unix timestamp in ms)
}
}

conversation

{
"conversation": {
"conversation_id": string, // Conversation ID
"creator_id": string, // Creator ID
"members": [
string // Array of member IDs
],
"message": string, // Conversation message
"timestamp": number // Conversation creation time (Unix timestamp)
}
}

chatroom

{
"chatroom": {
"chatroom_image_url": string, // Chatroom image URL
"community_id": int, // Community ID
"community_name": string, // Community name
"title": string, // Chatroom title
"header": string, // Chatroom header
"id": string, // Chatroom ID
"is_secret": boolean, // Indicates if the chatroom is secret
"updated_at": int, // Chatroom update time (Unix timestamp in milliseconds)
"created_at": int, // Chatroom creation time (Unix timestamp in milliseconds)
"participants_count": int // Number of participants in the chatroom
}
}

Chat event payloads (data)

chatroom.joined

{
"chatroom": {}, // Chatroom Object
"user": {}, // User Object
"join_method": "" // How the user joined
}

chatroom.user.tagged

{
"chatroom": {}, // Chatroom Object
"conversation": {}, // Conversation Object
"created_by_user": {}, // User Object (Created By User)
"tagged_users": [{}] // Array of User Objects (Tagged Users)
}

chatroom.conversation.replied

{
"chatroom": {}, // Chatroom Object
"original_conversation": {}, // Original Conversation Object
"replied_conversation": {}, // Replied Conversation Object
"original_conversation_user": {}, // User Object (Original Conversation User)
"replied_conversation_user": {} // User Object (Replied Conversation User)
}

profile.created

{
"user": {} // User Object
}

notifications.chat

{
"notification_payload": {}, // Notification Payload
"uuids": [] // Customer UUIDs (Notification Receivers)
}

Feed event payloads (data)

post.created

{
"post": {}, // Post Object
"topics": {}, // Topics
"widgets": {}, // Widgets
"post_creator": {} // Post Creator
}

post.pinned

{
"post": {}, // Post Object
"topics": {}, // Topics
"widgets": {}, // Widgets
"post_creator": {}, // Post Creator
"pinned_by": {} // User Object (Pinned By)
}

post.tagged

{
"post": {}, // Post Object
"topics": {}, // Topics
"widgets": {}, // Widgets
"post_creator": {}, // Post Creator
"tagged_users": [{}] // Array of User Objects (Tagged Users)
}

post.liked

{
"post": {}, // Post Object
"topics": {}, // Topics
"widgets": {}, // Widgets
"post_creator": {}, // Post Creator
"post_liked_by": {} // User Object (User Who Liked the Post)
}

comment.added

{
"comment": {}, // Comment Object
"comment_creator": {}, // User Object (Comment Creator)
"post": {}, // Post Object
"topics": {}, // Topics
"widgets": {}, // Widgets
"post_creator": {} // Post Creator
}

comment.tagged

{
"comment": {}, // Comment Object
"comment_creator": {}, // User Object (Comment Creator)
"post": {}, // Post Object
"topics": {}, // Topics
"widgets": {}, // Widgets
"post_creator": {}, // Post Creator
"tagged_users": [{}] // Array of User Objects (Tagged Users)
}

comment.react

{
"comment": {}, // Comment Object
"comment_creator": {}, // User Object (Comment Creator)
"post": {}, // Post Object
"topics": {}, // Topics
"widgets": {}, // Widgets
"post_creator": {}, // Post Creator
"liked_by_user": {} // User Object (User Who Liked/Reacted on the Comment)
}

notifications.feed

{
"current_page": int, // current page of uuids
"total_pages": int, // total pages for the uuids
"notification_payload": {}, // Notification Payload
"uuids": [] // Customer UUIDs (Notification Receivers) (paginated to 1000 per page)
}

Examples

Let's say you want to receive a webhook whenever a user sends a conversation in a chatroom. For that, you first need to register a webhook with webhook_type = "conversation.create" using the POST /webhook Endpoint, along with a Valid URL.

Here's an example of how you would register the webhook:

  curl --location 'https://auth.likeminds.community/webhook'\
--header 'Authorization: <auth_token>'\
--data '{
"webhook_type": "conversation.create",
"url": "<your_webhook_url>",
"is_active": true
}'

Once registered, Likeminds will send a POST request to your webhook URL whenever a new conversation is created in a chatroom. You can then handle the webhook payload according to your application's requirements.

Note: If your endpoint is IP restricted, please contact backend[at]likeminds.community to whitelist the IP addresses from which the webhooks will be sent.

Best Practices

  • Design for duplicate and out-of-order webhooks: Ensure idempotency on actions you take when receiving a webhook. If you drive application state with webhooks, ensure your code doesn't rely on a specific order of webhook receipt.
  • Handle missed webhooks: If you (or Likeminds) experience downtime for longer than Likeminds's retry period, you will lose webhooks. If you use webhooks for state transitions, ensure your application can self-heal by requesting data from Likeminds's other endpoints if a webhook is not received within a window. All data present in webhooks is also available through other APIs.
  • Keep your receiver simple: It's best to keep your webhook receiver as simple as possible, such as a receiver whose only job is to write the webhook into a queue or reliable storage. This is important for two reasons:
    1. If the receiver does not respond within certain time (1min), the delivery is considered failed.
    2. Webhooks can arrive at unpredictable rates, so if you do a lot of work in your receiver (e.g., generating and sending an email), spikes are likely to overwhelm your downstream services or cause rate-limiting if the downstream is a third-party.
  • Exempt webhook route from CSRF protection: If you're using a web framework that automatically checks for CSRF tokens on POST requests (e.g., Rails, Django), you might need to exempt the webhooks route from CSRF protection to ensure that legitimate webhook requests can be processed.

Additional Resources

This comprehensive documentation should provide you with all the necessary information to set up, configure, authenticate, and utilise webhooks for your LikeMinds integration effectively.