Webhooks are a mechanism for receiving notifications about events from disparate systems without having to continuously poll them. Also called Reverse APIs, they can be thought of as providing “API specs” that the consuming system needs to implement. One of the challenges of working with webhooks is testing the code that you write to process webhooks in your local development environment. In this article I am going to show you some of the options available to test webhooks locally.
How Do Webhooks Work?
As the world becomes more and more interconnected, it becomes more likely that your application needs to receive information from other systems. One way to do this is to periodically poll the other system to see if any new information is available, but you’d have to poll very frequently to get something close to real-time data. A more efficient way to do this is to use webhooks.
A webhook is essentially an HTTP request sent by the source system to a registered URL in the destination system. In programming terms, webhooks can be thought of as an implementation of the Observer Pattern. This is where the consuming system registers to be notified of events in the source system by registering an endpoint or URL.
Most source systems support security measures such as allowing you to configure Basic Authentication or authentication using Bearer Tokens when registering an endpoint. When an event occurs that a system has registered to be notified of, the source system sends an HTTP request to the registered endpoint with a payload that contains information pertaining to the event.
Webhooks are widely used by modern web applications. For example:
- Paypal uses Instant Payment Notifications (IPNs), which are essentially webhooks to send notifications whenever a payment is received.
- GitHub uses webhooks to inform CI/CD systems when a push event occurs.
- Slack implements incoming webhooks that allow any system to send messages that are published to selected Slack channels.
Working With Webhooks
As mentioned before, webhook URLs can be thought of as reverse APIs that the consuming system needs to implement. Typically, webhook requests are processed by writing code in a programming language such as PHP. Before you write any code to process information sent through a webhook, you need a clear understanding of what the payload looks like. Once you write some code to process the payload, you need to be able to test that your code does what it should when it receives the webhook, such as returning the right status code.
Inspecting Payloads and Webhook Testing
Tools such as Request Bin allow you to create a publicly accessible endpoint you can configure in your source system. Whenever an event that you have registered for occurs, the source system sends an HTTP GET or POST request to your bin, allowing you to inspect the payload. Request Bin also allows you to view items like headers, making debugging and troubleshooting easier. To see how this works, head over to Request Bin and click on the link that says Create a public bin instead. You will be presented with a URL you can configure as the endpoint in your source system.
For example, I added a webhook to my WooCommerce site following the steps described in the WooCommerce documentation. In the “Delivery URL” field, I entered the URL that Request Bin presented me with.
When I created an order, WooCommerce sent an HTTP request to the configured endpoint and I was able to inspect the payload immediately by accessing the URL of my bin in Request Bin.
Typically you would not want to create a public bin, as it’s accessible to anyone that has the URL of the bin. It’s usually better to create a private bin, which requires you to create an account with Pipedream.
Receiving Webhooks Locally
Before deploying any code that processes webhooks, you need to test out your code in your development environment. For that you need to be able to expose your local endpoint as a public URL that you can configure as the destination URL in the system that sends the webhooks. There are quite a few tools available for you to do that.
Exposing Local Endpoints With ngrok
Installing ngrok is pretty straightforward. Head over to the downloads page, get the appropriate binary for your operating system, unzip it, and copy over to a directory on your path. On a Mac you can alternatively use Homebrew to install ngrok:
brew install ngrok/ngrok/ngrok
The next step after installing ngrok is to add an authtoken. Once you create an account and log in, you can obtain your token by visiting your dashboard.
ngrok config add-authtoken (token)
Now you’re ready to expose your local endpoint URL using ngrok. Suppose you have a web application running on port 80. In your terminal, type
ngrok http 80. Your output should look like this:
ngrok (Ctrl+C to quit) Visit http://localhost:4040/ to inspect, replay, and modify your requests Session Status online Account Sanjucta Ghose (Plan: Free) Version 3.0.6 Region Asia Pacific (ap) Latency 89ms Web Interface http://127.0.0.1:4040 Forwarding https://deec-110-227-84-74.ap.ngrok.io -> http://localhost:80 Connections ttl opn rt1 rt5 p50 p90 0 0 0.00 0.00 0.00 0.00
You now have a publicly accessible URL,
https://deec-110-227-84-74.ap.ngrok.io, that you can use as your destination URL when configuring your webhook.
Ngrok offers switches and options that allow you to configure how it works. You can see which options are available with
Using ngrok With Virtual Hosts
It’s likely that you serve your local site through a virtual host, a mechanism that allows you to serve multiple domains from a single web server. Web servers typically implement this by checking the HTTP request’s Host header to determine which website should be served. To expose a site served through a virtual host, you need to ask ngrok to rewrite the Host header of all tunneled requests to match what your web server expects. Suppose you have a local site running at
http://hellfishmedia.test. To expose this site, you could use the following command:
ngrok http --host-header=hellfishmedia.test 80
Using ngrok With WordPress
If the URL you’re trying to expose using ngrok is a WordPress endpoint, the documentation describes a couple of things you need to do to ensure that it works.
Using ngrok With Laravel Valet
You don’t need to install ngrok separately if you are a macOS user and use Laravel Valet as your local development environment. Valet comes bundled with a copy of ngrok which it uses to expose publicly accessible URLs. You can simply navigate to your site directory and use the
valet share command to obtain a publicly accessible URL.
You need to mention the domain name when using the
valet share command if you have associated your site to a domain which is different from the name of the site directory. For example, if you use
valet link hellfishmedia to make your site available at
http://hellfishmedia.test, then you should also use the following command to obtain a publicly accessible URL:
valet share hellfishmedia
Using Local as Your Local Development Environment
Local by WP Engine is a very popular local development environment for WordPress developers. Local makes it very easy to expose a local endpoint using the Live Links feature without requiring any additional software.
Alternatives to ngrok
Several alternatives to ngrok exist that allow you to expose a local endpoint to the internet. I’ve tried out two of them below.
To install Localtunnel, use the command:
npm install -g localtunnel
To expose an application running on
localhost:80, run the following command on the terminal:
lt --port 80
If your local application is running through a virtual host at
http://hellfishmedia.test, then you can use the
lt --port 80 --localhost hellfishmedia.test
Pagekite is another service that allows you to expose a local endpoint. It’s written in Python and requires you to have Python installed on your system. Assuming you are on a Mac and have Python 3.x installed, you can get started quickly by typing the following on your terminal:
curl -O https://pagekite.net/pk/pagekite.py
This will fetch the
pagekite.py program for you. After that you can create your first “kite” using the following command and replacing (yourname) with the name you want to use to identify your kite:
python3 pagekite.py 80 (yourname).pagekite.me
You will be prompted to enter your email address to create an account when you run this command for the first time. Subsequently, when you run this command you will need to log into your account by entering your password. The above command will make
localhost:80 available at
To expose your local site running at
hellfishmedia.test through a virtual host, you can use the following command:
pagekite.py deliciousbrains.test:80 (yourname).pagekite.me +rewritehost
Webhooks are a convenient and now almost ubiquitous way for systems to communicate over HTTP. As a developer, you need to be able to inspect the payload to process webhooks, which is where services like Request Bin come in handy. Testing webhook processing code means you need to expose your local endpoint to the internet. This is made possible by a host of services including ngrok, Localtunnel, and Pagekite.
Have you ever had to write code to process webhooks? If so, what tools did you use to test your webhooks? Let me know in the comments.