Overview

Stratus subscriptions deliver events via webhooks, enabling your systems to respond immediately to key events. This guide explains how to set up and validate webhook notifications.

Getting Started

1

Enable Webhooks

Toggle webhooks within your subscription settings

2

Configure Endpoint

Provide the URL where your system will accept POST requests

3

Store Signing Key

Save the Signing Key from your subscription settings for payload validation

Implementation Guide

Webhook Validation

Each webhook payload includes a signature header (x-signature) that should be validated to ensure authenticity.

// https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries
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' })
  }
}

Important Considerations

Batching

Multiple events may be batched into a single webhook payload

Retry Logic

Failed webhooks are retried exponentially up to five times

Security

Always validate webhook signatures using your WEBHOOK_SECRET

Never expose your WEBHOOK_SECRET in client-side code or public repositories. Always store it securely in environment variables.