Webhooks
Webhooks enable HTTP payloads to be sent to an external service when data in Ditto is changed.
Setup
You can configure webhooks for your workspace in the Webhooks section of your team’s developer integrations.
Signing Key
Prior to creating any webhook endpoints, it’s essential to generate and securely store a signing key. This key plays a crucial role in appending a signature to all outbound webhook payloads, allowing your server to authenticate that a particular request originates from Ditto.
Once you’ve saved your key in Ditto, it is encrypted and cannot be directly accessed. However, you can preview the last four characters of your saved key.
Creating a Webhook
You can open the modal for creating webhooks via the Create Webhook button.
Each webhook must be assigned a name, a URL, and have at least one trigger activated. While there are no strict guidelines for URLs, it is strongly advised that they direct to secure endpoints utilizing HTTPS.
Before saving a webhook, the URL must be validated with a test request. See Example Webhook Server below for details on configuring your webhook server to process a test request.
Request Headers
Every request sent to a webhook endpoint will have the following three headers included:
x-ditto-request-id
— a v4 uuid uniquely identifying a given request. This identifier can be cross-referenced 1:1 with delivery history exported from inside of Ditto.x-ditto-timestamp
— a Unix timestamp identifying the time at which the request was made. This timestamp is included in the signature and can therefore be used to guard against replay attacks.x-ditto-signature
— a signature (HMAC-SHA256) created using your workspace’s webhook signing key, by concatenating the request ID, the timestamp of the request and the request body (each separated by a period).
The JavaScript code below demonstrates how the values for these headers are generated:
Request Validation
Ditto expects all webhook consumers to return a status code between 200 and 299 to indicate successful payload processing. To enhance your security, it is strongly advised to perform the following actions on your server prior to accepting a webhook payload and issuing a success response:
- Validate the signature included in the
x-ditto-signature
header.- Concatenate the request ID, the timestamp, and a string representation of the request body into a single string, with each component separated by the
.
character${requestId}.${timestamp}.${JSON.stringify(req.body)}
; - Using your signing key, sign the concatenated value using HMAC-256, encoded as hex.
- Validate that the signed value you’ve generated matches the value in the
x-ditto-signature
header. If it does not match, then the request is not valid and an error response should be returned.
- Concatenate the request ID, the timestamp, and a string representation of the request body into a single string, with each component separated by the
- (Optional) Ensure idempotence by tracking request IDs.
- After validating the signature of a request, track the request ID in a persistent data store (like Redis).
- Before processing new requests, check your data store to see if a given request has been seen before; if it has already been processed, then the request is not valid and an error response should be returned.
- (Optional) Validate the timestamp included in the
x-ditto-timestamp
header.- Decide on a time window (e.g. 6 minutes to allow for retries) outside of which you will not accept requests.
- Check that the time elapsed since the timestamp in the x-ditto-timestamp header does not exceed your established time window. If it exceeds the time window, then the request is not valid and an error response should be returned.
See Example Webhook Server below for example code for request validation in a Node.js environment.
Error Handling
If Ditto receives an error response from your server, it will retry sending a payload 3 additional times:
- 1 minute following the initial request
- 2 minutes following the first retry
- 3 minutes following the second retry.
If a given endpoint returns a non-success response for more than 10 requests in a 10 minute window, the webhook will be automatically disabled. If a webhook has been disabled, it can be re-enabled by revalidating with a test request.
Event Reference
All request bodies sent to webhook endpoints will have event
and data
properties.
Component Creation
Emitted any time a component is created in Ditto.
Component Deletion
Emitted any time a component is deleted in Ditto.
Component Text Change
Emitted any time a component’s base text is changed in Ditto. Does not emit when variant text, plural text, or rich text styling is changed.
Component Status Change
Emitted any time a component’s status is changed in Ditto.
Component ID Change
Emitted any time a component’s developer ID is changed in Ditto.
Test Event
Emitted when sending a test request while creating a webhook.
Example Webhook Server
Here is an annotated code sample showing a simple Node.js server to process webhook events from Ditto: