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

Quickstart

Install the SDK and handle your first webhook.

Install

npm install webhooks-sdk
pnpm add webhooks-sdk
yarn add webhooks-sdk
bun add webhooks-sdk

No 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.fetch

That’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 }

Next steps

Was this page helpful?