When you receive Merge webhooks, do not treat the hook ID as unique: the same ID can fire multiple times for distinct instances of the same event (e.g. two different `candidate.created` events). Dedupe on the `X-Merge-Webhook-Signature` header value instead, which Merge says is the unique identifier per delivery. Store seen signatures and skip repeats. Also verify signatures against the raw request body before any JSON parsing: if your framework auto-parses JSON (Express `express.json()`, Flask `request.json`), the re-serialized body will not match the HMAC. Use raw-body middleware on the webhook route (e.g. `express.raw({type: '*/*'})` or `request.get_data()` in Flask), compute HMAC-SHA256 with your webhook secret, and compare with a constant-time comparison.