skip to content
Sean Thawe
Table of Contents

When I was building the payment flow for an e-commerce store, I hit the classic webhook problem: the local development server runs on localhost, and payment providers like Paystack need a public HTTPS URL to fire webhooks at. I don’t own a domain for the project yet, and I didn’t want to deploy to production just to test a payment confirmation.

The solution turned out to be simple: Cloudflare Quick Tunnels (the trycloudflare.com tool). It gives you a random public URL that proxies straight into the localhost server — for free, with no Cloudflare account, and no DNS setup.

This guide was tested against a Paystack test-mode checkout with an Astro dev server running on http://localhost:4321. The same flow works for any payment provider that sends webhooks.

What You’ll Learn in This Guide

  • Why a localhost URL can’t receive webhooks.
  • What Quick Tunnels are and how they work.
  • The single command that exposes your dev server publicly.
  • How to wire the tunnel into the Paystack dashboard.
  • The limitations you need to know before relying on one.

Part 1: Quick Tunnels — The Problem and the Tool

Payment providers don’t deliver webhooks to localhost — the URL they call must be publicly reachable over HTTPS. Since my dev machine had no public address and no domain pointing at it, the provider would simply have been unable to reach the confirmation endpoint at all.

That’s where Quick Tunnels come in. They’re part of the cloudflared client. You launch one command, Cloudflare’s network assigns your tunnel a random subdomain on trycloudflare.com, and every request to that URL is proxied through Cloudflare straight to your web server on localhost.

Cloudflare’s own docs are clear about the intended use: testing and development only — a quick tunnel has no SLA and caps at 200 in-flight requests. For production, you’d create a remotely-managed tunnel instead.

Prefer a similar tool? I’ve also written a guide on Tunnelmole, which does the same job of exposing a local service: How to Correctly Install Tunnelmole on a Raspberry Pi.

Part 2: Getting Started

2.1. Install cloudflared

Follow the official installation instructions for your OS: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/

On Linux or macOS you can install it easily — it’s just a single binary.

2.2. Start the tunnel

Make sure the dev server is running, then launch a quick tunnel pointed at it:

Terminal window
cloudflared tunnel --url http://localhost:4321

Cloudflared connects to Cloudflare’s network and prints a random public URL, something like:

https://wider-copyrights-albums-intelligence.trycloudflare.com

Leave that terminal window running — while it’s up, the URL forwards traffic to your localhost server.

2.3. Add the URL to the payment provider

In the Paystack dashboard (Settings → API Keys & Webhooks), paste the tunnel URL into the Webhook URL field. Since the app exposes its webhook endpoint at /api/payment-webhook, the full URL was:

https://wider-copyrights-albums-intelligence.trycloudflare.com/api/payment-webhook

Then enable the events you care about (for this checkout flow it’s charge.success) and save.

Part 3: Testing End-to-End

Now the whole loop works like production. Since the tunnel URL is the local dev site, place the order through the public URL (in an incognito window, as a fresh customer would):

  1. Place an order on the dev site via the tunnel URL
  2. Pay with a test card
  3. Paystack calls the tunnel URL with the payment event
  4. Cloudflare proxies it to the localhost server
  5. The webhook handler verifies the signature, confirms the order, and sends the confirmation email

I could watch it all happen in the dev server logs — webhook received, order confirmed, email queued — without ever leaving my laptop.

The same public link also doubles as a quick demo URL: share it and a client or teammate can interact with the app running on your local machine from anywhere, without deploying anything.

Two gotchas I ran into:

  • The URL changes on every restart. Each time you run cloudflared tunnel, you get a new random subdomain. If you restart the tunnel, you must re-paste the new URL in the Paystack dashboard.
  • It conflicts with an existing config: if you have a config.yaml in ~/.cloudflared, quick tunnels won’t start. Rename it temporarily (mv ~/.cloudflared/config.yaml ~/.cloudflared/config.yaml.bak) and you’re good.

Part 4: References & Further Reading