Skip to main content

While creating or updating a webhook, Contensis allows you to send a JSON payload to the specified URL whenever a selected event occurs.

Payload types

We support different payload types to give you flexibility and support different development scenarios.

  • Default payloads are an ideal way for a development team to get the barebones information they require about a change in a resource. Once the endpoint is notified, the appropriate API calls and data mapping can take place in the application.
  • Custom payloads offer the opportunity to reduce the need for a middleware application and provide the endpoint with the data and structure that it expects. This can include any data from the selected resource that would be available from the Management API. This is especially useful for services that have an incoming webhook feature like Slack.
  • Empty payloads can be useful if you are providing the the information you require through a templated webhook endpoint URL.

Default payloads

When you add a topic to a webhook we automatically provide a default payload template that will be sent with the webhook. The payload template varies depending on the topic that has been set.

Entries example

The following example outlines the payload that will be sent when the entries topic has been added to a webhook. The webhook payload is structured in the JSON format.

JSON
{
    "eventId": "{{event.id}}",
    "eventName": "{{event.name}}",
    "subscriptionId": "{{event.subscriptionId}}",
    "datetime": "{{event.dateTime | date.to_string '%Y-%m-%dT%H:%M:%S.%LZ'}}",
    "invokedBy": {
        "username": "{{user.username}}",
        "firstName": "{{user.firstName}}",
        "lastName": "{{user.lastName}}"
    },
    "resource": {
        "id": "{{event.resourceId}}",
        "type": "entry",
        "projectId": "{{resource.sys.projectId}}",
        "contentTypeId": "{{resource.sys.contentTypeId}}",
        "title": "{{resource.entryTitle}}",
        "language": "{{resource.sys.language}}",
        "url": "{{event.resourceUrl}}"
    }
} 

Let's walk through each object in a typical webhook payload template. As you'll see in the example, we use the Liquid syntax to define the output of the webhook. Each value in the curly braces represents a value of a Contensis resource which is replaced when the webhook is sent.

ElementPropertyTypeDescription
event
idstringUnique ID for the specific webhook event. Automatically assigned by Contensis.
eventNamestringThe name of the event that triggered the webhook, e.g. Created, Updated, Published, Unpublished, workflowStateChange, WorkflowEventRaised.
subscriptionIdGuidThe ID of the event subscription.
dateTimeDateTimeThe date and time that the event was raised. Formatted to UTC string.
resourceTypestringThe resource type, in this example it has a type of entry.
resourceUrlstringThe url of the resource in the Management or Security APIs.
user
idstringUnique ID for the user
usernamestringThe username of the person who triggered the webhook being sent.
firstNamestringThe first name of the person who triggered the webhook being sent, if available from their user profile.
lastNamestringThe last name of the person who triggered the webhook being sent, if available from their user profile.
resource
entryTitlestringThe title (when the resource is an asset or entry).
entryDescriptionstringThe description (when the resource is an asset or entry).
sys.idThe unique ID of the resource.
sys.dataFormatThe resource type, in this example it has a type of entry.
sys.projectIdThe API ID of the project that the resource relates to.
sys.contentTypeIdThe Content type ID that the entry or asset is based on.
sys.languageThe language code of the entry.

Custom payloads

You can customise the default template, or completely replace the template with your own to meet the needs of your endpoint. This can include any data from the selected resource that would be available from the Management API.

In addition to the Management API properties, you can use resource.sys.uri, which provides the relative path to a resource when it’s attached to a node in Siteview. This is particularly useful if you prepend your website address, allowing you to create a direct link to the resource on your published or preview site.

Liquid templating provides a way to construct really flexible payloads without requiring additional API calls.

Example

The following example demonstrates a custom payload for Slack using their Block Kit syntax.

JSON
{
	"text": "{{resource.entryTitle}} has been {{event.name}}",
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "{% assign handle = event.name %} {% case handle %} {% when "workflowStateChanged" %}:page_with_curl: An entry has been transitioned to the {{resource.sys.workflow.state}} workflow state.{% else %}:page_with_curl: An entry has been {{event.name}}{% endcase %}",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "*Entry title:*\n<https://cms-{{event.alias}}.cloud.contensis.com/app/projects/{{resource.sys.projectId}}/entries/{{resource.sys.id}}?language={{resource.sys.language}}>\n\n{% if resource.entryDescription %}*Entry description:*\n {{resource.entryDescription}}{% endif %}"
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"fields": [
				{
					"type": "mrkdwn",
					"text": "*Content type:*\n{{resource.sys.contentTypeId}}"
				},
				{
					"type": "mrkdwn",
					"text": "*Last updated:*\n{{event.dateTime | date.to_string "%Y-%m-%d at %H:%M"}}"
				},
				{
					"type": "mrkdwn",
					"text": "*Updated by:*\n{{resource.sys.version.modifiedBy}}"
				},
				{
					"type": "mrkdwn",
					"text": "*Entry ID:*\n{{resource.sys.id}}"
				}
			]
		},
		{
			"type": "divider"
		},
		{
			"type": "actions",
			"elements": [
				{
					"type": "button",
					"text": {
						"type": "plain_text",
						"text": ":pencil2: Edit entry",
						"emoji": true
					},
					"value": "edit_entry",
					"url": "https://cms-{{event.alias}}.cloud.contensis.com/app/projects/{{resource.sys.projectId}}/entries/{{resource.sys.id}}?language={{resource.sys.language}}"
				}
			]
		}
	]
}

Liquid examples

Checking if a value is empty

Nil is a special empty value that is returned when Liquid code has no results.

In the following example, if an entryDescription does not exist (that is, resource.entryDescription returns nil), Liquid will not print the text.

Liquid
{% if resource.entryDescription %}
	*Entry description:* {{resource.entryDescription}}
{% endif %}

The above example has been formatted for readability. As payloads in webhooks are in JSON, this example would not be a valid string and would fail JSON validation.

Instead you'd have to format the example without any returns as below.

Liquid
{% if resource.entryDescription %}*Entry description:* {{resource.entryDescription}}{% endif %}

case/when

Creates a switch statement to compare a variable with different values. case initialises the switch statement, and when compares its values.

In this example, the output will be determined when the variable called handle is "equal" to the value of workflowStateChanged. If it does not match it will output the text in the else clause.

Liquid
{% assign handle = event.name %}
	{% case handle %}
	{% when "workflowStateChanged" %}
		An entry has been transitioned to the {{ resource.sys.workflow.state }} workflow state.
	{% else %}
		An entry has been {{ event.name }}
{% endcase %}  

Again for this example to work in the payload you'd need to ensure it validates as a string, as formatted below.

Liquid
{% assign handle = event.name %} {% case handle %} {% when "workflowStateChanged" %}An entry has been transitioned to the {{ resource.sys.workflow.state }} workflow state.{% else %}An entry has been {{ event.name }}{% endcase %}

Custom Liquid filters

Filters are simple methods that modify the output of numbers, strings, variables and objects. They are placed within an output tag {{ }} and are denoted by a pipe character |.

We have provided the following custom Liquid filters to use with webhook payloads.

to_json and to_xml

You can use these filters to render part of a resource, or the entire resource to JSON or XML.

The following example will output the entire resource e.g. an entry to JSON

Liquid
{{ resource | to_json }}

Where as this example will output the field of a resource to XML.

Liquid
{{ resource.somefield | to_xml }}

Empty payloads

In some cases you may want to send an empty payload for your webhook. You can do this by checking the Do not send payload checkbox above the payload field.

XML payloads

Whilst our webhooks services have been designed to deliver JSON payloads by default you can also define your payload as XML.

You will need to edit the payload as normal and replace the JSON structure as XML. In addition to this you'll need to set a header declaring the content-type as application/xml or the particular flavour of XML you require.

Still need help?

If you still need help after reading this article, don't hesitate to reach out to the Contensis community on Slack or raise a support ticket to get help from our team.
New support request