We support signing Webhook's payloads and we force using HTTPS for your webhook URLs.

HTTPS/SLS

We only accept endpoints in HTTPS in both sandbox and production. Your endpoint must have a valid certificate and self-signed certificates are not accepted.

Webhook Signature

All our Webhooks are sent with a signature to validate their authenticity. You should compare the signature we sent in X-Yousign-Signature-256 header with the signature you recreate. To recreate the signature you have to:

  1. Retrieve webhook associated secret key through the app by clicking "Copy secret key" in the right menu,

  1. Compute an HMAC SHA-256 hash of the entire Webhook's payload as binary, using the Webhook Subscription secret_key as a key,
  2. Add "sha256=" at the beginning of the binary hash.

🚧

Make sure you compute the hash from a raw version of the webhook payload.

Examples

$expectedSignature = $_REQUEST['x-yousign-signature-256'];

$payload = file_get_contents('php://input'); // This is an example, you should get the content from an HTTP request
$secret = 'SECRET_KEY_OF_YOUR_WEBHOOK';
$digest = hash_hmac('sha256', $payload, $secret);
$computedSignature = "sha256=" . $digest;

$doSignaturesMatch = hash_equals($expectedSignature, $computedSignature);
SECRET = YOUR_WEBHOOK_SECRET_KEY
digest = hmac.new(SECRET.encode('utf-8'), data, hashlib.sha256).hexdigest()
computed_signature = f"sha256={digest}"
matches = hmac.compare_digest(signature, computed_signature)
const express = require("express");
const crypto = require("crypto");
const https = require("https");

const app = express();
const secret = 'YOUR_WEBHOOK_SECRET_KEY';
const port = 3000;

// SSL Certification
const options = {
  key: 'PRIVATE_KEY',
  cert: 'CERTIFICATE',
};

/* If you are not using Express, you need to find a way to get the raw request body and
 * encoding it.
 * You can for example, use the `raw-body` middleware https://www.npmjs.com/package/raw-body
*/
app.use(
  express.json({
    verify: (req, res, buf, encoding) => {
      if (buf && buf.length) {
        req.rawBody = buf.toString(encoding || "utf-8");
      }
    },
  })
)

app.post('/hook', (req, res) => {
  const signature = Buffer.from(req.get('X-Yousign-Signature-256') || '', 'utf8');
  const hmac = crypto.createHmac('sha256', secret);
  const computedSignature = Buffer.from(`${'sha256' + '='}${hmac.update(req.rawBody).digest('hex')}`, 'utf8');
  
  const isSignatureMatch = crypto.timingSafeEqual(signature, computedSignature)
})

https.createServer(options, app).listen(PORT);

Domain validation

You will find below the range of IPs that we use to send our Webhooks for you to whitelist them if needed:

CIDR 5.39.7.128/28 (from IP 5.39.7.128 to IP 5.39.7.143)