Webhooks

Configure Viafoura webhooks to receive near real-time audience engagement events, including follow and unfollow events.

Viafoura can send audience engagement events to your own systems in near real time. Business intelligence and reporting dashboards can be enriched and empower your staff with insights into the real-time activity of your audience as they engage with content and each other.

Webhook types

Viafoura offers three webhooks. Each one sends its own set of events to its own URL, so you can turn on only the ones you need.

WebhookWhat it sendsSent to
Content Action WebhookActivity on comments, replies, chat messages, live blog posts, reviews, and Live Q&A, such as posts, likes, flags, pins, and moderationContent data webhook URL
User Action WebhookActivity by or about a user: following or unfollowing authors and topics, poll and quiz votes, and bansUser action webhook URL
Notification WebhookNotifications addressed to specific users, and broadcastsNotification webhook URL

Content Action Webhook
Capture actions taken on community content, such as posting, liking, flagging, or pinning comments. Ideal for analyzing content engagement, monitoring moderation activity, and integrating content data into external systems.

User Action Webhook
Track user-level activities, such as following or unfollowing users and topics, voting in polls and quizzes, and account bans. Useful for synchronizing user activity with external systems and automating workflows based on user relationships or restrictions.

Notification Webhook
Extend Viafoura's notifications and broadcasts to your own communication channels. Designed for delivering notifications through email, push notifications, or newsletters using existing tools and preferences. The Notification Webhook has its own events and request format, described on the Notifications Webhook page.

The Content Action and User Action webhooks use the same request format, described on this page. Use message_type to tell their events apart.

⚠️

Each webhook sends only to its own URL. If the User action webhook URL is empty, follow, poll vote, and ban events are not sent, even when the Content data webhook URL is set.

Setup

You will need to:

  1. Configure an HTTPS endpoint for each webhook you want to receive. Because the Content Action and User Action webhooks use the same request format, one endpoint can receive both: provide the same URL for each.
  2. Provide us with an authorization value we can pass to your API to let you know it's coming from us. It must be at least 64 bytes, hexadecimal.

Please contact your client success representative with this information and they will get this set up with you.

These are the settings involved, in Viafoura Admin → General → Notifications. Some appear under an older label, shown in parentheses.

SettingApplies to
Enable webhooks (Server-to-server callback)All three webhooks. Turns webhook delivery on or off for the site.
Webhook authorization header (server-to-server callback authorization header)All three webhooks. Sent in the authorization header of every request.
Content data webhook URL (content server-to-server callback url)Content Action Webhook
User action webhook URLUser Action Webhook
Notification webhook URL (Notification server-to-server callback URL)Notification Webhook

Request format

This section applies to both the Content Action and User Action webhooks.

Security
Note that:
The service will be available over SSL (https) using a valid certificate
Viafoura application will use the certificate for both Authentication and Authorization

Conversation Pattern
The conversation between client and server will be Fire and Forget.
RESTful Service Specification

Request
Scheme: https
URL: will be provided by you to your CS representative
*HTTP Method: POST

Parameters

Request Headers

Header nameDescription
x-request-idRandom request ID provided by viafoura on each HTTP request, the value is the same as “request_uuid” in the request body
authorizationAt least 64 bytes, hexadecimal. Please provide this to your CS representative
content-typeapplication/json; charset=utf-8
acceptapplication/json

Request Body
The request body is a JSON encoded string that follows the schema below:

FieldTypeDescription
request_uuidstringSame as “X-Request-ID” in header
timenumberThe time in milliseconds
versionnumberThe current value is 1
eventsarrayArray of Event object

Event object

Event objects describe state changes in the Viafoura system. Additional fields may be included based on message_type and action.

