Notification Webhook

Have notification event information sent to a webhook endpoint

The Notification Webhook enables you to monitor message-related events. Through a POST API call, the Notification Webhook sends event information to a webhook endpoint, such as those in the following list:

  • Someone liked your message
  • Your message was approved or rejected
  • Someone replied to your message
  • An author you follow posted a new article
  • A new topic that has a keyword you follow has been posted
  • Someone mentioned you in a comment
  • Someone started following you
  • Someone you follow commented or replied on any other comment

πŸ“˜

OpenWeb only sends notifications events for notifications that the user is expecting to receive. Users set their notification settings within their OpenWeb notification preferences.

If you use an SSO implementation, you can also create custom notification checkboxes for your users. Once a user has set the notifications to be received, you can make an Update User API call to update the user's OpenWeb notification settings.


The following sections explain how to set up and maintain the Notification Webhook.



Set up the Notification Webhook

  1. Create a webhook endpoint.

    πŸ“˜

    Be sure that your endpoint accepts both HTTPS connections and POST requests.

  2. Identify the notification events that you want to receive.

  3. Prepare the required configuration JSON.

  4. Contact your OpenWeb representative with your webhook configuration. Your OpenWeb representative will create and configure a unique authenticated endpoint request for you.



Security

OpenWeb supports authenticating your webhook using any of the methods listed in the following sections.


Tokens

Webhook Token

When OpenWeb sends an event notification to a registered webhook, an x-openweb-notification-event-webhook-token header is included so that you know the request was sent from OpenWeb servers.

OpenWeb strongly recommends that you verify the header when you receive a request at your webhook endpoint.

Please provide your token in a secure way to your OpenWeb representative.



Oauth2

OpenWeb supports authentication via the implementation of the RFC7523 (client_secret_jwt).

When using this approach, please provide the associated client secret in a secure way to your OpenWeb representative. OpenWeb will then securely store the client secret and sign the authentication requests with that key.

πŸ“˜

  • This flow creates a signed JWT in order to issue the request, The JWT expiration is *600 seconds.
  • The JWT Signing method uses HS256 (HMAC with SHA-256).


{
    "client_id": "CLIENT_ID",
    "client_secret": "CLIENT_SECRET",
    "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
    "grant_type": "client_credentials",
    "token_uri": "TOKEN_URI",
    "audience": "AUDIENCE",
    "extra_grants": {
        "scope": "PARTNER_SCOPE",
        "realm": "PARTNER_REALM"
    }
}
Parameter Description
audience* string Claim containing a value that identifies the authorization server as an intended audience
client_id* string ID of the client who must be authenticated
token_uri* string URL used to request an access token
client_assertion_type string Format of the assertion as defined by the authorization server

Default value: urn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_secret string Secret used to sign the JWT request to the authentication server

This is provided as a placeholder. You will need to supply this value in a secure way to your OpenWeb representative.
extra_grants string Various optional extra grants needed for the authorization request
grant_type string Credential representing the resource owner's authorization for the client to access its protected resources

The grant_type is used by the client to obtain an access token.

Default value: Client credentials


The successful authentication returns the following JSON.

{
   "access_token": "ACCESS_TOKEN",
   "token_type":" Bearer",
   "expires_in": 600
}
Parameter Description
access_token* string Access token used to issue webhook calls
expires_in* string Expiration time of the access token in seconds

OpenWeb will re-issue an authentication one minute before expiration. Be sure to return a value that is greater than 300 seconds.
token_type string Token type that is received

This is unused by OpenWeb.

Response codes and retries

The following table lists the response codes that OpenWeb issues for responses that are received from an authentication request.

If OpenWeb does not receive a 2xx response within 10 seconds of posting an event to your webhook endpoint, an attempt to resend the event occurs according to your configuration.

Status Code Description
200 Success: The access_token will be used for further webhook calls.
401 Unauthorized: OpenWeb will try to re-authenticate. If unsuccessful, the event will go through the regular retry cycle.
403 Forbidden: OpenWeb will try to re-authenticate. If unsuccessful, the event will go through the regular retry cycle.


Configuration

