General concepts > Webhooks

Webhooks

If you need to know when data has changed in one of your projects, you can create customized webhooks to get HTTP notifications as soon as the events occur.

For example, you might use webhooks as the basis to:

  • Integrate/sync DatoCMS data with third-party systems (Snipcart, Shopify, Algolia, etc.);

  • Get Slack/email notifications;

  • Automatically post an update on Facebook/Twitter;

  • Produce an automatic deploy on your staging environment;

You can connect DatoCMS webhooks to any endpoint you like — for example, some custom AWS lambda function.

Pro tip: DatoCMS + Zapier: no-code management of webhooks!

If you prefer not to write code, you can use Zapier Webhooks to connect a DatoCMS event with hundreds of different external services, creating any kind of complex automation workflow.

Setting up a webhook

You can set up a new webhook under the Project Settings > Webhooks section of your administrative area. You can enter any URL as the destination for calls, add HTTP basic authentication and custom HTTP headers:

DatoCMS needs to get a status code 2XX reply from the configured URL to confirm that the notification sent via HTTP POST has been successfully delivered. If any webhook returns a different status code or times out, DatoCMS will set the status as "Failed".

Webhook triggers

Webhook triggers let you specify under which circumstances an HTTP call will be performed towards your endpoint:

You can add as many triggers as you want to a single webhook. DatoCMS supports events for the following objects:

Entity Available eventsAdditional notes
Record"create", "update", "delete", "publish", "unpublish"You can trigger the webhook only for specific records or records belonging to specific models.
Model"create", "update", "delete"You can trigger the webhook only for specific models. Changes made to a model's field will trigger a call as well.
Upload"create", "update", "delete"
Build trigger"deploy_started", "deploy_succeeded", "deploy_failed"
Environment"create", "update", "promote", "delete"
Maintenance Mode"change"Triggers whenever an admin activates or deactivates the maintenance mode.
SSO User"create"Triggers when an SSO User is added to a project as a collaborator.
CDA Cache Tags"invalidate"Triggers when CDA Cache Tags need to be invalidated.

Visit the Data consistency: key concepts and implications section for more details on when the webhooks related to the records will be triggered.

The HTTP Payload

DatoCMS will perform an HTTP POST request towards the specified endpoint. The HTTP body will be in JSON format, and will contain all the information relevant to the event just happened.

The body will contain the following information:

Payload propertyDescription
site_idID of the project where the event occurred.
webhook_idID of the webhook that triggered the delivery.
environmentID of the environment where the entity resides.
is_environment_primaryWhether the environment where the event occurred is the primary environment.
webhook_call_idID of the specific webhook event that triggered.
event_triggered_atDate when the event originally occurred.
attempted_auto_retries_countIf auto-retry is on for the webhook, this field displays the number of the current attempt.
entity_typeThe type of entity that triggered the webhook (ie. item, item_type...)
event_typeThe type of event that triggered the webhook (i.e.: create, update, delete...)
entityThe full payload of the entity serialized according to our Content Management API schema.
previous_entityOnly present if the event type is "Record > Update". It represents the serialized record BEFORE the update (useful to know what changed).
related_entitiesAn array containing all serialized entities specified in the entity's relationships.

As an example, in the case of a Record > Update event, you can access the record state both before the update operation (previous_entity) and after (entity), making it easier to make a diff and see exactly what fields in the record changed:

{
"site_id": "example-site-id",
"webhook_id": "123",
"environment": "foo-bar",
"is_environment_primary": true,
"webhook_call_id": "456",
"event_triggered_at": "2024-08-26T14:30:00Z",
"attempted_auto_retries_count": 3,
"entity_type": "item",
"event_type": "update",
"entity": {
"id": "39830648",
"type": "item",
"attributes": {
"name": "Mark Smith"
},
"relationships": {
"item_type": {
"data": {
"id": "810928",
"type": "item_type"
}
},
"creator": {
"data": {
"id": "42011",
"type": "account"
}
}
},
"meta": {
"created_at": "2018-10-28T18:44:32.776+01:00",
"updated_at": "2021-08-17T09:11:56.145+02:00",
"published_at": "2021-08-17T09:11:56.143+02:00",
"first_published_at": "2018-10-28T18:44:32.789+01:00",
"status": "published",
"current_version": "117626080"
}
},
"previous_entity": {
"id": "39830648",
"type": "item",
"attributes": {
"name": "John Smith"
},
"relationships": {
"item_type": {
"data": {
"id": "810928",
"type": "item_type"
}
},
"creator": {
"data": {
"id": "42011",
"type": "account"
}
}
},
"meta": {
"created_at": "2018-10-28T18:44:32.776+01:00",
"updated_at": "2021-08-17T09:11:53.371+02:00",
"published_at": "2021-08-17T09:11:53.367+02:00",
"first_published_at": "2018-10-28T18:44:32.789+01:00",
"status": "published",
"current_version": "117626079"
}
},
"related_entities": [
{
"id":"810928",
"type": "item_type",
"attributes": {
"name": "Author",
"api_key": "author",
...
},
"relationships": { ... }
}
]
}

