Example webhook receiver

A minimal Node.js Express handler that verifies signatures and processes member events.

Example receiver

A complete Express handler that verifies the signature, deduplicates by event ID, and routes to per-event handlers.

Node.js
import express from 'express';
import crypto  from 'node:crypto';

const app    = express();
const SECRET = process.env.KEY_WEBHOOK_SECRET;
const seen   = new Set();   // in prod, use Redis / a TTL store

function verify(rawBody, signature) {
  const expected =
    'sha256=' +
    crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

app.post(
  '/webhooks/key',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const sig     = req.headers['x-webhook-signature'];
    const eventId = req.headers['x-event-id'];

    if (!sig || !verify(req.body, sig)) return res.sendStatus(401);
    if (seen.has(eventId))            return res.sendStatus(200); // dedup
    seen.add(eventId);

    const event = JSON.parse(req.body);

    switch (event.eventType) {
      case 'member.joined':   onJoined(event);   break;
      case 'member.approved': onApproved(event); break;
      case 'member.rejected': onRejected(event); break;
      case 'member.removed':  onRemoved(event);  break;
      case 'member.left':     onLeft(event);     break;
      case 'webhook.test':    /* no-op */      break;
    }

    res.sendStatus(200);
  }
);

app.listen(3000);

← In the product, this is also reachable from Community Settings → Developer → Webhooks.

← Full webhooks reference · developers@key.ai