Skip to content
MothershipDevelopers

GuidesConfiguring webhooks

Validating webhook payloads

Check the X-Mothership-Signature header with your webhook configuration's secret key.

1 min read

The Create a webhook configuration and Retrieve a webhook configuration responses each contain a secretKey property that can be used to validate the signature of incoming Mothership webhook events.

Secret keys are unique to webhook configs.

Create Webhook 201 Responsejson
{
  "data": {
    "id": "48asjgaoi33nkl4t3lae",
    "createdAt": "2019-03-20T16:17:13.424Z",
    "status": "active",
    "subscribedEvents": ["shipment.purchased", "billOfLading.created", "proofOfDelivery.created"],
    "webhookUrl": "https://www.yourserver.io/webhook/mothership",
    "secretKey": "de3ADDAek3245DLAdANe91Dn3asklAMSsna03aGKkl23agsJea"
  }
}

The X-Mothership-Signature header is the hex-encoded HMAC-SHA256 of the raw request body, keyed with the secret key. To validate a payload, compute the same HMAC over the body exactly as you received it and compare it to the header.

Let's validate a webhook payload. Both examples read the secret key from the MOTHERSHIP_WEBHOOK_SECRET environment variable and use a constant-time comparison.

import crypto from 'node:crypto'
import express from 'express'

const app = express()
// Check the signature against the raw body, before any JSON parsing.
const rawBody = express.raw({ type: 'application/json' })

app.post('/webhooks/mothership', rawBody, (req, res) => {
  const expected = crypto
    .createHmac('sha256', process.env.MOTHERSHIP_WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex')
  const received = req.get('X-Mothership-Signature') ?? ''

  if (
    !/^[a-f0-9]{64}$/.test(received) ||
    !crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected))
  ) {
    return res.sendStatus(401)
  }

  const event = JSON.parse(req.body.toString('utf8'))
  // event.eventType, event.data, event.sentAt, event.deliveryAttempt, event.pendingRetries
  res.sendStatus(200)
})

Check a signature in your browser

Paste a delivery's raw body and your secret key to see the X-Mothership-Signature value Mothership sends. The key and body stay on this page; the HMAC runs in your browser with Web Crypto.

X-Mothership-Signature

Signing…

Why the raw body matters

Any change to the bytes, even whitespace or key order, gives a different signature. Verify before you parse.