FieldTypeDescription
event_uuidstringEvent ID
timenumberThe time in milliseconds
user_agentstringHTTP User-Agent header captured when the event was generated; may be absent for internally-generated events (e.g. moderation actions).
message_typestringThe type of item or activity. See Content Action events and User Action events for every value and the webhook that sends it.
actionstringWhat happened to the item. See the event tables below for the actions each message_type supports.
detailobjectEvent-specific details for poll_vote and user_ban events. Absent for other event types.
content_uuidstringID of the content item that was interacted with. For poll_vote, this is the poll UUID and equals detail.poll_uuid.
actor_uuidstringid of the user or actor who caused the interaction (this could be internal ids in the case of moderation events)
author_uuidstringid of the user who created the content (e.g. the author of the comment)
topic_idstringTopic identifier for follow_topic events. Absent for other event types.
topic_namestringOptional human-readable topic name for follow_topic events. Absent for other event types.
content_container_uuidstringid of the content container that was interacted on
section_uuidstringid of the viafoura section where the action occurred
page_urlstringFull URL where the action occurred. Absent for poll_vote events.

Response

HTTP Status
A 200, 201 or 202 response code is expected in the HTTP response code. However third-party service can return other status codes to let our customer success team help with diagnosing possible issues in the integration.

Error CodeDescription
404Not Found
500Any internal error
400Data is not valid
200-201Request accepted
403Authorization failed

Response Body from Third Party Service
The expected response from the third party service will only be parsed if the following schema is used.

FieldTypeDescription
request_uuidstringrequest_id of corresponding request
resultsarrayArray of Result objects

Result object

FieldTypeDescription
event_uuidstringEvent ID
typestringEither “success” or “failure”
error_typestringArbitrary value
error_descriptionstringArbitrary value

Example response

{
    "request_uuid": "c71b5cb1-ce44-4239-8b6e-87b99cf2b1f0",
    "results": [
        {
            "event_uuid":"c71b5cb1-ce44-4239-8b6e-87b99cf2b1a0",
            "type": "failure",
            "error_type": "unknown",
            "error_description": "unable to store"
        },
        {
            "event_uuid":"dd519c8a-3619-4cb0-b31b-0ffd14d24aab",
            "type": "success"
        },
        {
            "event_uuid":"d8a6a231-0cef-4385-83d8-66b6160811a5",
            "type": "success"
        },
        {
            "event_uuid":"5c0c5ab3-f3be-4194-bfc5-2000f94665ad",
            "type": "success"
        }
    ]
}

Content Action events

Sent to the Content data webhook URL.

