Using webhooks for automatic updates

See how to set up webhooks for your integrations with Kentico Cloud.

In this tutorial, you'll see how webhooks allow you to integrate Kentico Cloud with other software applications and automate your processes. Think of webhooks as programmatic notifications that let your application know when something changes inside your Kentico Cloud project.

For example, when a new content item is published your application can automatically react in numerous ways, such as:

  • Invalidating the cache of your app to make sure users see the latest content.
  • Updating a search index of your project's content.
  • Triggering a new build process and redeploying your application.
  • Notifying your team by sending an email, posting a message to a Slack channel or moving a card inside Trello.
  • Scheduling a social media post featuring the newly published content item.

How webhooks work in a nutshell

  • When something changes inside your project, we send an HTTP POST request to a URL you have specified.
  • The payload of the request contains structured information about the type of change and the affected content items.
  • The header of the request contains a secret token you can use to authenticate the message.
  • Your application's endpoint at the specified URL must process the request - parse the information in the payload and react accordingly.
  • If your application is down or fails to process the request correctly, we send it again according to the retry policy.

Let's go through the process in more detail.

Creating a webhook

To register a new webhook in your project:

  1. In Kentico Cloud, choose Project settings from the app menu.
  2. Under Development, choose Webhooks.
  3. Click Create new Webhook.
  4. Type a name for the webhook. For example, Purge cache.
  5. Enter a publicly available URL address of your webhook endpoint, such as
  6. Click Save.
Registering a webhook in Kentico Cloud

Registering a webhook in Kentico Cloud

Now, whenever your published content changes, we will send a notification to your webhook endpoint.

When webhooks are called

Webhooks are called as a result of actions done by users in a Kentico Cloud project. Whenever an action affects already published content, you get a notification.

Here are a few examples of the actions that can trigger a webhook:

  • A user changes the description of an asset.
  • A content contributor rewrites some text in a content item.
  • A content contributor renames a few terms in a Taxonomy group.

For the full list of actions, see the list of Types and operations in our API reference.

Note: Updates to content made using the Content Management API can't trigger webhooks. The CM API can only work with content that is not published.

Receiving notifications

Once the webhook is registered, we will start sending HTTP POST notifications to the provided webhook URL. Receiving your notifications might take a few minutes or possibly even longer.

Note that the notifications may sometimes come in batches because the content changes are processed dynamically based on load.

Webhook call model

The notifications come in the form of a JSON object with two attributes: message and data. The message tells you why the notification came and the data tells you which content items and taxonomy groups were affected.

