Interface VerifyWebhookOptions

interface VerifyWebhookOptions {
    payload: Buffer<ArrayBufferLike> | Uint8Array<ArrayBufferLike>;
    secret: string;
    signatureHeader: string;
    timestampHeader: string;
    toleranceSeconds?: number;
    now?: () => number;
}

Properties

payload: Buffer<ArrayBufferLike> | Uint8Array<ArrayBufferLike>

Raw request body bytes — NOT the parsed JSON. The signature is computed over exact bytes, so any re-encoding (e.g. JSON.stringify after req.json()) will shift them and break verification.

Framework recipes:

  • Express: app.post('/webhook', express.raw({ type: 'application/json' }), ...)
  • Fastify: addContentTypeParser('application/json', { parseAs: 'buffer' }, ...)
  • Next.js App Router: Buffer.from(await req.arrayBuffer())
  • Cloudflare Workers: Buffer.from(await request.arrayBuffer())
  • AWS Lambda: event.isBase64Encoded ? Buffer.from(event.body, 'base64') : Buffer.from(event.body)
secret: string

Webhook signing secret from the dashboard. Stored in your env.

signatureHeader: string

Value of the X-NessyAPI-Signature-256 header.

timestampHeader: string

Value of the X-NessyAPI-Timestamp header (Unix seconds as string).

toleranceSeconds?: number

Max allowed skew between the timestamp and now. Default 300s (5 min). Set 0 to disable (not recommended — you lose replay protection).

now?: () => number

Clock override for testing. Default () => Date.now() / 1000.