Message TypeActionTrigger
livecomment_postcreatednew comment created
livecomment_postvisiblecomment enabled after moderation
livecomment_postdisabledcomment disabled by moderation or if the report (flag) threshold has been reached
livecomment_postupdatedcomment modified
livecomment_postlikedcomment liked by a user
livecomment_postunlikedcomment like reverted by a user
livecomment_postdislikedcomment disliked by a user
livecomment_postundislikedcomment dislike reverted by a user
livecomment_postflaggedcomment has been reported
livecomment_postspammedcomment was marked as spam by moderation
livecomment_postpinnedcomment was pinned to the top
livecomment_postunpinnedcomment was unpinned from the top
livecomment_postpickedcomment was marked as "editor's pick"
livecomment_postunpickedremoved the "editor's pick" mark from the comment
reply_to_livecomment_postcreatednew comment reply created
reply_to_livecomment_postvisiblecomment reply enabled after moderation
chat_messagecreatedchat message is created
chat_messagevisiblechat message is enabled after moderation
chat_messagelikedchat message liked by a user
chat_messageunlikedchat message like reverted by a user
chat_messagedislikedchat message disliked by a user
chat_messageundislikedchat message dislike reverted by a user
reply_to_chat_messagecreatedchat message reply is created
reply_to_chat_messagevisiblechat message reply is enabled after moderation
liveblog_postcreatedliveblog post is created
liveblog_postdisabledliveblog post disabled by admin
liveblog_postupdatedliveblog post modified
liveblog_postlikedliveblog post liked by a user
liveblog_postunlikedliveblog post like reverted by a user
liveblog_postdislikedliveblog post disliked by a user
liveblog_postundislikedliveblog post dislike reverted by a user
liveblog_postpickedliveblog post was marked as "editor's pick"
liveblog_postunpickedremoved the "editor's pick" mark from the liveblog post
liveblog_postpinnedliveblog post was pinned to the top
liveblog_postunpinnedliveblog post was unpinned from the top
livereview_postcreatednew review was created
livereview_postvisiblereview enabled after moderation
livereview_postdisabledreview disabled due to moderation
livereview_postupdatedreview edited/changed
livereview_postlikedreview marked as helpful by a user
livereview_postunlikedreview marked as not helpful by a user
livereview_postdislikedreview unmarked as helpful by a user
livereview_postundislikedreview unmarked as not helpful by a user
livereview_postflaggedreview has been reported
livereview_postspammedreview marked as spam
livereview_postpinnedreview pinned to the top
livereview_postunpinnedreview unpinned from top
livereview_postpickedreview marked as "editors pick"
livereview_postunpickedremoved the "editor's pick" mark from the review
reply_to_livereview_postcreateda reply to a review was created
reply_to_livereview_postvisiblereview reply enabled after moderation
livequestioncreatednew Live Q&A session created
livequestionupdatedLive Q&A session details modified (title, settings)
livequestionstartedLive Q&A session moved from Upcoming to Live
livequestionconcludedLive Q&A session moved from Live to Concluded
livequestionreopenedLive Q&A session moved from Concluded back to Live
livequestion_postcreatednew question created
livequestion_postvisiblequestion enabled after moderation
livequestion_postdisabledquestion disabled by moderation or if the report (flag) threshold has been reached
livequestion_postupdatedquestion modified
livequestion_postdeletedquestion deleted
livequestion_postlikedquestion liked by a user
livequestion_postunlikedquestion like reverted by a user
livequestion_postdislikedquestion disliked by a user
livequestion_postundislikedquestion dislike reverted by a user
livequestion_postflaggedquestion has been reported
livequestion_postspammedquestion was marked as spam by moderation
reply_to_livequestion_postcreatednew question reply created
reply_to_livequestion_postvisiblequestion reply enabled after moderation

Example request

{ 
 request_uuid: 'abcc2254-b0a4-492c-a8f2-ae7820f4968a',
 time: 1593205167183,
 version: 1,
 events:
  [ 
    { event_uuid: '99d2a532-e1a1-4455-834a-775148570e9d',
      time: 1593205166938,
      section_uuid: '00000000-0000-4000-8000-337a437adec1',
      content_container_uuid: '0dc371b9-cecd-4dc3-954b-e5255794e2e7',
      content_uuid: 'bf890170-4828-4d1d-a1b0-a0072a6117d3',
      actor_uuid: '00000000-0000-4000-8000-017ea245f200',
      author_uuid: '00000000-0000-4000-8000-485fe358a524',
      message_type: 'livecomment_post',
      page_url: 'https://action.click/livecomments/actioncomments.html',
      action: 'liked' 
    } 
  ] 
}

User Action events

Sent to the User action webhook URL. These events use the same request format as Content Action events.

Message TypeActionTrigger
follow_authorfolloweda user follows another user (author)
follow_authorunfolloweda user unfollows another user (author)
follow_topicfolloweda user follows a topic
follow_topicunfolloweda user unfollows a topic
poll_votevoteda signed-in user votes in a poll or quiz
user_banbannedA user is banned
user_banunbannedA user is unbanned

Follow events

For follow events, content_uuid, content_container_uuid, and page_url are absent. actor_uuid is the user performing the follow. For follow_author, author_uuid is the user being followed.

Follow author request

{
  request_uuid: 'abcc2254-b0a4-492c-a8f2-ae7820f4968a',
  time: 1593205167183,
  version: 1,
  events: [
    {
      event_uuid,
      time,
      section_uuid,
      actor_uuid,
      author_uuid,
      message_type: 'follow_author',
      action: 'followed'
    }
  ]
}

