Skip to content

Webhook verifier

@feitpay/webhooks verifies deliveries exactly as described in Verify webhook signatures and returns a typed event.

Terminal window
pnpm add @feitpay/webhooks
import { verifyWebhook, WebhookVerificationError, type WebhookEvent } from '@feitpay/webhooks';
const event = await verifyWebhook({
payload: rawBody, // string or Uint8Array — the raw body
header: request.headers.get('feitpay-signature'),
secrets: [process.env.FEITPAY_WEBHOOK_SECRET!, process.env.FEITPAY_WEBHOOK_SECRET_PREVIOUS!].filter(Boolean),
toleranceSeconds: 300, // default
});
if (event.event_type === 'payment.confirmed' && event.data.fulfillable) {
// typed: event.data.quote?.asset_amount, event.data.totals?.confirmed_base_units …
}
import { verifyWebhookSync } from '@feitpay/webhooks/node';
const event = verifyWebhookSync({ payload: rawBodyBuffer, header, secret });

WebhookVerificationError.reason is one of malformed_header, no_signatures, signature_mismatch, timestamp_outside_tolerance or invalid_payload. Respond 400. A missing secret or a non-positive tolerance throws a TypeError (a configuration bug, not a bad request).

import { generateTestHeader } from '@feitpay/webhooks';
const header = await generateTestHeader({ payload: body, secret: 'whsec_test_only' });

The package’s own test-suite runs every case in the shared cross-language vector file.