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.

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.