Local-first Webhook Toolkit

Stop fightingwebhooks.

The local-first toolkit for capturing, replaying, and shipping type-safe webhook handlers in TypeScript.

Quick Install

$ brew install --cask endalk200/tap/better-webhook
View on GitHub
5
Providers
5
Adapters
100%
Type-safe
TYPE-SAFE LOCAL-FIRST OPEN SOURCE SECURE TYPESCRIPT ZERO BOILERPLATE FAST EXTENSIBLE TYPE-SAFE LOCAL-FIRST OPEN SOURCE SECURE TYPESCRIPT ZERO BOILERPLATE FAST EXTENSIBLE
Quick Start

Get started in 60s

Choose how you want to work with webhooks — capture and replay with the CLI, or build type-safe handlers with the SDK.

1

Install the CLI

$ brew install --cask endalk200/tap/better-webhook
2

Start capture server

$ better-webhook capture --port 3001

Stores incoming webhooks locally under ~/.better-webhook/captures

3

Point webhooks to capture server

http://localhost:3001/webhooks/your-provider

Use this URL in your webhook provider settings (e.g., GitHub webhook URL)

4

Replay captured webhooks

$ better-webhook captures replay <capture-id> http://localhost:3000/api/webhooks/github

Replay to your local development server

Features

Everything you need for webhook dev

A focused toolkit for fast, repeatable webhook development — from local testing to production handlers.

CLI

Live Capture

Start a local server to capture incoming webhooks with headers, path, and payload preserved.

CLI

Smart Replay

Replay captured webhooks to any endpoint with full header preservation. Test handlers without re-triggering events.

SDK

Signature Verification

Automatic signature verification for GitHub, Stripe, Ragie, and Recall.ai with timing-safe comparison.

SDK

Type-Safe Handlers

Full TypeScript support with Zod schemas. Get autocomplete for every event payload property.

CLI

Fast Native Binary

Install a prebuilt Go binary from Homebrew or GitHub Releases with no Node.js runtime requirement.

SDK

Framework Adapters

First-class integrations for Next.js, Hono, Express, NestJS, and GCP Cloud Functions.

CLI

Auto Signatures

CLI generates valid signatures when running templates. Test signature verification without manual setup.

CLI

Curated Templates

Download and run built-in webhook templates for GitHub, Stripe, Ragie, and Recall.ai with realistic payloads.

CLI Tool

Capture. Replay. Test.

A powerful CLI for local webhook development. Capture real webhooks, replay them on demand, and test your handlers.

Terminal

Capture

Start a local server to intercept and store incoming webhooks

better-webhook capture

Replay

Re-send captured webhooks to any endpoint with full headers

better-webhook captures replay <id> <url>

Templates

Download and run curated templates for GitHub, Ragie, and Recall.ai

better-webhook templates list

Install with Homebrew

$ brew install --cask endalk200/tap/better-webhook
SDK Packages

Type-safe. Verified. Simple.

Build webhook handlers with full TypeScript support, automatic signature verification, and Zod schema validation.

Signature Verification

Automatic HMAC verification for all providers. Timing-safe comparison prevents attacks.

Type-Safe Handlers

Full TypeScript support with Zod schemas. Autocomplete for every payload property.

Framework Adapters

First-class support for Next.js, Hono, Express, NestJS, and GCP Functions.

$ npm install @better-webhook/github @better-webhook/nextjs
app/api/webhooks/github/route.ts
import { github } from "@better-webhook/github";
import { push, pull_request } from "@better-webhook/github/events";
import { toNextJS } from "@better-webhook/nextjs";

const webhook = github()
  .event(push, async (payload) => {
    console.log(`Push to ${payload.repository.name}`);
    console.log(`${payload.commits.length} commits`);
  })
  .event(pull_request, async (payload) => {
    if (payload.action === "opened") {
      console.log(`New PR: ${payload.pull_request.title}`);
    }
  })
  .onError((error, context) => {
    console.error(`Error in ${context.eventType}`, error);
  });

export const POST = toNextJS(webhook);

Available Providers

G

GitHub

@better-webhook/github
pushpull_requestissuesinstallation+1 more
R

Ragie

@better-webhook/ragie
document_status_updateddocument_deletedentity_extractedconnection_sync_started+4 more
S

Stripe

@better-webhook/stripe
charge.failedcheckout.session.completedpayment_intent.succeeded
R

Recall.ai

@better-webhook/recall
participant_events.joinparticipant_events.leaveparticipant_events.chat_messagetranscript.data+21 more
R

Resend

@better-webhook/resend
email.deliveredemail.bouncedemail.receiveddomain.updated+13 more

See the difference

Compare traditional webhook handling with better-webhook. Less boilerplate, more safety.

route.tsbetter-webhook
1// The better-webhook way - type-safe and secure
2
3import { github } from "@better-webhook/github";
4import { push } from "@better-webhook/github/events";
5import { toExpress } from "@better-webhook/express";
6
7const webhook = github()
8 .event(push, async (payload) => {
9 // Full autocomplete and type safety!
10 console.log(payload.repository.name);
11 console.log(payload.commits.length);
12
13 for (const commit of payload.commits) {
14 console.log(commit.message);
15 }
16 })
17 .onError((error, context) => {
18 logger.error(`Failed: ${context.eventType}`, error);
19 });
20
21app.post('/webhooks/github',
22 express.raw({ type: 'application/json' }),
23 toExpress(webhook)
24);

What changes

Automatic signature verification
Full type inference with Zod
Schema-validated payloads
Built-in error hooks
Less boilerplate with adapters
~20%
Less boilerplate
Providers

Webhook Providers

Pre-built providers with automatic signature verification and fully typed payloads. Create custom providers for any webhook source.

G

GitHub

R

Ragie

S

Stripe

R

Recall.ai

R

Resend

+

Custom

G

GitHub

@better-webhook/github

Example Events

pushpull_requestissuesinstallationinstallation_repositories
R

Ragie

@better-webhook/ragie

Example Events

document_status_updateddocument_deletedentity_extractedconnection_sync_startedconnection_sync_progressconnection_sync_finished
S

Stripe

@better-webhook/stripe

Example Events

charge.failedcheckout.session.completedpayment_intent.succeeded
R

Recall.ai

@better-webhook/recall

Example Events

participant_events.joinparticipant_events.leaveparticipant_events.chat_messagetranscript.datatranscript.partial_databot.joining_callbot.donebot.fatal
R

Resend

@better-webhook/resend

Example Events

email.deliveredemail.bouncedemail.receiveddomain.updatedcontact.created

Need a different provider? Create custom webhooks with the core package.