Build webhook integrations without the usual local-dev pain: capture real events, replay them instantly, and ship handlers with validation and signature verification.
Most webhook workflows still require tunnel juggling, repeated provider triggers, and hand-rolled scripts for replay and verification. better-webhook replaces that with a local-first workflow for faster iteration and safer production handlers.
better-webhook gives you:
- A local-first CLI to capture, inspect, and replay real webhook requests
- SDK packages for typed events, schema validation, and signature verification
- Flexible adoption: use only the CLI, only the SDK, or both together
- Faster feedback loops: capture once, replay as many times as needed
- Less debugging guesswork: inspect real payloads and headers locally
- Safer production handlers: typed payloads, schema validation, signature verification
- Replay/idempotency controls: provider replay keys with configurable duplicate handling (
409by default when enabled) - Fits your stack: adapters for Next.js, Express, NestJS, Hono, and more
# Install once (Homebrew Cask)
brew install --cask endalk200/tap/better-webhook
# Alternative install (Go)
go install github.com/endalk200/better-webhook/apps/webhook-cli/cmd/better-webhook@latest
# Start local capture API
better-webhook capture --port 3001
# Replay a captured webhook to your app
# (Use `better-webhook captures list` to find a capture ID)
better-webhook captures replay <capture-id> http://localhost:3000/api/webhooks/githubThe CLI is available through Homebrew Cask, GitHub Releases binaries, and go install.
npm install @better-webhook/github @better-webhook/nextjsimport { github } from "@better-webhook/github";
import { push } from "@better-webhook/github/events";
import { toNextJS } from "@better-webhook/nextjs";
const webhook = github().event(push, async (payload) => {
console.log(payload.repository.full_name);
});
export const POST = toNextJS(webhook);- Docs source:
apps/docs - CLI docs:
apps/webhook-cli/README.md - SDK docs:
packages/core/README.md - Maintainer release runbook:
docs/cli-release-runbook.md
For deep details, use the docs source and package-level READMEs. The root README stays intentionally lightweight.
- Incoming requests are signature-verified before verified but unhandled events return the provider's acknowledgement status (
204by default; some providers such as Resend use200). - When core replay protection is enabled, duplicate replay keys return
409by default.
pnpm install --frozen-lockfile
pnpm dev
pnpm lint
pnpm check-types
pnpm test
pnpm buildIf you only want to work on docs:
pnpm dev:docs- CLI:
better-webhookGo CLI - Core SDK:
@better-webhook/core - Providers:
@better-webhook/github,@better-webhook/stripe,@better-webhook/ragie,@better-webhook/recall,@better-webhook/resend - Adapters:
@better-webhook/nextjs,@better-webhook/express,@better-webhook/nestjs,@better-webhook/hono,@better-webhook/gcp-functions
apps/docs- docs site source (better-webhook.dev)apps/webhook-cli- Go CLI command implementationapps/examples- runnable framework examplespackages- SDK providers, adapters, and shared tooling
- Contributing guide:
CONTRIBUTING.md - Code of conduct:
CODE_OF_CONDUCT.md - Support:
SUPPORT.md - Security policy:
SECURITY.md - Issues: github.com/endalk200/better-webhook/issues
MIT