How to Receive Stripe Webhooks on Localhost (Without the Headache)
Source: Dev.to
Testing Stripe Webhooks Locally with Hooklink
If you’ve ever integrated Stripe payments, you know the drill: Stripe sends webhook events to a public URL, but your development server is running on localhost:3000. You need those events to reach your machine in real time so you can:
- Test payment flows
- Handle subscription changes
- Debug edge‑case payloads
In this post, I’ll walk through how to bridge that gap using Hooklink, a webhook‑to‑localhost tool that gives you:
- A permanent sub‑domain
- Signature verification
- Event filtering
- Replay capabilities
Why Not the Usual Workarounds?
| Tool | Pros | Cons |
|---|---|---|
| Stripe CLI | Works out‑of‑the‑box for Stripe | Only for Stripe – you need separate tools for GitHub, Shopify, Slack, etc. |
| ngrok | Generic tunnel | Free tier URL changes on every restart, no webhook replay, no built‑in signature verification |
| Deploy to staging | Public endpoint | Slow feedback loop, you lose the ability to set breakpoints locally |
Step‑by‑Step: From Zero to Live Stripe Events on Your Machine
1. Create a Hooklink Account
- Go to app.hooklink.net/register and sign up.
- The free plan includes 2,500 requests per week – more than enough for development.
2. Create a Stripe Endpoint
-
In the Hooklink dashboard, navigate to Endpoints → Create Endpoint.
-
Choose the Stripe template (fastest path):
- Integrations → find the Stripe card → Use Template
The dialog will pre‑fill the following fields:
| Field | Value (example) |
|---|---|
| Keyword | stripe (your URL becomes https://stripe‑yourname.hooklink.net) |
| Local target | http://localhost:3000/api/webhooks/stripe |
| Source allowlist | All 12 official Stripe webhook IP ranges (pre‑loaded) |
| Event filter | Common events like payment_intent.succeeded, checkout.session.completed, invoice.paid, etc. |
- Adjust the Local target URL to match your project’s webhook route, then click Create.
Your endpoint is now live at a permanent, memorable URL:
https://stripe-yourname.hooklink.net
Note: This URL never changes, so you won’t need to keep updating Stripe’s dashboard.
3. Register the Hooklink URL in Stripe
- In the Stripe Dashboard: Developers → Webhooks → Add endpoint.
- Paste the Hooklink URL:
https://stripe-yourname.hooklink.net. - Select the events you want to receive (e.g.,
payment_intent.succeeded,checkout.session.completed,customer.subscription.created). - Click Add endpoint.
4. Enable Signature Verification
Stripe signs every webhook with an HMAC‑SHA256 signature in the Stripe-Signature header.
-
In Stripe’s webhook settings, copy the Signing secret (starts with
whsec_). -
In Hooklink’s endpoint settings, enable Signature Verification:
- Algorithm: HMAC‑SHA256
- Header:
Stripe-Signature - Signing secret: paste the value from Stripe
Hooklink parses Stripe’s signature format (t=timestamp,v1=signature) natively, builds the signed payload as {timestamp}.{body}, and performs a constant‑time comparison. It also checks the timestamp against a configurable tolerance window (default 5 minutes) to prevent replay attacks.
5. Install & Authenticate the Hooklink CLI
# Install globally
npm install -g @hooklink/cli
Generate an API key from Dashboard → API Keys, then log in:
hooklink login --key hlk_your_api_key_here
6. Connect to Your Stripe Endpoint
hooklink connect stripe
You’ll see output similar to:
$ hooklink connect stripe
Connection Details:
Version: v1.2.0
Endpoint: stripe
Webhook URL: https://stripe-yourname.hooklink.net
Target: http://localhost:3000/api/webhooks/stripe
Waiting for webhooks...
Now every Stripe webhook flows to your local server in real time over a persistent WebSocket connection.
7. Test the Flow
- In Stripe’s webhook settings, click Send test webhook and choose an event (e.g.,
payment_intent.succeeded). - In your terminal you’ll see:
stripe POST --> payment_intent.succeeded
stripe POST payment_intent.succeeded
stripe POST push
github POST <-- 200 8ms
preview GET /dashboard 200
Installation
npm install -g @hooklink/cli
Authentication
hooklink login --key hlk_your_key
Connect to Endpoints
-
Single endpoint (Stripe)
hooklink connect stripe -
Multiple endpoints (Stripe, GitHub, Preview)
hooklink connect stripe,github,preview
Useful Commands
-
View recent webhook logs
hooklink logs --endpoint stripe -
Check connection status
hooklink status
Why Use Hooklink?
Testing Stripe webhooks locally doesn’t have to be painful. With Hooklink you get:
- A permanent URL that survives restarts
- Built‑in Stripe signature verification
- Event filtering and source IP allowlisting
- One‑click webhook replay
- Full request logging for free
The free plan covers 2,500 requests per week across 3 endpoints with full request logging—more than enough for most development workflows.
Quick Start (No Sign‑Up Required)
npx @hooklink/cli listen 3000
You’ll have a public webhook URL in under 30 seconds.