Stratus subscriptions deliver events via webhooks, enabling your systems to respond immediately to key events.

Enabling Webhooks

To begin receiving webhook notifications:

  • Toggle Webhooks: Enable webhooks within your subscription settings.

  • Configure Endpoint: Provide the URL where your system will accept POST requests from the Snag subscription service.

Validating Webhooks

Each webhook payload is signed with a unique signing key, ensuring its authenticity. Use the Signing Key from your subscription settings to verify the payload signature.

Below is a Next.js example demonstrating webhook validation:

// https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries#validating-payloads-from-github
export const config = {
  api: {
    bodyParser: false,
  },
}

export default async function handler(req, res) {
  try {
    if (req.method !== 'POST') {
      res.setHeader('Allow', 'POST')
      return res.status(405).json({ error: 'Method Not Allowed' })
    }

    const rawBody = (await getRawBody(req)).toString('utf-8')

    const signature = req.headers['x-signature']
    if (!signature) {
      console.error('Missing signature')
      return res.status(400).json({ error: 'Missing signature' })
    }

    const secret = process.env.WEBHOOK_SECRET
    if (!secret) {
      console.error('Server misconfiguration: Missing WEBHOOK_SECRET')
      return res
        .status(500)
        .json({ error: 'Server misconfiguration: Missing WEBHOOK_SECRET' })
    }

    const computedSignature = crypto
      .createHmac('sha256', secret)
      .update(rawBody)
      .digest('hex')

    if (
      !crypto.timingSafeEqual(
        new Uint8Array(Buffer.from(computedSignature)),
        new Uint8Array(Buffer.from(signature))
      )
    ) {
      console.error('Invalid signature')
      return res.status(401).json({ error: 'Invalid signature' })
    }

    const payload = JSON.parse(rawBody)
    payload.forEach((event) => {
      console.log('Received event:', event)
    })

    res.status(200).json({ status: 'Webhook processed successfully' })
  } catch (error) {
    console.error('Webhook processing error:', error)
    res.status(500).json({ error: 'Internal Server Error' })
  }
}

Key Points:

  • Batching: Multiple events may be batched into a single webhook payload.

  • Retry Logic: Webhook requests are retried exponentially up to five times before marking them as failures.

  • Security: Always validate the webhook signature with your WEBHOOK_SECRET to ensure payload authenticity.