← Blog/Webhooks

How to test webhooks

Test and debug webhooks with a public HTTPS URL: inspect method, headers, and body, forward to localhost with the macOS app or npm CLI, then replay a stored delivery from the console.

Webhook debugging fails when you cannot see what the provider actually sent. Localhost alone cannot receive callbacks from Stripe, GitHub, or Twilio. You need a public HTTPS URL, a place to read method, headers, and body, and — only later — a way to forward that traffic to a process on your laptop.

What a webhook test needs

  • A public URL the provider can reach (localhost alone is not enough)
  • Payload visibility — headers and body, including signature headers
  • A clear path for retries and failed deliveries when the first attempt misbehaves

An online webhook inspector covers the first two without installing an agent. An Endpoint covers the third when your app must respond on a local port.

Browser inspector vs Endpoint

  • Inspect a delivery quickly — use the online webhook inspector (guest mode)
  • Forward to a local HTTP server — use an Endpoint after free registration
  • Record live tunnel traffic — use Record Session on an Endpoint (account required)
  • Replay a stored request — use Retry in console request history (proxy mode, agent connected)

Guest mode records requests and returns 204 No Content. It does not forward to your machine.

Open an online webhook inspector

Open the webhook inspector

A guest endpoint is provisioned in the browser with no account and no install.

Copy the public HTTPS URL

Copy the temporary endpoint from the page. Unused guest endpoints expire after 24 hours idle. Copy the URL from the page — the subdomain is unique to your session.

Point a provider or curl at the URL

Paste the URL into a provider webhook setting, or send a POST with curl. The inspector responds 204 and records the request. Provider dashboards (Stripe, GitHub, Shopify, Twilio, and others) work the same way: paste the HTTPS URL and trigger a test event.

Send a sample delivery yourself:

Run
curl -X POST "$MERCUR_URL" \
-H "Content-Type: application/json" \
-d '{"hello":"webhook"}'

Inspect method, headers, and body

Open request history on the same page to see what the sender transmitted, including signature headers and retries. Select a log entry to expand headers and body. Signature verification failures usually show up here as the raw Stripe-Signature or X-Hub-Signature-256 header plus the body your code would verify.

That is enough to debug most integrations without adding logging to your app yet.

Forward to localhost when ready

Create a free account, start an Endpoint aimed at your local port, and connect the macOS app or npm CLI so deliveries reach a service on your machine. Your guest inspector URL is deleted on registration (or expires after idle TTL). After signup you get a stopped HTTP tunnel in the console — start it when you are ready to hit localhost.

When inspection is not enough and your local server must respond:

  1. Create a free Mercur account
  2. Start an Endpoint aimed at your local port
  3. Connect an agent — macOS app or npm CLI — and start forwarding
  4. Point the provider at the Endpoint URL (or keep the guest URL for inspect-only work)

Forwarding needs a connected agent — the macOS app or the npm package @mercur_dev/cli.

macOS app walkthrough

npm CLI walkthrough

Guest mode does not forward traffic. Forwarding and Retry need an account, a proxy Endpoint, and a connected agent.

Verify webhook signatures

Providers sign each request with a secret so your app can confirm authenticity. Keep that secret in your local environment — not in Mercur.

Use request history to compare the raw body and signature header with what your verifier expects. Encoding and whitespace matter; mismatches usually show up as a failed check in your handler while the delivery itself looks fine in the log. Step-by-step for HMAC and secret-token failures: Webhook signature verification failed.

Replay a stored delivery

After a handler fix, you often want the same payload again without waiting on the provider. In the console, open request history for the Endpoint and choose Retry. Mercur re-sends the stored method, path, headers, and body through the public URL.

Requirements:

  • Endpoint in proxy mode (not logging-only)
  • Agent connected
  • Payload still stored (within plan retention and size limits)

Oversized bodies that were omitted from the log cannot be replayed.

Common failures

These are symptoms, not a second copy of this walkthrough:

Keep going

Try the online webhook inspector

webhooksdebugginglocalhost