You can find the full notification model description in the API reference.

  "message": {
    "id": "77e3661a-6e8f-4d8c-963f-ccb4dbe08333",
    "type": "taxonomy",
    "operation": "upsert",
    "api_name": "delivery_production",
    "project_id": "975bf280-fd91-488c-994c-2f04416e5ee3"
  "data": {
    "items": [
        "language": "en-US",
        "codename": "hario_v60",
        "type": "brewer"
        "language": "en-US",
        "codename": "aeropress",
        "type": "brewer"
    "taxonomies": [
        "codename": "manufacturer"
using System;
using Newtonsoft.Json;

public class KenticoCloudWebhookModel
    public Message Message { get; set; }

    public Data Data { get; set; }

public class Message
    public Guid Id { get; set; }

    public string Type { get; set; }

    public string Operation { get; set; }

    public string ApiName { get; set; }

    public Guid ProjectId { get; set; }

public class Data
    public Item[] Items { get; set; }

    public Taxonomy[] Taxonomies { get; set; }

public class Item
    public string Language { get; set; }

    public string Type { get; set; }

    public string Codename { get; set; }

public class Taxonomy
    public string Codename { get; set; }
import com.fasterxml.jackson.annotation.JsonProperty;

public class KenticoCloudWebhookModel {
    Message message;

    Data data;

    public Message getMessage() { return message; }

    public Data getData() { return data; }

public class Message {
    String id;

    String type;

    String operation;

    String apiName;

    String projectId;

    public String getId { return id; }

    public String getType { return type; }

    public String getOperation { return operation; }

    public String getApiName { return apiName; }

    public String getProjectId { return projectId; }

public class Data {
    List<Item> items;

    List<Taxonomy> taxonomies;

    public List<Item> getItems { return items; }

    public List<Taxonomy> getTaxonomies { return taxonomies; }

public class Item {
    String language;

    String type;

    String codename;

    public String getLanguage { return language; }

    public String getType { return type; }

    public String getCodename { return codename; }

public class Taxonomy {
    String codename;

    public String getCodename { return codename; }

Verifying notifications

To verify the authenticity of the notifications, you need to generate a hash using the body of the notification and the secret key (you'll find the key in the configuration details of your webhook).

The calculated hash should match the notification signature in the X-KC-Signature header that is sent with each notification. For example, a signature can look like this fRbrQ1lpBSRB9T3MckJ51HDdjQ8UuV3WnjqKqirSpW8=. The signature is a base64 encoded string generated using a hash-based message authentication code (HMAC) with SHA-256.

For more examples on generating verification hashes, see the code samples in our API reference.

Reacting to notifications

Once you have received and verified the message, you can react to it and use the provided information. You might consider using webhooks for clearing the cache of your app, triggering a build process, or scheduling social media posts. See our blog posts for some inspiration.

Worked examples

Learn how to integrate webhooks into your app's workflow from worked examples in our blog posts.

Getting the latest content

After you get a notification about changed content, you might want to explicitly request the new content from the Delivery API. You can do this by sending a standard request to the Delivery API with the X-KC-Wait-For-Loading-New-Content header.

curl --request GET \
  --url \
  --header 'X-KC-Wait-For-Loading-New-Content: true' \
  --header 'content-type: application/json'
using KenticoCloud.Delivery;

// Initializes a client that retrieves the latest version of published content
IDeliveryClient client = DeliveryClientBuilder
    .WithOptions(builder => builder

// Gets a content item
// Create strongly typed models according to
DeliveryItemResponse<object> response = await client.GetItemAsync<object>("on_roasts");
const KenticoCloud = require('kentico-cloud-delivery');

// Create strongly typed models according to
class Article extends KenticoCloud.ContentItem {
    constructor() {
const deliveryClient = new KenticoCloud.DeliveryClient({
    projectId: '975bf280-fd91-488c-994c-2f04416e5ee3',
    typeResolvers: [
        new KenticoCloud.TypeResolver('article', () => new Article())

    .queryConfig({ waitForLoadingNewContent: true })
    .subscribe(response => console.log(response));
import { ContentItem, DeliveryClient, Fields, TypeResolver } from 'kentico-cloud-delivery';

// Create strongly typed models according to
export class Article extends ContentItem {
    public title: Fields.TextField;
    public summary: Fields.TextField;
    public post_date: Fields.DateTimeField;
    public teaser_image: Fields.AssetsField;
    public related_articles: Article[];

const deliveryClient = new DeliveryClient({
    projectId: '975bf280-fd91-488c-994c-2f04416e5ee3',
    typeResolvers: [
      new TypeResolver('article', () => new Article)

    .queryConfig({ waitForLoadingNewContent: true })
    .subscribe(response => console.log(response));

DeliveryOptions deliveryOptions = new DeliveryOptions();

DeliveryClient client = new DeliveryClient(deliveryOptions);

ContentItemResponse item = client.getItem("on_roasts");
import com.kenticocloud.delivery_core.*;
import com.kenticocloud.delivery_rx.*;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;

// Prepares an array to hold strongly-typed models
List<TypeResolver<?>> typeResolvers = new ArrayList<>();

// Registers the type resolver for articles
typeResolvers.add(new TypeResolver<>(Article.TYPE, new Function<Void, Article>() {
    public Article apply(Void input) {
        return new Article();

// Prepares the DeliveryService configuration object
String projectId = "975bf280-fd91-488c-994c-2f04416e5ee3";
IDeliveryConfig config = DeliveryConfig.newConfig(projectId)
                .withDefaultQueryConfig(new QueryConfig(true, false))

// Initializes a DeliveryService for Java projects
IDeliveryService deliveryService = new DeliveryService(config);

// Gets specific elements of an article using a simple request
Article article = deliveryService.<Article>item("on_roasts")

// Gets specific elements of an article using RxJava2
    .subscribe(new Observer<DeliveryItemResponse<Article>>() {
        public void onSubscribe(Disposable d) {

        public void onNext(DeliveryItemResponse<Article> response) {
            // Gets the article
            Article article = response.getItem();

        public void onError(Throwable e) {

        public void onComplete() {

// Defined by Composer to include required libraries
require __DIR__ . '/vendor/autoload.php';

use KenticoCloud\Delivery\DeliveryClient;

$client = new DeliveryClient("<YOUR_PROJECT_ID>", null, true);

$item = client->getItem('on_roasts');

Including the header will cause the Delivery API to explicitly fetch new content. Without the header, the Delivery API might return stale content (if cached by the CDN) for performance reasons while fetching latest content. To find out more, see Serving stale content in the Fastly documentation.

Retry policy

If your application responds with a 20X HTTP status code, the notification delivery is considered successful. Any other status code or a request timeout (which occurs after 60 seconds) will result in a retry policy.

On the first unsuccessful delivery, we will try to send the notification again in 1 minute. If the delivery is unsuccessful, the delay between resending the notification increases exponentially to a maximum of 1 hour. The specific delay intervals are (in minutes): 1, 2, 4, 8, 16, 32, 60. When the delay reaches 60 minutes, we try to deliver the notification every hour for up to 3 days, after which the notification is removed from the queue.

Email notifications

We will send email notifications to users with the Manage APIs capability in these cases:

  • Notification delivery repeatedly failing for 1 hour. This email is sent only once for each registered webhook.
  • Notification delivery repeatedly failing for 3 days. Note that we will not attempt to deliver the notification again.
  • Notification delivery was successful after failed attempts. This email is only sent if you previously received an email notification about a failed delivery.

Note: All notifications are delivered in the order they were created. For example, if a notification is successfully delivered after 4 minutes, the notifications created after it will follow in the original order.

Debugging webhooks

If you get an email that a webhook is failing, you might want to know more about that webhook and what the problem is. For that, you can find more information inside Kentico Cloud in your list of webhooks under Project settings -> Webhooks.

For an overview of the health of your webhooks, each webhook in your list has a colored status next to its name:

  • Light grey – Ready for message. This appears for newly created webhooks before any change to published content has been made (so notification has been sent).
  • Green – Working. This appears for webhooks that have properly delivered notifications.
  • Red – Failing. This appears for webhooks that have not been delivered properly (received a response other than a 20X HTTP status code). These webhook notifications are still being sent based on the retry policy.
  • Grey – Dead. This appears for webhooks where delivery has repeatedly failed and the retry policy has been exhausted so no more notifications will be sent.

For more information about each webhook, click on Debugging. You'll find a list of all attempts at delivering a message, sorted from newest to oldest. Each attempt will show:

  • The HTTP response code (e.g., 200 for delivered messages or 404 for missing URLs) from the most recent delivery attempt. For failed deliveries, you'll also see
    • How many times the delivery has been attempted
    • A button (</>) to see the most recent response
  • The date and time when the most recent delivery attempt was made
  • A button (</>) to see the content of the sent notification with the chance to copy it

What's next?