Skip to main content
Humanos provides a comprehensive webhook system that allows organizations to receive real-time notifications when specific events occur in their processes. All webhook events are delivered to a single configured endpoint, providing a unified interface for handling all event types. To configure the webhook system, organization administrators can navigate to Humanos Admin – Webhooks. The following image illustrates an example configuration:
  • Webhook URL is the endpoint where all webhook events will be delivered (e.g., https://your.domain.com/webhook).
  • Webhook Signature Secret is used for validating that the webhooks were sent by Humanos.
  • Webhook Encryption Secret is used for decrypting the payloads, ensuring security on transit.
  • Webhook Encryption Salt is used together with the Webhook Encryption Secret to derive the final encryption key. The salt adds uniqueness and protects against dictionary or pre-computed attacks, ensuring stronger security for each payload.
import crypto from "crypto";

function generateSignature(data, secret, timestamp) {
  const hmac = crypto.createHmac("sha256", secret);
  hmac.update(data ? `${timestamp}.${data}` : timestamp.toString());
  return hmac.digest("hex");
}
const express = require("express");
const crypto = require("crypto");
const app = express();
app.use(express.json());
const SIGNATURE_SECRET = "your-signature-secret";
const ENCRYPTION_SECRET = "your-encryption-secret";
const ENCRYPTION_SALT = "your-encryption-salt";
app.post("/webhook", (req, res) => {
  try {
    const signature = req.headers["x-signature"];
    const timestamp = req.headers["x-timestamp"];
    // 1. Verify signature
    const expected = generateSignature(req.body, SIGNATURE_SECRET, timestamp);
    if (signature !== expected)
      return res.status(401).send("Invalid signature");
    // 2. Decrypt payload
    const { iv, data, tag } = req.body;
    const key = crypto.pbkdf2Sync(
      Buffer.from(ENCRYPTION_SECRET, "base64"),
      ENCRYPTION_SALT,
      10000,
      32,
      "sha256"
    );
    const decipher = crypto.createDecipheriv(
      "aes-256-gcm",
      key,
      Buffer.from(iv, "base64")
    );
    decipher.setAuthTag(Buffer.from(tag, "base64"));
    const decrypted = Buffer.concat([
      decipher.update(Buffer.from(data, "base64")),
      decipher.final(),
    ]).toString("utf8");
    const webhook = JSON.parse(decrypted);
    console.log("Webhook received:", webhook);
    res.sendStatus(200);
  } catch (err) {
    res.status(500).send(err.message);
  }
});
app.listen(5000, () => console.log("Listening on port 5000"));
The provided code snippet implements an express API containing an endpoint to deal with Humanos Webhook notifications. The request should be handled as follows:
  1. Receive the request → Your endpoint will be called with an encrypted payload.
  2. Verify authenticity → Check the x-signature header using your Webhook Signature Secret.
  3. Decrypt the payload → Use the Webhook Encryption Secret and Webhook Encryption Salt to decrypt the message and read the event data.
  4. Process the event → Store it in your system, update statuses, or trigger business logic.
  5. Respond quickly → Always return 200 OK after successful processing. Humanos retries failed deliveries automatically.