Integration recipe

Send new Toolbench leads to n8n

Register your n8n Webhook URL with POST /webhooks for lead.created, verify Toolbench-Signature in a Code node, then branch on the event payload.

Webhook node, signature check in Code, importable workflow JSON.

Register the webhook

Turn write on for your API token, then subscribe your n8n production Webhook URL for lead.created. Store the signing_secret (full whsec_… string) in n8n credentials or an env var — it is shown once.

POST /webhooks
curl -s -X POST "https://app.toolbench.com/api/v1/webhooks" \
  -H "Authorization: Bearer $TB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{:,:[]}'

Import the workflow

In n8n: Workflows → Import from file, then paste your Webhook path and set TB_WEBHOOK_SECRET to the signing secret. Download the starter JSON.

Raw body
In the Webhook node, enable raw body access if your n8n version exposes it — signature verification must use the exact bytes Toolbench POSTed, not a re-stringified object.

Verify in a Code node

Place this immediately after the Webhook node:

n8n Code
// n8n Code node — first item is the Webhook payload
const crypto = require("crypto");

const secret = $env.TB_WEBHOOK_SECRET; // full whsec_… from POST /webhooks
const header = $input.first().headers["toolbench-signature"] ?? "";
const rawBody = JSON.stringify($input.first().json.body ?? $input.first().json);

const parts = Object.fromEntries(
  header.split(",").map((p) => {
    const i = p.indexOf("=");
    return [p.slice(0, i), p.slice(i + 1)];
  }),
);
const t = Number(parts.t);
const v1 = parts.v1;
if (!t || !v1 || Math.abs(Date.now() / 1000 - t) > 300) {
  throw new Error("Invalid or stale Toolbench-Signature");
}
const expected = crypto
  .createHmac("sha256", secret)
  .update(`${t}.${rawBody}`, "utf8")
  .digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) {
  throw new Error("Signature mismatch");
}

return $input.all();

Branch on the event

After verification, read $json.body.type (or your raw-body parse) — for lead.created, map data.lead into your CRM, Slack, or a second workflow.