Developers

Webhooks

Outbound webhooks are signed with a shared secret so you can be sure the payload came from Anemone and was not tampered with. The anemone-server-js module implements HMAC-SHA256 verification, timestamp tolerance to limit replay, and constant-time signature comparison.

Headers

HeaderPurpose
x-anemone-timestampUnix time (seconds) when the event was created; must be within the allowed skew window (default 300s).
x-anemone-signatureLowercase hex HMAC-SHA256 over `${timestamp}.${rawBody}`.

Verify in your handler (Node)

Working reference in the demo: POST /api/webhooks/contact-changed applying events via applyContactChangeFromPrimary.

import { verifyAndParseWebhook } from "anemone-server-js";

// raw body string (must be exact bytes as received, before JSON parse)
const raw = await getRawBody(request);
const event = verifyAndParseWebhook(
  raw,
  Object.fromEntries(request.headers.entries()) as any,
  process.env.ANEMONE_WEBHOOK_SECRET!
);
// event.event === "contact.changed"
// event.kind: "address" | "phone" | "name" | "email"
// event.address?: { line1, line2, city, ... }

Event types

The envelope includes externalUserId, kind, and occurredAt (ISO 8601). Address payloads are nested under address when kind is address.