Skip to content

Webhook Signatures

Skunivo signs webhook deliveries so your integration can verify that the payload came from Skunivo and was not modified in transit.

Webhook requests include:

X-Skunivo-Event-Id: <outbox-event-id>
X-Skunivo-Delivery-Id: <webhook-delivery-id>
X-Skunivo-Timestamp: <unix-timestamp-seconds>
X-Skunivo-Signature: v1=<hmac-sha256-hex>

Verify the signature over:

<timestamp>.<raw-json-body>

Use the raw request body exactly as received. Parsing and re-stringifying JSON can change whitespace or ordering and break verification.

import { verifyWebhookSignature } from '@skunivo/sdk'
const isValid = verifyWebhookSignature({
secret: process.env.SKUNIVO_WEBHOOK_SECRET!,
timestamp: request.headers['x-skunivo-timestamp'],
signature: request.headers['x-skunivo-signature'],
rawBody
})

Reject deliveries with invalid signatures before making inventory or downstream state changes.

Webhook deliveries can be retried. Your handler should be idempotent and safe to receive the same event more than once.

Use these headers as stable logging and deduplication inputs:

  • X-Skunivo-Event-Id: identifies the outbox event.
  • X-Skunivo-Delivery-Id: identifies this delivery attempt.
  • X-Skunivo-Timestamp: the timestamp included in signature verification.

Store processed event ids when applying downstream state changes. If an event id was already applied, return a successful response without applying the change again.

Manual replay creates a new delivery for the same event. Do not treat a new delivery id as a new business event.

  • Store webhook secrets as server-side secrets.
  • Do not log full webhook secrets.
  • Keep X-Skunivo-Event-Id and X-Skunivo-Delivery-Id in logs.
  • Make handlers idempotent because webhook deliveries may be retried.
  • Alert on repeated delivery failures and include event id, delivery id and request id when contacting support.