{
    "spot_id": "SPOT_ID",
    "endpoint": "ENDPOINT_URL",
    "auth_type": "partner_secret_token",
    "auth_config": {
        "token": "TOKENENDPOI"
    },
    "retry_base": 2,
    "retry_max_count": 5,
    "registered_events": {
        "email": [
            "user-mentioned",
            "user-followed",
            "liked-message"
        ],
        "in-app": []
    }
}
{
    "spot_id": "SPOT_ID",
    "endpoint": "ENDPOINT_URL",
    "auth_type": "client_secret_jwt",
    "auth_config": {
        "client_id": "CLIENT_ID",
        "client_secret": "CLIENT_SECRET",
        "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
        "audience": "AUDIENCE",
        "token_uri": "TOKEN_URI",
        "grant_type": "client_credentials",
        "extra_grants": {
            "scope": "PARTNER_SCOPE",
            "realm": "PARTNER_REALM"            
        }        
    },
    "retry_base": 2,
    "retry_max_count": 5, 
    "registered_events": {
        "email": [
            "user-mentioned",
            "replied-your-message",
            "liked-message"
        ],
        "in-app": []
    }
}
Notification Event Description
endpoint* string Events will be sent to this URL
spot_id* string Spot ID that should be used for those notifications
registered_events object List of email and in-app events per channel to which the user would like to register

This will always match the user's settings. For cases of a mismatch between both configurations (no registered channels), notification will not be sent for that user.
retry_base integer Base value to perform exponential retries

The formula for retries is: retry_base seconds.

Default: 2
Minimum: 1
Maximum: 5
retry_max_count integer Maximum number of retries per event after which the event will be discarded

The formula for retries is: retry_base seconds.

Default: 5
Minimum: 0
Maximum: 10


Events

OpenWeb enables you to configure your webhook endpoints to receive only the types of events required by your integration.

When event processing, be mindful of the following points:

  • You should account for receiving the same event more than once. We advise you to guard against duplicated events by checking the event id or making your event processing idempotent.
  • Event processing should rely upon event timestamps. Events are not guaranteed to be delivered in chronological order.
  • Events are sent one by one. They are not batched.

The following table lists all supported event types.

Notification Event Description
followee-commented Someone you follow commented or replied
liked-message Someone liked your message
message-approved Your message was approved
message-rejected Your message was rejected
replied-message Someone replied to your message
topic-by-author There is a new article from an author you are following
topic-by-keyword There is a new topic by keyword you are following
user-followed Someone started following you
user-mentioned Someone mentioned you in a comment

Responses

Each type of event returns a specific event response.

followee-commented
{
  "event_id": EVENT_ID, // hash of event
  "channels": [
    "email", 
    "in-app"
  ],
  "type": "followee-commented",
  "action_link": "ARTICLE_URL", 
  "conversation_id": "CONVERSATION_ID",
  "conversation_title": "ARTICLE_TITLE",
  "user": { 
       "user_id": "USER_ID",
       "sso_user_id": "SSO_USER_ID",
       "user_name": "USER_NAME",
       "display_name": "DISPLAY_NAME",
       "registered": true
  },
  "comment": {
    "content": [{
      "type": "text|image|animation",
      "text": "COMMENT_TEXT" 
    }],
    "comment_id": "COMMENT_ID",
    "type": "comment",
    "timestamp": 1642598712
  },
  "followee": {
    "user_id": "USER_ID2",
    "sso_user_id": "SSO_USER_ID2",
    "user_name": "USER_NAME2",
    "display_name": "DISPLAY_NAME2",
    "registered": true
  }
}

liked-message
{
   "event_id": EVENT_ID, // event hash
   "channels": [
       "email",
       "in-app"
   ],
   "type": "liked-message",
   "action_link": "ARTICLE_URL",
   "conversation_id": "CONVERSATION_ID",
   "conversation_title": "ARTICLE_TITLE",
   "user": { // recipient
       "user_id": "USER_ID",
       "sso_user_id": "SSO_USER_ID",
       "user_name": "USER_NAME",
       "display_name": "DISPLAY_NAME",
       "registered": true
   },
   "comment": {
       "content": [{
               "type": "text|image|animation",
               "text": "COMMENT_TEXT",
               "url": "IMAGE_URL"
       }],
       "type": "comment",
       "comment_id": "COMMENT_ID",
       "timestamp": 1641492345
   },
   "total_count": 10,
   "liker": {
       "user_id": "USER_ID2",
       "sso_user_id": "SSO_USER_ID2",
       "user_name": "USER_NAME2",
       "display_name": "DISPLAY_NAME2",
       "registered": false
   }
}

