Quickstart
Install the SDK and handle your first webhook.
Install
npm install webhooks-sdkpnpm add webhooks-sdkyarn add webhooks-sdkbun add webhooks-sdkNo other dependencies. The SDK uses Web Crypto and fetch only, so it runs
unchanged on Node 22+, Cloudflare Workers, Deno, and Bun.
Create a handler
Import a provider
Each provider lives on its own subpath, so your bundle only carries the schemes you use:
import { createWebhookHandler } from 'webhooks-sdk'
import { stripe } from 'webhooks-sdk/stripe'Wire up your event handlers
Keys in on are the provider’s native event names:
const handler = createWebhookHandler({
provider: stripe({ secret: process.env.STRIPE_WEBHOOK_SECRET! }),
on: {
'payment_intent.succeeded': async (event) => {
await fulfill(event.payload.data.object)
},
'customer.subscription.deleted': async (event) => {
await revoke(event.payload.data.object)
},
},
})Mount it
handler.fetch is a (request: Request) => Promise<Response> function —
mount it anywhere that speaks the Web platform:
export const POST = handler.fetchThat’s the whole integration. The handler verifies the signature, enforces the
replay window, parses the body, and dispatches to your on handlers. It
returns 401 on a bad signature, 400 on a malformed request, 500 if your
handler throws (so the provider retries), and 200 otherwise.
Other frameworks
import { toHonoHandler } from 'webhooks-sdk/hono'
app.post('/webhooks/stripe', toHonoHandler(handler))import express from 'express'
import { toExpressHandler } from 'webhooks-sdk/express'
// Raw on the webhook path only; JSON everywhere else.
app.post('/webhooks/stripe', express.raw({ type: '*/*' }), toExpressHandler(handler))
app.use(express.json())import { toNodeHandler } from 'webhooks-sdk/node'
server.on('request', toNodeHandler(handler))export default { fetch: handler.fetch }