Signature Verification

Every webhook delivery is signed with HMAC-SHA256 using your webhook secret. Always verify the signature before processing the payload.

How It Works

When Merx sends a webhook, it computes an HMAC-SHA256 hash of the raw request body using your webhook secret as the key. The resulting hex digest is sent in the X-Merx-Signature header with the format sha256=<hex_digest>.

Verification Steps

USE RAW BODY

You must use the raw, unparsed request body for signature verification. Parsing and re-serializing the JSON may change whitespace or key order, producing a different hash.

Code Examples

Signature verification
const crypto = require('crypto')

function verifyWebhook(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')

  const received = signatureHeader.replace('sha256=', '')

  return crypto.timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(received, 'hex'),
  )
}

// Express middleware example
app.post('/webhooks/merx', express.raw({ type: '*/*' }), (req, res) => {
  const signature = req.headers['x-merx-signature']
  const secret = process.env.MERX_WEBHOOK_SECRET

  if (!verifyWebhook(req.body, signature, secret)) {
    return res.status(401).send('Invalid signature')
  }

  const event = JSON.parse(req.body)
  console.log(event.event, event.data)

  // Return 200 immediately, process asynchronously
  res.status(200).send('OK')
})

Testing Locally

To test webhook verification locally, compute a signature manually and include it in a test request.

Test with curl
SECRET="your_webhook_secret"
BODY='{"event":"order.filled","data":{"id":"ord_test"},"timestamp":1711200000}'
SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)

curl -X POST http://localhost:3000/webhooks/merx \
  -H "Content-Type: application/json" \
  -H "X-Merx-Signature: sha256=$SIG" \
  -d "$BODY"
TIP

Use a tool like ngrok to expose your local server and register the tunnel URL as your webhook endpoint during development.