message-approved | message-rejected
{
    "event_id": EVENT_ID, // event hash
    "channels": [
        "email",
        "in-app"
    ],
    "type": "message-approved", // could also be message-rejected
    "action_link": "ARTICLE_URL",
    "conversation_id": "CONVERSATION_ID",
    "conversation_title": "ARTICLE_TITLE",
    "user": { // recipient
        "user_id": "USER_ID",
        "sso_user_id": "SSO_USER_ID",
        "user_name": "USER_NAME",
        "display_name": "DISPLAY_NAME",
        "registered": true
    },
    "comment": {
        "content": [{
            "type": "text|image|animation",
            "text": "COMMENT_TEXT",
            "url": "IMAGE_URL"
        }],
        "comment_id": "COMMENT_ID",
        "state": "approved | rejected",
        "type": "comment",
        "timestamp": 1642598712
    }
}

replied-message
{
   "event_id": EVENT_ID, // event hash
   "channels": [
       "email",
       "in-app"
   ],
   "type": "replied-message",
   "action_link": "ARTICLE_URL",
   "conversation_id": "CONVERSATION_ID",
   "conversation_title": "ARTICLE_TITLE",
   "user": { // recipient
       "user_id": "USER_ID",
       "sso_user_id": "SSO_USER_ID",
       "user_name": "USER_NAME",
       "display_name": "DISPLAY_NAME",
       "registered": true
   },
   "comment": {
       "content": [{
               "type": "text|image|animation",
               "text": "COMMENT_TEXT",
               "url": "IMAGE_URL"
       }],
       "comment_id": "COMMENT_ID",
       "type": "comment",
       "timestamp": 1643201248
   },
   "replier": {
       "user_id": "USER_ID2",
       "sso_user_id": "SSO_USER_ID2",
       "user_name": "USER_NAME2",
       "display_name": "DISPLAY_NAME2",
       "registered": false
   },
   "reply": {
       "content": [{
               "type": "text|image|animation",
               "text": "COMMENT_TEXT",
               "url": "IMAGE_URL"
       }],
       "comment_id": "COMMENT_ID",
       "type": "reply",
       "timestamp": 1643201248
   }
}

topic-by-author | topic-by-keyword
{
   "event_id": EVENT_ID, // event hash
   "channels": [
       "email",
       "in-app"
   ],
   "type": "topic-by-author | topic-by-keyword", // to complete
   "action_link": "ARTICLE_URL",
   "conversation_id": "CONVERSATION_ID",
   "conversation_title": "ARTICLE_TITLE",
   "description": "DESCRIPTION",
   "timestamp": 1642598712,
   "user": { // recipient
       "user_id": "USER_ID",
       "sso_user_id": "SSO_USER_ID",
       "user_name": "USER_NAME",
       "display_name": "DISPLAY_NAME",
       "registered": true
   },
   "keywords": [
       "Chris Columbus"
   ],
   "authors": [
       "John Doe"
   ]
}

user-followed
{
  "event_id": EVENT_ID, // hash of event
  "channels": ["email", "in-app"],
  "type": "user-followed",
  "action_link": "URL", 
  "user": {
       "user_id": "USER_ID",
       "sso_user_id": "SSO_USER_ID",
       "user_name": "USER_NAME",
       "display_name": "DISPLAY_NAME",
       "registered": true
  },
  "follower": {
      "user_id": "USER_ID2",
      "sso_user_id": "SSO_USER_ID2",
      "user_name": "USER_NAME2",
      "display_name": "DISPLAY_NAME2",
      "registered": true
  }
}

user-mentioned
{
   "event_id": EVENT_ID, // event hash
   "channels": [
       "email",
       "in-app"
   ],
   "type": "user-mentioned",
   "action_link": "ARTICLE_URL",
   "conversation_id": "CONVERSATION_ID",
   "conversation_title": "ARTICLE_TITLE",
   "user": { // recipient
       "user_id": "USER_ID",
       "sso_user_id": "SSO_USER_ID",
       "user_name": "USER_NAME",
       "display_name": "DISPLAY_NAME",
       "registered": false
   },
   "comment": {
       "content": [{
           "type": "text|image|animation",
           "text": "COMMENT_TEXT",
           "url": "IMAGE_URL"
       }],
       "comment_id": "COMMENT_ID",
       "type": "comment",
       "timestamp": 1641384172
   },
   "mentioner": {
       "user_id": "USER_ID2",
       "sso_user_id": "SSO_USER_ID2",
       "user_name": "USER_NAME2",
       "display_name": "DISPLAY_NAME2",
       "registered": false
   }
}

