Skip to content
Webhooks SDK
Esc
navigateopen⌘Jpreview
On this page

Standalone verification

The router is optional — verify and parse without a handler.

The handler is optional. When you want the check and nothing else — inside an existing framework, a queue consumer, or middleware you already own — every provider exports standalone verify and parse functions:

import { toRawWebhook } from 'webhooks-sdk'
import { verifyStripeWebhook, parseStripeWebhook } from 'webhooks-sdk/stripe'

const raw = await toRawWebhook(request)
await verifyStripeWebhook(raw, { secret })  // throws WebhookError on failure
const event = parseStripeWebhook(raw)

Unlike handler.process(), the standalone functions throw on failure — the same error classes, with the same codes and statuses.

toRawWebhook

Verification needs the exact bytes on the wire, so everything starts by normalizing your input into a RawWebhook:

const raw = await toRawWebhook(input)

input can be:

  • a Web-standard Request (cloned; the body is read once as bytes)
  • an existing RawWebhook (passed through)
  • a plain object: { headers, body, method?, url? } — headers as a Headers instance or a plain record, body as a string, Uint8Array, or ArrayBuffer

The result is frozen and exposes headers, body (bytes), method, url, plus header(name), text(), and json() accessors.

Per-provider functions

Provider Verify Parse
Stripe verifyStripeWebhook(raw, { secret, tolerance? }) parseStripeWebhook(raw)
GitHub verifyGitHubWebhook(raw, { secret }) parseGitHubWebhook(raw)
Discord verifyDiscordWebhook(raw, { publicKey, mode?, tolerance? }) parseDiscordWebhook(raw, options)
Twilio verifyTwilioWebhook(raw, { authToken, url? }) parseTwilioWebhook(raw)
Google Pub/Sub verifyGooglePubSubWebhook(raw, options) parseGooglePubSubWebhook(raw, options?)
Standard Webhooks verifyStandardWebhook(raw, options) parseStandardWebhook(raw, options?)

Options are identical to the corresponding provider factory.

What standalone mode skips

Only verification and parsing run. You give up the handler’s replay-window default, idempotency, handshake answering, and dispatch — bring your own where the provider needs them. If you find yourself reimplementing several of those, createWebhookHandler with onEvent is the same thing with less code:

const handler = createWebhookHandler({
  provider: stripe({ secret }),
  onEvent: async (event) => queue.push(event),  // every verified event
})

Was this page helpful?