Skip to main content
Anyone can send a request to your webhook URL, so before you act on one, check it really came from us. Every message we send has an X-Minisend-Signature header. It’s a fingerprint of the message body made with your webhook_secret (technically, an HMAC-SHA256 hex digest). You make the same fingerprint on your side, and if the two match, the message is genuine.
Find your webhook_secret under Dashboard → Webhooks. Treat it like a password.
Compare the two with a timing-safe function, like the ones in the examples below. A plain === can leak information to an attacker through how long it takes.

Use the raw body

The signature is made from the exact text we sent. If you parse the JSON and turn it back into text (JSON.stringify(req.body)), the spacing or order can change and the check will fail. So grab the raw body before your framework parses it. In Express, use express.raw({ type: 'application/json' }) on the webhook route.

Verify

A stronger option: X-Minisend-Signature-V2

Checkout and settlement messages also come with X-Minisend-Signature-V2, in the form t=<timestamp>,v1=<signature>. It includes the time we sent the message, so if someone copied an old message, they couldn’t send it to you again later. X-Minisend-Signature is staying and works everywhere. V2 is there if you want the extra protection.
Not every message has this header. Off-ramp, onramp, and Wallet API events only send X-Minisend-Signature. So use V2 when it’s there, and fall back to the first check when it isn’t.

Full Express handler

Reply with 2xx first, then do your own processing. If you take more than 10 seconds to reply, we’ll send the message again.