Parameter Description
action_link string URL of the comment or reply

The URL can contain a combination of the following query strings:
  • spot_im_comment_id: Identifies the specific comment
  • spot_im_highlight_immediate: Highlights the comment or reply
  • spot_im_reply_id: Identifies the specific reply

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned


URL of the article

Relevant events:
  • topic-by-author
  • topic-by-keyword


URL of the user's profile on the article the following action happened

Relevant event:
  • user-followed
authors array[string] List of article creators being followed

Relevant event:
  • topic-by-author
channels array[string] List of notification channels about which the user wants to be notified

If a user subscribed to a channel to which the webhook configuration is not subscribed, the channel will be removed from this list.

If there is no match between the user channel configuration and webhook channel configuration (empty channel array), the event will not be sent to the webhook.

Possible values:
  • email
  • in-app
comment object Contents and metadata of the comment

See: comment object

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned
conversation_id string Unique identifier that is a combination of the Spot ID and post ID

Relevant events: All
conversation_title string Title of the article

Relevant events: All
event_id string Unique identifier for the notification event

Relevant events: All
followee object Information about the user who commented or replied on any article, and the user follows that followee

See: user object

Relevant event:
  • followee-commented
follower object Information about the user who started following the recipient

See: user object

Relevant event:
  • user-followed
keywords array[string] List of one or several keywords being followed

Relevant event:
  • topic-by-keyword
liker object Information about the user who liked a message written by the notification recipient

See: user object

Relevant event:
  • liked-message
mentioner object Information about the user who mentioned the notification recipient within a comment

See: user object

Relevant event:
  • user-mentioned
replier object Information about the user who replied to a comment written by the notification recipient

See: user object

Relevant event:
  • replied-message
reply object Contents and metadata of the reply

See: comment object

Relevant event:
  • replied-message
total_count integer Number of likes for that comment or reply

Relevant event:
  • liked-message
type string Type of webhook notification

Possible values:
  • followee-commented
  • liked-messages
  • message-approved
  • message-rejected
  • replied-message
  • topic-by-author
  • topic-by-keyword
  • user-followed
  • user-mentioned

Relevant events: All
user object Information about the user (the recipient) receiving the notification

See: user object

Relevant events: All

comment object

Parameter Description
comment_id string Unique identifier of the comment or reply

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned
content array[string] List of content the comment or reply contains

See: comment.content object

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned
state string Approval status of a comment

Possible values:
  • approved: Value for a message-approved event
  • rejected: Value for a message-rejected event

Relevant events:
  • message-approved
  • message-rejected
timestamp integer List of content the comment or reply contains

Time of the comment or reply in Unix Epoch time

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned
type string Type of comment

Possible values:
  • comment
  • reply

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned

comment.content object

Comment content object represents an array of contents the comment has, There are several combination that are possible:

  • text
  • animation
  • image
  • text + animation
  • text + image
Parameter Description
text string Written, non-image, HTML-encoded content of the comment

This is relevant only for the text type portion of the comment.

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned
type string Type of content of the comment

Possible values:
  • animation
  • image
  • text

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned
url string URL of the image in the comment

This is relevant only for animation and image type portion of the comment.

Relevant events:
  • followee-commented
  • liked-message
  • message-approved
  • message-rejected
  • replied-message
  • user-mentioned

user object

The following object is relevant for all following events:

  • followee object for followee-commented
  • follower object for user-followed
  • liker object for liked-message
  • mentioner object for user-mentioned
  • replier object for replied-message
  • user object for all events
Parameter Description
display_name string Non-unique personal identifier used prominently throughout the platform

Relevant events: All
registered boolean Identifies if the user is a registered user

Possible values:
  • true: Registered user
  • false: Unregistered user

For the user-followed follower object and followee-commented followee object, the value is always true. A guest cannot follow or be followed

Relevant events: All
sso_user_id string Partner user identifier

This parameter is not returned for non-SSO implementations.

Relevant events: All
user_id string OpenWeb user identifier

Relevant events: All
user_name string Unique personal identifier used to differentiate between different users

Relevant events: All