Customize the URL or HTTP payload

If you want, you can also customize the HTTP body of the outgoing requests. To do that, hit the Send a custom payload? switch and provide the new payload.

You can use the Mustache language to make the payload dynamic. The original payload we would send is used as source for the template. You can experiment with the Mustache language in their sandbox, or read their docs.

As an example, this custom payload template:

{
"message": "{{event_type}} event triggered on {{entity_type}}!",
"entity_id": "{{#entity}}{{id}}{{/entity}}"
}

Will be converted into the following HTTP body:

{
"message": "update event triggered on item!",
"entity_id": "123213"
}

You are not limited to send JSON payloads: just make sure that if the payload is not in JSON format, you configure the proper Content-Type header.

Similarly, you can also insert Mustache tags in the webhook URL.

Automatic Retries

Optionally, you can activate the Automatic Retry option in your webhook settings, so that in case of delivery failure, DatoCMS will attempt to resend the request up to 7 times, with increasing intervals between each attempt.

Each retry will use the most recent webhook settings, and the retry schedule is as follows:

RetryTime
12 minutes after the failure
26 minutes after the previous retry
330 minutes after the previous retry
41 hour after the previous retry
55 hours after the previous retry
61 day after the previous retry
72 days after the previous retry

Understanding webhook statuses

Webhook calls can have different statuses to indicate the outcome of the delivery attempt:

StatusDescription
PendingThe webhook call is currently being executed.
SuccessThe webhook call was successfully delivered to the specified endpoint, and the server responded with an HTTP status code in the 2xx range.
FailedThe webhook call could not be successfully delivered. This may be due to issues such as server errors, invalid endpoints, network problems or an HTTP status code not in the 2xx range.
RescheduledThe webhook delivery failed, but is scheduled to be retried automatically based on the webhook automatic retries setting.

Debug and keep track of webhooks activity

You can browse webhook activity under the Project Settings > Webhooks activity log section of your project, or using our API. In both cases, you can filter/order webhook calls to refine your search based on various criteria, such as status, type of event, date, etc:

Manually Resend Webhook Event

At any time you have the option to resend a webhook manually. To do so, click on the "Details" link and then on "Resend now"

When you choose to manually resend a webhook call, the system will repeat the exact same call with the updated webhook settings. If auto-retries are enabled:

  • a successful manual resend will stop further auto-retry attempts,

  • a failed manual resend won't add to the count of automatic retries.

Webhook Timeouts

DatoCMS enforces two timeout limits for webhook integrations:

  • Connection Timeout: 2 seconds
    This is the maximum time allowed to establish the initial connection to the webhook's HTTP server.

  • Total Execution Timeout: 8 seconds
    This is the maximum time allowed for the entire webhook process to complete.

If your service exceeds either of these timeouts, DatoCMS will terminate the connection. The delivery attempt will then be marked as either Failed — or Rescheduled, if Automatic Retries are enabled.

Pro tip: Prefer asynchronous over synchronous

Due to the unpredictable nature of service completion times, it's recommended to handle the bulk of your processing in background jobs. This approach helps manage DatoCMS's timeout constraints effectively. Consider using job queue libraries such as Resque (Ruby), RQ (Python), or RabbitMQ (Java).

The pattern we suggest is to perform the initial validation checks of the payload quickly and synchronously before starting the background jobs. This allows you to potentially respond with a status code other than 2XX to the webhook, thereby notifying DatoCMS of the issue.