Webhooks

Monthly delivery when a crawl publishes. New rows only.

Signing

Every payload carries X-Ansafi-Signature: t=<unix>,v1=<hmac>. The HMAC is SHA-256 over {timestamp}.{body} — verify against the timestamp too, so a replayed body with an old timestamp can be rejected.

const [t, v1] = header.split(",").map(p => p.split("=")[1]);
const expected = crypto.createHmac("sha256", secret)
  .update(`${t}.${rawBody}`).digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1))) reject();

Retries

Non-2xx retries at 1m, 5m, 30m, 2h, 12h, then dead-letters and emails the workspace owner.

An empty month still fires. A quiet month is delivered with a zero count and a note that the crawl completed normally. Silence reads as breakage.