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
| Header | Purpose |
|---|---|
x-anemone-timestamp | Unix time (seconds) when the event was created; must be within the allowed skew window (default 300s). |
x-anemone-signature | Lowercase 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.