Step by step
From localhost to public HTTPS
Start the webhook receiver locally
Run the app and verify the webhook path locally before involving the provider. Preserve the raw request body if your provider requires it for signature verification.
curl -i -X POST http://localhost:3000/api/webhooks/testOpen the local port with Bore
Authenticate if needed, then expose the same port. Bore returns a public HTTPS namespace.
bore login
bore up 3000Register the complete endpoint URL
Add your handler path to the Bore origin in the provider dashboard. Select only the event types the handler supports.
https://<namespace>.bore.dk/api/webhooks/stripeConfigure and verify the signing secret
Store the provider's webhook secret in a server-only environment variable and verify every event before changing state.
STRIPE_WEBHOOK_SECRET=whsec_...
GITHUB_WEBHOOK_SECRET=...Send a test event and inspect both sides
Trigger a provider test delivery, then compare its delivery status with your local application logs. Bore transports the request; provider delivery tools and your app remain the source of payload-level diagnostics.
Endpoints
Use the route your application actually handles
A tunnel exposes an origin, not a magic webhook route. If the local handler is /api/webhooks/github, register that same path after the Bore hostname. A 404 usually means the request reached your app but the path or HTTP method is wrong.
Keep Stripe in test mode and use a test repository or narrowly selected GitHub events while developing. Public tunnel URLs can receive unsolicited internet traffic.
https://<namespace>.bore.dk/api/webhooks/stripe
https://<namespace>.bore.dk/api/webhooks/githubSecurity
A successful HTTP request is not a trusted event
TLS protects the connection to the Bore edge, but your handler must still authenticate the sender. Verify the provider signature using its official SDK or algorithm, reject stale timestamps where supported, and never authorize an event from a user-controlled body field alone.
- Verify signatures against the unmodified raw body when the provider requires it.
- Return a non-2xx response when validation fails; do not continue asynchronously.
- Store signing secrets outside source control and browser-exposed environment variables.
- Use idempotency keys or provider event IDs before applying side effects.
Bore does not replace Stripe or GitHub signature verification. It only makes the local HTTP endpoint reachable.
Reliability
Design the handler for retries and short response times
Providers retry failed or slow deliveries, so the same event may arrive more than once. Validate the request, record its unique event ID, enqueue or perform bounded work, and acknowledge it promptly. Your exact timeout and retry schedule comes from the provider, not Bore.
- Persist processed event IDs with a uniqueness constraint.
- Log the provider event ID, event type, response status, and processing outcome.
- Make side effects transactional or safely repeatable.
- Test duplicate delivery and out-of-order delivery before shipping.
Isolation
Route a dedicated webhook service to another port
A child hostname keeps webhook traffic separate from the main local app. After reserving it, point that host at the receiver's local port.
bore host add <namespace> hooks
bore host set-port <namespace> hooks 3001The child host is still public. Isolation by hostname is useful routing, not access control.
Troubleshooting
Locate failures in the shortest order
Work from the local handler outward. This separates application failures from tunnel state and provider configuration without guessing.
- Local curl fails: fix the route, process, or framework first.
- Local curl works, public curl fails: check
bore ls, the assigned port, and tunnel status. - Public curl works, provider fails: check its exact URL, event selection, signature secret, and delivery log.
- Provider receives 2xx but behavior is wrong: trace the event ID through application logs and idempotency storage.
Common questions
Before you expose a port
Can Bore inspect or replay webhook bodies?
Bore provides tunnel telemetry, but this workflow should use the provider's delivery log and your application logs for payload inspection and replay. Do not assume Bore is a webhook-specific inspector.
Why does signature verification fail through a tunnel?
The common cause is parsing or modifying the body before verification, or using the wrong endpoint secret. Verify the provider's signature against the exact body format its documentation requires.
Will the webhook URL change every time?
Bore reserves namespaces to your account. Stopping a local claim does not release the namespace, so it can be reused when available.
Can I use the same setup for custom webhook senders?
Yes. Any sender that can reach a public HTTPS URL can call the endpoint, but your application must define and verify an authentication scheme.
Sources and further reading
Run it locally
Debug the next webhook locally
Keep your debugger and logs close while Bore gives the provider a stable HTTPS destination.