Skip to content
Zap Studio
webhooks
Esc
navigateopen⌘Jpreview
On this page

Web API Native

handle(request) returns a Response, so the router plugs directly into Bun, Deno, Cloudflare Workers, Next.js, Hono, and any other fetch-compatible runtime.

handle(request: Request) returns a Response, so the router plugs directly into Bun, Deno, Cloudflare Workers, Next.js route handlers, Hono, and any other fetch-compatible runtime. There is no adapter layer to implement.

Why this design:

  • no framework lock-in and no custom request/response contract to learn
  • smaller package surface
  • raw body capture is handled by the router itself: it reads the request body exactly once and exposes the exact bytes as ctx.rawBody, so signature verification always sees what the provider sent

Fetch-Native Runtimes

import { createWebhookRouter } from "@zap-studio/webhooks";

const router = createWebhookRouter();

router.register("/ping", () => Response.json("pong"));

// Bun / Deno / Cloudflare Workers
export default {
  fetch: (request: Request) => router.handle(request),
};

Next.js Route Handlers

// app/webhooks/[...path]/route.ts
import { router } from "@/lib/webhooks";

export const POST = (request: Request) => router.handle(request);

Hono

import { Hono } from "hono";
import { router } from "./webhooks";

const app = new Hono();

app.all("/webhooks/*", (c) => router.handle(c.req.raw));

Node http Servers

Raw Node http servers do not speak fetch natively. Use a fetch-to-Node bridge such as srvx or @hono/node-server:

import { serve } from "srvx";
import { router } from "./webhooks";

serve({
  fetch: (request) => router.handle(request),
  port: 3000,
});

The router parses the request URL’s pathname, requires the configured prefix (default /webhooks) on a segment boundary, and matches routes on the remainder. Prefix, routes, and incoming pathnames are normalized to the same canonical form (leading slash, no trailing slash), so a stray trailing slash never 404s. Requests that miss the prefix or match no route get a 404 without the body ever being read.

See Also

Last updated on September 21, 2026

Was this page helpful?