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 what a sample webhook notification might look like:

    • JSON
    { "data": { "items": [ { "id": "e5d575fe-9608-4523-a07d-e32d780bf92a", "codename": "where_does_coffee_come_from_", "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": "where_does_coffee_come_from_", "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. The properties of the Message object are duplicated in the HTTP headers prefixed with X-KC-Message. For example, the Project ID property is represented as the X-KC-Message-Project-Id HTTP header.

    PropertyDescriptionTypeNotes
    idThe notification's ID.string
    typeThe type of changed data.stringSee Types and operations.
    operationThe action performed on the data.stringSee Types and operations.
    api_nameSpecifies whether the notification's content is suited for the Delivery API or Management API.stringValid values: delivery_production, content_management
    project_idThe source project's ID.string
    webhook_urlPublicly available URL address of a webhook endpointstringValid address format: https://yourapp.com/webhook
    created_timestampFormatted UTC time and datestringValid format: YYYY-MM-DDTHH:MM:SSZ. ISO-8601Opens in a new window formatted string.
    • 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://myapp.com/webhook-endpoint" }
    "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://myapp.com/webhook-endpoint" }

    Data object for non-workflow events

    The Data object contains information about the modified content items and taxonomy groups.

    The notification contains information you can use with the Delivery API.

    PropertyDescriptionType
    itemsA list of content item objects.array of Item objects
    taxonomiesA list of taxonomy group objects.array of Taxonomy group objects
    • JSON
    "data": { "items": [ { "id": "e113e464-bffb-4fbd-a29b-47991d003732", "codename": "on_roasts", "language": "en-US", "type": "article" } ], "taxonomies": [ { "id": "4794dde6-f700-4a5d-b0dc-9ae16dcfc73d", "codename": "categories" } ] }
    "data": { "items": [ { "id": "e113e464-bffb-4fbd-a29b-47991d003732", "codename": "on_roasts", "language": "en-US", "type": "article" } ], "taxonomies": [ { "id": "4794dde6-f700-4a5d-b0dc-9ae16dcfc73d", "codename": "categories" } ] }

    Item object for non-workflow events

    PropertyDescriptionType
    idThe content item's internal ID.string
    codenameThe content item's codename.string
    languageThe language's codename.string
    typeThe content type's codename.string

    Taxonomy group object for non-workflow events

    PropertyDescriptionType
    idThe taxonomy group's internal ID.string
    codenameThe taxonomy group's codename.string

    Data object for workflow events

    The data object for workflow events contains information about the modified content items as well as information about the workflow steps from or to which the content items transitioned.

    PropertyDescriptionType
    itemsA list of content item objects.array of Item objects
    • 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

    PropertyDescriptionType
    itemThe content item's ID.Reference
    languageThe language's ID.Reference
    transition_fromThe ID of the workflow step the content item was moved from.Reference to a workflow step
    transition_toThe ID of the workflow step the content item was moved to.Reference to a workflow step

    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 are a few examples 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); ?>

    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.