Webhooks
read time 3 mins
Webhooks enable secret changes in Doppler to be integrated into your continuous delivery flow. For example, a webhook could be used by Doppler restart or redeploy an application when a secret is changed.
Each webhook receives a single POST request from Doppler whenever a change is made to secrets for that project.
Multiple webhooks can be defined for a single project
Creating a Webhook
- Navigate to a project config, then click Webhooks from the project menu
- Click the + Add button which will open a dialog asking you to provide the webhook URL and an optional Secret value to enable the signing of each webook request.
- After adding the webhook, you will see it listed in the Active Webhooks list.

Webhook Request Signing
If a Secret value is provided, Doppler uses this to cryptographically sign each webhook request, enabling you to verify the request originated from Doppler. See the Request Signing section to learn more.
Accepting Webhooks
Your endpoint will receive a JSON payload with the following structure.
Field | Description |
---|---|
type | Event types available:config.secrets.update |
config | Config object |
project | Project object |
workplace | Workplace object |
Here is an example payload:
{
"type": "config.secrets.update",
"config": {
"name": "dev_2",
"created_at": "2019-05-30T08:18:33.634Z",
"environment": "dev",
"project": "714faaa5958"
},
"project": {
"id": "714faaa5958",
"name": "Backend",
"description": "Your first project!",
"created_at": "2019-05-26T01:42:30.256Z"
},
"workplace": {
"id": "fcd76",
"name": "Pied Piper",
"billing_email": "[email protected]"
}
}
Verify Webhook With Request Signing
Doppler can optionally sign the webhook events by including a signature in each eventβs X-Doppler-Signature
header. This allows you to verify that the events were sent by Doppler, not by a third party.
To enable webhook verification, a value for Secret must be supplied when creating the webhook. The X-Doppler-Signature
header will then contain a SHA256 hash of the request body prepended with sha256=
(e.g. X-Doppler-Signature: sha256=724cd2c1110335a8ea6207f74cd74fb198a8e59ca1b7b39d67678e0f97df832e
).
To verify the signature, create your own SHA256 hash of the request body using the Secret value. Then compare the header value against your own computed value using a timing-safe equality function. Here is an example of how you might accomplish this using Node.js.
const bodyParser = require("body-parser");
const crypto = require("crypto");
const express = require("express");
const app = express();
app.use(bodyParser.json({
limit: '200kb',
}));
app.post('/webhooks/doppler', (req, res) => {
const requestHMAC = req.header("X-Doppler-Signature");
const secret = process.env.WEBHOOK_SECRET;
const computedHMAC = `sha256=${crypto.createHmac('sha256', secret).update(JSON.stringify(req.body)).digest('hex')}`;
const signatureMatches = crypto.timingSafeEqual(Buffer.from(requestHMAC), Buffer.from(computedHMAC));
if (signatureMatches) {
// do stuff
}
res.sendStatus(signatureMatches ? 200 : 401);
});
require "sinatra"
require "json"
require "openssl"
set :port, ENV["PORT"] || 8081
post "/webhooks/doppler" do
if valid_webhook_signature?(request)
# do something
status 200
else
status 401
end
end
def valid_webhook_signature?(request)
request.body.rewind
data = request.body.read
key = ENV["WEBHOOK_SECRET"]
digest = OpenSSL::Digest.new("sha256")
computedHMAC = OpenSSL::HMAC.hexdigest(digest, key, data)
requestHMAC = request.env["HTTP_X_DOPPLER_SIGNATURE"].delete_prefix("sha256=")
return OpenSSL.secure_compare(requestHMAC, computedHMAC)
end
Removing a Webhook
A webhook can be removed by clicking the Remove button next to the webhook you wish to have deleted.
Once confirmed, it will be removed by from the list of active webhooks.
Updated 3 months ago