Webhook transformations
Overview
By default every webhook call:
- uses the
POST
HTTP method - has the
Content-Type
header set toapplication/vnd.contentful.management.v1+json
- does not have the
Content-Length
header set - sends a predefined body depending on the triggering event (as described above)
If you control the code of your webhook receiver you can respond to the default webhook call appropriately by implementing a custom logic in your receiver. The situation is different if you try to call an API you don't control with a webhook: most likely the default webhook payload won't adhere to the format expected by the API.
The transformation
property of a webhook definition allows you to define:
- a custom HTTP method
- a custom
Content-Type
header - if automatically computed, a
Content-Length
header should be included. - a custom webhook call body that may or may not make use of the default webhook body.
transformation
property is an optional object containing the following properties. None of these properties are required.
transformation.method
can be one of:
POST
(default)GET
PUT
PATCH
DELETE
transformation.contentType
can be one of:
application/vnd.contentful.management.v1+json
(default)application/vnd.contentful.management.v1+json; charset=utf-8
application/json
application/json; charset=utf-8
application/x-www-form-urlencoded
application/x-www-form-urlencoded; charset=utf-8
Using the last two options will convert the JSON body to URL encoded form data.
transformation.includeContentLength
can be either true
or false
. If true
the Content-Length
header will be present with its value set to automatically computed byte length of the request body.
transformation.body
can be any arbitrary JSON data structure. It will be used as the webhook call body.
It's possible to use values from the original webhook payload in the transformed body. This can be achieved by JSON pointers in the body JSON. Depending on the referenced data either whole values or strings are resolved.
URL transformation
Webhook URLs can contain JSON pointers that are resolved to values from the original payload. The value resolution always follows the string template resolution logic. For example, a webhook defined as follows will result in a call to https://my-webhook-endpoint.com/my-entry-1
for an entity with ID my-entry-1
.
{
"name": "Dynamic URL",
"url": "https://my-webhook-endpoint.com/{ /payload/sys/id }"
}
Header transformation
Custom header values can contain JSON pointers as described below. This is achieved by JSON pointers that are resolved using the string template resolution logic.
The following header definition
{
...,
"headers": [
{ "key": "X-CTFL-Entity-ID", "value": "{ /payload/sys/id }" },
{ "key": "X-CTFL-Entity-Type", "value": "{ /payload/sys/type }" }
]
}
will result in two headers on the actual webhook call if the webhook was triggered by a change of entry 42:
X-CTFL-Entity-ID: 42
X-CTFL-Entity-Type: Entry
Secret and HTTP Basic Auth headers are not transformed. Also, the header keys are not transformed.
Resolution strategies
Resolving a whole value
- In your data structure, introduce a string value that starts with
{
and ends with}
in a place you want to resolve the original value - In between curly braces put an absolute JSON pointer to the property you want to resolve; the original webhook body is stored in the
payload
top-level namespace - The string value containing a pointer will be replaced with the resolved value
For example, given the following original payload:
{
"sys" {
"id": "entry-id"
"type": "Entry"
},
"fields": {
"title": {
"en-US": "hello world"
}
}
}
And the following body transformation:
{
"entryId": "{ /payload/sys/id }",
"title": "{ /payload/fields/title }"
}
Your webhook will be called with:
{
"entryId": "entry-id",
"title": {
"en-US": "hello world"
}
}
Using string templates
- In your data structure, introduce a string value that contains an absolute JSON pointer to the property you want to resolve, wrapped with
{
and}
- The original webhook body is stored in the
payload
top-level namespace - JSON pointers will be replaced with resolved values
- All values, including complex ones, will be stringified
For example, given the following original payload:
{
"sys": {
"id": "entry-id",
"type": "Entry"
},
"fields": {
"title": {
"en-US": "hello world"
}
}
}
And the following body transformation:
{
"entityInfo": "Entity of type { /payload/sys/type } with ID { /payload/sys/id }",
"title": "Entity title is { /payload/fields/title/en-US }",
"stringified": "Let's try to stringify an object: { /payload/fields/title }"
}
Your webhook will be called with:
{
"entityInfo": "Entity of type Entry with ID entry-id",
"title": "Entity title is hello world",
"stringified": "Let's try to stringify an object: {\"en-US\":\"hello world\"}"
}
Helpers
In some cases, there can be a need for trimming or slightly modifying certain fields before delivering them to the webhook target. Contentful provides numerous helpers that can be used at the transformation level. For example:
{
"content": "{ first-paragraphs 2 /payload/fields/content/en-US }",
}
Above-mentioned example limits the content
field with first two paragraphs. If the content field has more than two paragraphs, the rest of the text gets trimmed. In addition to
trimming content, helpers are useful in modifying or refining content. Following is another transformation, using the strip-stop-words
helper:
{
"keywords": "{ strip-stop-words /payload/fields/content }",
}
The above transform filters out stop words and delivers only the keywords in the content
field. For example:
Art is the expression or application of human creative skill and imagination
becomes:
art expression application human creative skill imagination
Refer to the table below to see the full list of available functions:
Helper name | Parameter | Description |
---|---|---|
first-chars | Number | Selects first n characters of the field. Example: { first-chars 6 /payload/fields/content/en-US } |
first-words | Number | Selects first n words of the field. Example: { first-words 12 /payload/fields/content/en-US } |
first-paragraphs | Number | Selects first n paragraphs of the field. Example: { first-paragraphs 3 /payload/fields/content/en-US } |
strip-stop-words | - | Strip out stop words (only English is supported). Example: { strip-stop-words /payload/fields/content/en-US } |
strip-markdown | - | Strip out Markdown markup. Example: { strip-markdown /payload/fields/content/en-US } |
stringify | - | Stringify the value pointed to. Example: { stringify /payload/fields } |
Transformation context
When transforming request body, URL, and headers, JSON pointers are used to resolve values. Values are resolved from a context object. Currently the context object has the following properties:
payload
contains the original webhook payloadtopic
is a string containing the webhook topicuser
is a stripped-down version of aUser
entity for the user who executed action triggering the webhook call; the only available pointer is{ /user/sys/id }