Forward Webhooks to Localhost with the OpenWebhook CLI
Install the public openwebhook CLI, authenticate a Pro token, and forward any custom endpoint to 127.0.0.1 without a tunnel.
A provider needs a public HTTPS URL. Your handler is often still on localhost. A tunnel can expose the whole machine. The OpenWebhook CLI does something narrower: it watches one custom endpoint and replays each request only to 127.0.0.1.
This is a Pro feature. The free inspector still works in the browser without an account.
Install and authenticate
npm install --global openwebhook
openwebhook auth owh_live_YOUR_TOKEN
Generate the token once in the developer dashboard. It is shown a single time. You can revoke it later. OPENWEBHOOK_TOKEN can supply the token without writing a config file.
Listen on a local port
Create a custom slug such as billing so the public URL is stable:
https://hooks.openwebhook.co/billing
Start a local receiver, then the CLI:
# terminal 1 — your app, or any HTTP echo on 127.0.0.1
npx --yes http-echo-server 3001
# terminal 2
openwebhook listen billing --port 3001
listen opens an authenticated SSE stream for that slug. Each inbound webhook is forwarded with the original method, path, query and body. Host and Content-Length are recalculated. Hop-by-hop, proxy and X-Forwarded-* headers are dropped. The destination host is always 127.0.0.1; the port comes only from --port.
Send a test:
curl -X POST \
'https://hooks.openwebhook.co/billing/stripe' \
-H 'content-type: application/json' \
--data '{"type":"checkout.session.completed"}'
The CLI should print POST /stripe -> 200 (or whatever your local process returned).
Why this is safer than a public tunnel
- Only one slug is observed, not your whole laptop.
- The local target cannot be chosen by the webhook payload.
- Absolute URLs, protocol-relative paths and
..tricks in the request path are rejected before forwarding.
Use a tunnel when the provider must hit your TLS terminator or a path that is not 127.0.0.1. Use the CLI when you want the public URL to stay on OpenWebhook and the handler to stay private.
MCP in the same token
openwebhook mcp exposes the same account to Cursor or Claude Code (list_endpoints, watch, wait_for_webhook). See Test webhooks in Cursor and Claude.