Skip navigation

Webhooks reference

Get notifications to your webhook endpoint whenever the content in your project changes. You can configure triggers for each webhook in your project to get notified only about specific events, such as unpublishing content items or moving items to a specific workflow step.

Table of contents

    Notification object model

    The notification consists of the objects, Data and Message. Here's an example of a webhook notification:

    • JSON
    { "data": { "items": [ { "id": "e5d575fe-9608-4523-a07d-e32d780bf92a", "codename": "this_article_changed", "language": "en-US", "type": "article" } ], "taxonomies": [ { "id": "4794dde6-f700-4a5d-b0dc-9ae16dcfc73d", "codename": "personas" } ] }, "message": { "id": "e1b372a2-1186-4929-b370-904c59f060b7", "project_id": "bf32e7ab-85c3-0073-47b9-90838a8462de", "type": "taxonomy", "operation": "upsert", "api_name": "delivery_production", "created_timestamp": "2019-07-18T10:52:33.1059256Z", "webhook_url": "https://myapp.com/webhook-endpoint" } }
    { "data": { "items": [ { "id": "e5d575fe-9608-4523-a07d-e32d780bf92a", "codename": "this_article_changed", "language": "en-US", "type": "article" } ], "taxonomies": [ { "id": "4794dde6-f700-4a5d-b0dc-9ae16dcfc73d", "codename": "personas" } ] }, "message": { "id": "e1b372a2-1186-4929-b370-904c59f060b7", "project_id": "bf32e7ab-85c3-0073-47b9-90838a8462de", "type": "taxonomy", "operation": "upsert", "api_name": "delivery_production", "created_timestamp": "2019-07-18T10:52:33.1059256Z", "webhook_url": "https://myapp.com/webhook-endpoint" } }

    The structure of the Data object differs based on the type of event that caused the notification to fire.

    • The Data object for non-workflow events (that is events related to content items and taxonomy groups) contains information in the format used by the Delivery API.
    • The Data object for workflow-related events (that is events related to changes of workflow steps) contains information in the format used by the Management API.

    The structure of the Message object is the same for all events.

    Message object (for all event types)

    The Message object contains information about the origin of the notification.

    • JSON
    "message": { "id": "b357fa9f-15ad-422d-84c7-b6bebc512c50", "project_id": "11a3492b-cd32-0054-51d2-8234ec4244a6", "type": "content_item_variant", "operation": "change_workflow_step", "api_name": "content_management", "created_timestamp": "2019-07-18T15:07:17.6823904Z", "webhook_url": "https://example.com/invalidate-cache" }
    "message": { "id": "b357fa9f-15ad-422d-84c7-b6bebc512c50", "project_id": "11a3492b-cd32-0054-51d2-8234ec4244a6", "type": "content_item_variant", "operation": "change_workflow_step", "api_name": "content_management", "created_timestamp": "2019-07-18T15:07:17.6823904Z", "webhook_url": "https://example.com/invalidate-cache" }
    • id (string): The notification's ID.
    • type (string): The type of changed data. For more details, see Types and operations.
    • operation (string): The action performed on the data. For more details, see Types and operations.
    • api_name (string): Specifies if the notification is suited for the Delivery API (delivery_production) or Management API (content_management).
    • project_id (string): The source project's ID.
    • webhook_url (string): Publicly available URL address of your webhook endpoint.
    • created_timestamp (string): ISO-8601Opens in a new window formatted UTC time and date, for example, YYYY-MM-DDTHH:MM:SSZ.

    The properties of the Message object are also duplicated in the HTTP headers with the X-KC-Message prefix. For example, the project_id property is represented as the X-KC-Message-Project-Id header.

    Data object for events related to Delivery API

    The Data object contains metadata of the modified content items and taxonomy groups. The notification contains information you can use with the Delivery API.

    • JSON
    "data": { "items": [ { "id": "e113e464-bffb-4fbd-a29b-47991d003732", "codename": "my_article", "language": "en-US", "type": "article" } ], "taxonomies": [ { "id": "4794dde6-f700-4a5d-b0dc-9ae16dcfc73d", "codename": "categories" } ] }
    "data": { "items": [ { "id": "e113e464-bffb-4fbd-a29b-47991d003732", "codename": "my_article", "language": "en-US", "type": "article" } ], "taxonomies": [ { "id": "4794dde6-f700-4a5d-b0dc-9ae16dcfc73d", "codename": "categories" } ] }
    • items (array): A list of Item objects for each modified content item.
    • taxonomies (array): A list of Taxonomy group objects.

    About the first item in the items array

    When the notification's type is content_item_variant and its operation is archive, restore, publish, or unpublish, then the first item in the items array designates the content item that caused the notification to be sent. For example, if the operation is unpublish, then the first item in the array was unpublished and the other items were affected by this operation.

    Item object for non-workflow events

    • id (string): The content item's internal ID.
    • codename (string): The content item's codename.
    • language (string): The language's codename.
    • type (string): The content type's codename.

    Taxonomy group object for non-workflow events

    • id (string): The taxonomy group's internal ID.
    • codename (string): The taxonomy group's codename.

    Data object for workflow events

    The data object for workflow events contains an array of Item objects with information about the modified content items as well as information about the workflow steps from or to which the content items transitioned.

    • JSON
    "data": { "items": [ { "item": { "id": "65f05e0f-40c3-436b-a641-e2d4cae16e46" }, "language": { "id": "00000000-0000-0000-0000-000000000000" }, "transition_from": { "id": "eee6db3b-545a-4785-8e86-e3772c8756f9" }, "transition_to": { "id": "03b6ebd3-2f49-4621-92fd-4977b33681d1" } } ] }
    "data": { "items": [ { "item": { "id": "65f05e0f-40c3-436b-a641-e2d4cae16e46" }, "language": { "id": "00000000-0000-0000-0000-000000000000" }, "transition_from": { "id": "eee6db3b-545a-4785-8e86-e3772c8756f9" }, "transition_to": { "id": "03b6ebd3-2f49-4621-92fd-4977b33681d1" } } ] }

    Item object for workflow events

    • item (Reference to content item): The content item's ID.
    • language (Reference to language): The language's ID.
    • transition_from (Reference to workflow step): The ID of the workflow step the content item was moved from.
    • transition_to (Reference to workflow step): The ID of the workflow step the content item was moved to.

    Types and operations

    The values of the type and operation properties in the Message object tell you what changed in your project. type specifies the type of the modified object (such as an asset or taxonomy group) while operation specifies the performed action.

    Here is a list of the possible type and operation pairs along with descriptions of what changed in each case:

    • asset type
      • upsert operation – For one or more assets used in published content items, the asset description was changed. 
    • content_item type
      • upsert operation – For published content item with a new version, the item's name was changed. May also occur when changing the sitemap location of a published content item.
    • content_item_variant type
      • archive operation – The language variant of a content item was deleted.
      • change_workflow_step operation – The language variant of a content item was moved to a different workflow step.
      • restore operation – The language variant of a content item was restored in a specific language after deletion.
      • publish operation – The language variant of a content item was published.
      • unpublish operation – The language variant of a content item was unpublished.
    • content_type type
      • upsert operation – The content type of published content items was changed.
    • language_settings type
      • upsert operation – The language's codename was changed.
    • project type
      • archive operation – The project was archived.
      • restore operation – The project was restored.
    • sitemap type
      • upsert operation – The project's sitemap was modified.
    • taxonomy type
      • archive operation – A taxonomy group was deleted.
      • restore operation – A taxonomy group was restored after deletion. 
      • upsert operation – A taxonomy group was changed.

    Notification signatures

    The notifications sent to your webhook URL come with the X-KC-Signature header. This header contains a checksum of the JSON payload that you can use to verify the authenticity of the notification. The signature is a base64Opens in a new window encoded hash generated using a HMACOpens in a new window-SHA-256Opens in a new window with a secret key.

    • HTTP
    X-KC-Signature: fRbrQ1lpBSRB9T3MckJ51HDdjQ8UuV3WnjqKqirSpW8=
    X-KC-Signature: fRbrQ1lpBSRB9T3MckJ51HDdjQ8UuV3WnjqKqirSpW8=

    To verify the received notification, use the JSON payload (that is the raw body of the notification) and the generated webhook Secret as the secret for the HMAC function. The secret is unique for each created webhook in your project. Once you generate a hash, compare it with the value of the X-KC-Signature header.

    Here's an example of generating the hash and verifying the notification.

    • Java
    // Tip: Find more about Java/JavaRx SDKs at https://docs.kontent.ai/java import javax.crypto; import javax.crypto.spec; import javax.xml.bind; public static String generateHash(String message, String secret) throws Exception { Mac sha256Hmac = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); sha256Hmac.init(secretKeySpec); return Base64.getEncoder().encodeToString(sha256Hmac.doFinal(message.getBytes(StandardCharsets.UTF_8))); }
    // Tip: Find more about Java/JavaRx SDKs at https://docs.kontent.ai/java import javax.crypto; import javax.crypto.spec; import javax.xml.bind; public static String generateHash(String message, String secret) throws Exception { Mac sha256Hmac = Mac.getInstance("HmacSHA256"); SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); sha256Hmac.init(secretKeySpec); return Base64.getEncoder().encodeToString(sha256Hmac.doFinal(message.getBytes(StandardCharsets.UTF_8))); }
    • JavaScript
    // Tip: Find more about JS/TS SDKs at https://docs.kontent.ai/javascript const crypto = require('crypto'); const isValidSignature = (req, secret) => { const givenSignature = req.headers['x-kc-signature']; const computedSignature = crypto.createHmac('sha256', secret) // Note: Use raw body data from the request, for example, by using body-parser .update(req.body) .digest(); return crypto.timingSafeEqual(Buffer.from(givenSignature, 'base64'), computedSignature); }
    // Tip: Find more about JS/TS SDKs at https://docs.kontent.ai/javascript const crypto = require('crypto'); const isValidSignature = (req, secret) => { const givenSignature = req.headers['x-kc-signature']; const computedSignature = crypto.createHmac('sha256', secret) // Note: Use raw body data from the request, for example, by using body-parser .update(req.body) .digest(); return crypto.timingSafeEqual(Buffer.from(givenSignature, 'base64'), computedSignature); }
    • C#
    // Tip: Find more about .NET SDKs at https://docs.kontent.ai/net using System; using System.Security.Cryptography; using System.Text; private static string GenerateHash(string message, string secret) { secret = secret ?? ""; UTF8Encoding SafeUTF8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); byte[] keyBytes = SafeUTF8.GetBytes(secret); byte[] messageBytes = SafeUTF8.GetBytes(message); using (HMACSHA256 hmacsha256 = new HMACSHA256(keyBytes)) { byte[] hashmessage = hmacsha256.ComputeHash(messageBytes); return Convert.ToBase64String(hashmessage); } }
    // Tip: Find more about .NET SDKs at https://docs.kontent.ai/net using System; using System.Security.Cryptography; using System.Text; private static string GenerateHash(string message, string secret) { secret = secret ?? ""; UTF8Encoding SafeUTF8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); byte[] keyBytes = SafeUTF8.GetBytes(secret); byte[] messageBytes = SafeUTF8.GetBytes(message); using (HMACSHA256 hmacsha256 = new HMACSHA256(keyBytes)) { byte[] hashmessage = hmacsha256.ComputeHash(messageBytes); return Convert.ToBase64String(hashmessage); } }
    • PHP
    <?php $givenSignature = $_SERVER['HTTP_X_KC_SIGNATURE']; $computedSignature = base64_encode(hash_hmac('sha256', $json_message, $secret, true)); $result = hash_equals($givenSignature, $computedSignature); ?>
    <?php $givenSignature = $_SERVER['HTTP_X_KC_SIGNATURE']; $computedSignature = base64_encode(hash_hmac('sha256', $json_message, $secret, true)); $result = hash_equals($givenSignature, $computedSignature); ?>

    Try our webhook helper library

    You can use the Kontent webhook helper library to quickly verify the webhook notifications and their signatures. The library is available as @kentico/kontent-webhook-helper npm packageOpens in a new window and helps you avoid common problems when calculating the hash.

    Outbound IP addresses

    If your application runs behind a firewall, you might need to add rules for specific IP addresses so that your app can receive the notifications.

    Kentico Kontent may send webhook notifications from the following IP addresses.

    • 13.69.68.1
    • 40.115.59.104
    • 104.47.142.248
    • 104.47.143.150
    • 104.47.144.212
    • 104.47.161.32
    • 104.47.161.68
    • 104.47.161.137

    Note: The list is SUBJECT TO CHANGE.

    What's next?

    Learn how you can set up webhooks for your project and app.