Webhooks

Webhooks are HTTP callbacks which can be used to send notifications when data in Contentful is changed. Common examples of integrations of Contentful with 3rd party systems are:

  • running a test suite on a CI service when the content model of a development environment was changed
  • deploying a production build when content was published or un-published
  • deploying a preview build when the draft state of content has changed
  • re-building a search index when content was updated
  • feeding assets into an image detection service when they are uploaded
  • trigger email or chat notifications due to editing activity

Actions on entities stored in Contentful that trigger webhooks

Webhooks are called as the result of an action against assets, entries or content types. Whenever a matching event occurs, Contentful sends a request to the URI defined in the webhook definition.

The following table summarizes the actions that Contentful offers for every resource type:

Type / Action create save auto_save archive unarchive publish unpublish delete
ContentType Yes Yes No No No Yes Yes Yes
Entry Yes Yes Yes Yes Yes Yes Yes Yes
Asset Yes Yes Yes Yes Yes Yes Yes Yes

Filtering of webhooks

Sometimes it is necessary to filter webhooks based on the properties of the entity that triggered the webhook. The most common examples are:

  • filter webhooks by environment ID (e.g. only trigger the pre-release test suite on a CI service for the environment with ID staging)
  • filter webhooks by entity ID (e.g. only trigger for a specific entry, asset or content type ID)
  • filter webhooks by content type ID (e.g. only trigger for entries of a specific content type ID)
Note: If a filter is evaluating a property which is not present on the entity, it will evaluate to false and not trigger the webhook. E.g. a webhook for topics Entry.publish and Asset.publish filters on a specific content type ID. As assets don't have a content type, all webhooks which are triggered by Asset.publish will be muted by the filter.

Create and configure a webhook

With the web app

In the top navigation bar, open SettingsWebhooks. Click Add webhook, configure the remote host, and click Save.

Creating a new webhook

You can configure the events that trigger a webhook at the bottom of the screen.

Configure triggering events

With the API

Create a webhook by sending the settings for the webhook in a body with your API call, for example, the following:

curl -X POST "https://api.contentful.com/spaces/<SPACE_ID>/webhook_definitions"
  -d '{"url": "<URL>", "name": "foo", "topics": ["*.*"], , "filters": []}'
  -H 'Authorization: Bearer <API_KEY>'
  -H 'Content-Type: application/vnd.contentful.management.v1+json'

This request will create a new webhook in the specified space with a url, name, it will trigger for all topics and will not apply any filtering constraints.

Topics

When creating a webhook you have to explicitly specify for which changes on your content (topics) you want your webhook called.

For example, your webhook could be called when:

  • Any content (of any type) is published.
  • Assets are deleted.

These filters have to be translated into a list of [Type].[Action] pairs, [*.publish, Asset.delete, Entry.*], and included in the payload that defines the webhook.

* is a wildcard character that can be used in place of any action or type. The combination *.* is also valid and means that your webhook is subscribed to all actions across all types.

Note: Using * allows your webhook to be called for future actions or types that didn't exist when the webhook was created or updated. Find more details on creating a webhook with the API in our reference docs.

Filters

The webhook definition holds a filters property. Filtering is a second step after defining the topics. Typical use cases for filtering are enabling a webhook only for a specific environment ID or entry ID. Without a filter, a webhook with the topic Entry.publish is triggering for all entries in the master environment of a space. By applying a filter we could make the webhook only trigger for specific entry IDs within a specific environment.

A filter is defined by adding one or multiple constraints to the webhook definition. The constraints consist of:

A property of the entity to evaluate:

  • sys.id
  • sys.environment.sys.id
  • sys.contentType.sys.id (for entries)

An operator / negation of an operator:

  • equals
  • in
  • regex

An argument for selected operator:

  • string value (e.g. "myEntryId") for equals
  • array of strings (e.g. ["idOne", "idTwo"]) for in
  • definition of a pattern (e.g. {"pattern": "^ci-.+$"} for regexp

So for example filtering a webhook to only trigger for two specific environments of ID master or development, the constraint would look like:

{
  ...,
  "filters": [
    {
      "in": [
        {
          "doc": "sys.environment.sys.id"
        },
        [
          "master",
          "development"
        ]
      ]
    }
  ]
}

Multiple constraints are connected with logical AND. Let's narrow the above's filter further down so it only triggers for an entry of ID foo in environments with ID master or development:

{
  ...,
  "filters": [
    {
      "in": [
        {
          "doc": "sys.environment.sys.id"
        },
        [
          "master",
          "development"
        ]
      ]
    },
    {
      "equals": [
        {
          "doc": "sys.id"
        },
        "foo"
      ]
    }
  ]
}

The last example uses a regular expression to match all environments which have an ID which uses a common prefix of ci- followed by 3-5 lowercase characters (e.g. ci-foo, ci-bar but not ci-foobar:

{
  ...,
  "filters": [
    {
      "regexp": [
        {
          "doc": "sys.environment.sys.id"
        },
        {
          "pattern": "^ci-[a-z]{3,5}$"
        }
      ]
    }
  ]
}

For a full reference on how filters are defined please refer to the webhooks section in the reference documentation of the Content Management API.

List webhooks in a space

With the web app

The Webhooks overview screen shows a list of the most recent webhook calls made, their status, possible errors, and the target URL.

Overview of webhooks

With the API

To list all webhooks in a space, use the following endpoint:

curl -X GET "https://api.contentful.com/spaces/<SPACE_ID>/webhook_definitions"
-H "Authorization: Bearer <API_KEY>"
-H "Content-Type: application/vnd.contentful.management.v1+json"

Find more details on listing the webhooks in a space with the API in our reference docs.

Activity log of a call

With the web app

Click the View details link of any webhook in the overview screen to get a detailed activity log, including the JSON and remote server response.

Activity log for webhooks

Detailed activity log of a webhook

With the API

The following endpoint will return the status of recent calls made by a webhook and any errors.

curl -X GET "https://api.contentful.com/spaces/<SPACE_ID>/webhooks/<WEBHOOK_ID>/calls"
-H "Authorization: Bearer <API_KEY>"
-H "Content-Type: application/vnd.contentful.management.v1+json"

Find more details on getting the activity log of a webhook with the API in our reference docs.

Auto save

The Contentful web app automatically saves documents you are working on after every change you make. Contentful keeps track of documents active in the web app and uses that information to call webhooks you have configured. Contentful considers documents edited in the last 20 seconds as active.

This means that, if you are editing an entry in the web app for one minute, and you have a webhook configured to be called for auto_save actions, that webhook will be called 3 times.

Local testing

For local testing we recommend RequestBin to inspect the sent webhooks or ngrok to build webhook consumers on your developer machine.