Events pushed to you, signed.
Alerts, case updates, report availability and screening results delivered to your endpoint with an HMAC signature, automatic retries and an idempotency key on every delivery.
How do ChainwatchCrypto webhooks work?
Webhooks push events to your endpoint with a signature you should verify before trusting the payload. Delivery is at-least-once with exponential backoff and an idempotency key, which means your handler must tolerate duplicates. A timeout counts as failure and is retried, so a slow endpoint produces repeats rather than losses.
What we send.
| Event | Meaning |
|---|---|
| alert.raised | A monitoring rule matched. Includes the rule, its version and observed values. |
| alert.resolved | An alert reached a terminal disposition. |
| case.stage_changed | A case moved between stages. |
| case.message_created | A new message on a case. |
| report.ready | A report version is available for download. |
| evidence.requested | An investigator has requested additional evidence. |
| risk.score_changed | A monitored address's score moved beyond your configured margin. |
| screening.match | A screening check produced a designation match. |
Do this before you trust the body.
import crypto from "node:crypto"; // Compare against the RAW body. Parsing first and re-serialising // will change the bytes and the signature will never match. function verify(rawBody, header, secret) { const [tsPart, sigPart] = header.split(","); const ts = tsPart.split("=")[1]; const sig = sigPart.split("=")[1]; // Reject anything older than five minutes to blunt replay. if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; const expected = crypto .createHmac("sha256", secret) .update(`${ts}.${rawBody}`) .digest("hex"); return crypto.timingSafeEqual( Buffer.from(sig), Buffer.from(expected)); }
CW-Signature: t=1771843200,v1=9f2c… — the timestamp and the hex HMAC of {timestamp}.{raw body} using your endpoint's signing secret.
Return 2xx as soon as you have verified and queued the event. We treat anything over 10 seconds as a failure and retry, which produces duplicates you then have to de-duplicate.
At least once, which means you must be idempotent.
First attempt
Immediately after the event occurs.
Retries
Exponential backoff over 24 hours on any non-2xx response or timeout.
Idempotency key
Every delivery carries a stable event id. A repeat is the same event, not a new one.
Failure state
After the retry window an endpoint is marked failing and surfaced in the dashboard.
Replay
Failed deliveries can be replayed from the dashboard once your endpoint is healthy.
Audit
Every attempt, response code and latency is recorded.
