Webhooks

Subscribe to events (e.g. review.created, booking.completed, invoice.paid) and Vimub POSTs an HMAC-signed JSON payload to your URL. Manage subscriptions and signing secrets in Settings → API keys or via the API.

Delivery headers

X-Vimub-Signature:  t=1719500000,v1=9f86d081...   # HMAC-SHA256, hex
X-Vimub-Timestamp:  1719500000
X-Vimub-Event-Id:   3b2e...                            # idempotency key
X-Vimub-Event-Type: review.created

Verify the signature

The signature is HMAC-SHA256 of `${timestamp}.${rawBody}` using your subscription's signing secret. Always compare in constant time and reject stale timestamps.

import { createHmac, timingSafeEqual } from 'node:crypto';

// Verify against the RAW request body (do not re-serialize JSON first).
export function verify(rawBody: string, sigHeader: string, secret: string): boolean {
  const parts = Object.fromEntries(sigHeader.split(',').map((p) => p.split('=')));
  const ts = parts.t, v1 = parts.v1;
  if (!ts || !v1) return false;

  // Reject anything older than 5 minutes to stop replay.
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;

  const expected = createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
  return v1.length === expected.length &&
    timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

Retries & dead-lettering

← Back to docs
Webhooks · Vimub