Skip to main content
Each request includes X-Minisend-Signature: an HMAC-SHA256 hex of the raw JSON body, keyed with your webhook_secret. Verify it before processing.
Find your webhook_secret in Settings. Treat it like a password.
Use a timing-safe comparison. === is vulnerable to timing attacks.

Sign over the raw body

The signature covers the exact bytes Minisend sent. Re-stringifying the parsed body (JSON.stringify(req.body)) can produce different bytes and break verification. Capture the raw body before parsing. In Express, use express.raw({ type: 'application/json' }) for the webhook route.

Verify

A stronger option: X-Minisend-Signature-V2

Checkout and settlement deliveries also carry X-Minisend-Signature-V2, formatted as t=<timestamp>,v1=<hmac>. It signs the timestamp together with the body, so a signature captured off the wire can’t be replayed later the way one covering the body alone could be. X-Minisend-Signature isn’t going anywhere and still works everywhere; V2 exists for anyone who wants that extra guarantee.
Not every delivery carries this header. Off-ramp, onramp, and Wallet API events only send X-Minisend-Signature, so check for X-Minisend-Signature-V2 and fall back to the V1 check above if it’s missing rather than requiring it everywhere.

Full Express handler

Return 2xx before running business logic. Anything taking >10s triggers a retry.