WinLayer Docs
Product documentation · Beta behavior. A documented path is not production acceptance; availability still depends on source health, workspace plan, provider setup, and deployed evidence.

Build a webhook receiver

A minimal, production-shaped endpoint that verifies WinLayer's signature and never blocks the sender.

1. Register the endpoint

On /developer, add your HTTPS URL. Copy the whsec_… secret (shown once) into your receiver's environment. Use the test ping button whenever you deploy a change.

2. Verify, then respond fast

The two rules of webhook receivers: compute the HMAC over the raw body (before JSON parsing), and return 2xx immediately — do real work asynchronously.

typescript
import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";

const app = express();
const SECRET = process.env.WINLAYER_WEBHOOK_SECRET!;

// Capture the RAW body — signature verification needs the exact bytes.
app.post("/hooks/winlayer", express.raw({ type: "application/json" }), (req, res) => {
  const sig = req.header("x-winlayer-signature") ?? "";
  const expected = "sha256=" + createHmac("sha256", SECRET).update(req.body).digest("hex");

  const a = Buffer.from(sig);
  const b = Buffer.from(expected);
  if (a.length !== b.length || !timingSafeEqual(a, b)) {
    return res.status(401).send("bad signature");
  }

  const { id, event, data } = JSON.parse(req.body.toString("utf8"));
  if (await alreadyProcessed(id)) return res.sendStatus(200);
  res.sendStatus(200); // ack first…

  // …then persist id and act. e.g. event === "opportunity.pursuit.set"
  //   → upsert data.signalId with data.status into your system.
});

app.listen(8080);

3. Know the delivery semantics

  • Delivery is at least once. Network errors, timeouts, HTTP 408/425/429, and 5xx responses enter a durable five-attempt queue with 1, 5, 30, and 120 minute backoff.
  • Events can arrive out of order under concurrency; treat data.status as the current truth, not a transition.
  • Make handling idempotent: store the stable payload id and return 2xx without repeating work when that id arrives again.
  • The developer console shows pending retry count, next attempt, last HTTP status, and terminal failures. Test pings remain one-attempt diagnostics.
Event reference: payload shapes and headers are in Webhooks.