Follow topic request

{
  request_uuid: 'abcc2254-b0a4-492c-a8f2-ae7820f4968a',
  time: 1593205167183,
  version: 1,
  events: [
    {
      event_uuid,
      time,
      section_uuid,
      actor_uuid,
      message_type: 'follow_topic',
      action: 'followed',
      topic_id: 'sports/nba',
      topic_name: 'NBA'
    }
  ]
}

The unfollowed variants are identical except action: 'unfollowed'.

Poll vote event fields

For poll_vote events, detail contains a snapshot of the poll when the vote was cast. Later changes to the question or options do not change an event that has already been delivered. Quizzes send the same poll_vote event with detail.is_quiz set to true.

FieldTypeDescription
detail.poll_uuidstringPoll UUID. This intentionally duplicates content_uuid so the detail object is self-contained.
detail.poll_questionstringPoll question at the time of the vote. Absent if the upstream record does not contain a question.
detail.is_quizbooleanWhether the poll is configured as a quiz.
detail.optionsarray of PollVoteOptionEvery poll option in presentation order, including options the voter did not select. The array can be empty when the upstream record contains no options.
detail.options[].option_uuidstringOption UUID.
detail.options[].option_descriptionstringOption description at the time of the vote.
detail.options[].is_selectedbooleanWhether the voter selected this option. At most one option is true; all options are false when the selection cannot be resolved upstream.
detail.options[].is_correctbooleanWhether this option is a correct quiz answer.

For poll_vote events, actor_uuid identifies the voter. author_uuid, topic_id, topic_name, and page_url are absent. Fields with null values are omitted from the request body.

When poll votes are not delivered

Viafoura does not send a poll_vote event when:

  • A signed-out visitor casts the vote. Poll-vote events require actor_uuid.
  • The upstream record has no payload or poll UUID.
  • The source topic message is not a vote.

Poll vote request

{
  "request_uuid": "3f578154-5e7b-470e-8f40-038f5c40d08c",
  "time": 1788381240669,
  "version": 1,
  "events": [
    {
      "event_uuid": "01a063d4-1d55-714c-8bdf-36f732b99465",
      "section_uuid": "00000000-0000-4000-8000-000000000bda",
      "content_container_uuid": "01a063d0-37d6-7b71-bf52-af42d0c01016",
      "content_uuid": "9f1c2f7e-0000-4000-8000-000000000001",
      "actor_uuid": "00000000-0000-4000-8000-0000000013b1",
      "message_type": "poll_vote",
      "action": "voted",
      "detail": {
        "poll_uuid": "9f1c2f7e-0000-4000-8000-000000000001",
        "poll_question": "Which option do you prefer?",
        "is_quiz": true,
        "options": [
          {
            "option_uuid": "aaaa0000-0000-4000-8000-000000000001",
            "option_description": "Option A",
            "is_selected": true,
            "is_correct": true
          },
          {
            "option_uuid": "bbbb0000-0000-4000-8000-000000000002",
            "option_description": "Option B",
            "is_selected": false,
            "is_correct": false
          }
        ]
      }
    }
  ]
}

User ban event fields

Receive user ban and unban notifications through events with message_type set to user_ban. Use action to distinguish between banned and unbanned events.

Both actions include ban information and user identifiers in detail. The affected user’s UUID appears in detail.author_uuid, rather than a top-level author_uuid field.

FieldTypeDescription
detail.author_uuidstringUUID of the user who is banned or unbanned.
detail.ban_uuidstringUUID identifying the ban.
detail.ban_typestringType of ban. The examples below show full.
detail.started_atnumberBan start timestamp in milliseconds.
detail.ends_atnumberBan end timestamp in milliseconds.
detail.is_permanentbooleanWhether the ban is permanent.
detail.message_to_userstringBan message addressed to the user.
detail.userobjectInformation identifying the affected user.
detail.user.emailstringUser’s email address.
detail.user.namestringUser’s name.
detail.user.viafoura_idobjectUser’s Viafoura identifiers.
detail.user.viafoura_id.uuidstringUser’s Viafoura UUID.
detail.user.viafoura_id.idnumberUser’s numeric Viafoura ID.
detail.user.external_idobjectUser’s external identity provider and identifier.
detail.user.external_id.providerstringIdentity provider, such as vf_email_login.
detail.user.external_id.idstringUser’s identifier within that provider.

Banned user request

This example shows a non-permanent full ban.

{
  "request_uuid": "3546bca5-22a9-4b45-807f-3b3ccd47dfb5",
  "time": 1792085996681,
  "version": 1,
  "events": [
    {
      "event_uuid": "2ebc566e-048f-424d-aa58-291f613ddd74",
      "time": 1792085996535,
      "section_uuid": "00000000-0000-4000-8000-01fb38b8132b",
      "message_type": "user_ban",
      "action": "banned",
      "detail": {
        "author_uuid": "00000000-0000-4000-8000-03373e1ad915",
        "ban_uuid": "00000000-0000-4000-8000-03a9dd78b46d",
        "ban_type": "full",
        "started_at": 1792085996000,
        "ends_at": 1792089596000,
        "is_permanent": false,
        "message_to_user": "Message to the user. You are full banned",
        "user": {
          "email": "[email protected]",
          "name": "Banned user",
          "viafoura_id": {
            "uuid": "00000000-0000-4000-8000-03373e1ad915",
            "id": 3535800031509
          },
          "external_id": {
            "provider": "vf_email_login",
            "id": "00000000-0000-4000-8000-03373e1ad915"
          }
        }
      }
    }
  ]
}

Unbanned user request

This example shows the same ban after the user is unbanned. The ban_uuid remains the same, while ends_at reflects the updated ban end timestamp.

{
  "request_uuid": "68a12492-f8e1-40c9-b9a6-c60a2eaa7ed7",
  "time": 1792086027455,
  "version": 1,
  "events": [
    {
      "event_uuid": "043e426a-6a95-4cb4-922b-e42c8a55f548",
      "time": 1792086027401,
      "section_uuid": "00000000-0000-4000-8000-01fb38b8132b",
      "message_type": "user_ban",
      "action": "unbanned",
      "detail": {
        "author_uuid": "00000000-0000-4000-8000-03373e1ad915",
        "ban_uuid": "00000000-0000-4000-8000-03a9dd78b46d",
        "ban_type": "full",
        "started_at": 1792085996000,
        "ends_at": 1792086027401,
        "is_permanent": false,
        "message_to_user": "Message to the user. You are full banned",
        "user": {
          "email": "[email protected]",
          "name": "Banned user",
          "viafoura_id": {
            "uuid": "00000000-0000-4000-8000-03373e1ad915",
            "id": 3535800031509
          },
          "external_id": {
            "provider": "vf_email_login",
            "id": "00000000-0000-4000-8000-03373e1ad915"
          }
        }
      }
    }
  ]
}

Integration Testing

  1. Sign up for RequestBin which is a free Webhook testing platform.
  2. Pipedream will provide a public callback URL. In Viafoura Admin → General → Notifications for the site you want to test, enter it as the Content data webhook URL, the User action webhook URL, or both, depending on which events you want to test (see below).
  3. You will also need to get your API key from your Pipedream account by going to your Pipedream Account Settings page.
  4. In the same settings, under Webhook authorization header (server-to-server callback authorization header), enter your Pipedream API key as Bearer <your API key> (see below).
  5. Contact your Viafoura Customer Success Manager to enable webhooks for your domain.

Done! Now when you perform actions that trigger webhook messages on the site you configured you will see the Webhook messages in Pipedream under the page for the Requestbin you created.


Did this page help you?