How to add webhooks to a Django project and test them locally
In our daily work, we need to receive information about events in external environments, which is why APIs have become popular today, they allow us to connect our applications with other platforms and exchange information using requests. However, every day greater interconnection is sought, seeking to make fewer requests to the APIs, for this, one of the most used approaches is webhooks.
Webhooks are notifications that are triggered automatically when a specific event occurs and are sent through the web. When the event occurs, a notification that contains the response data (or event data) is immediately sent to your chosen destination: the URL or web application you set. Your webhook should send a 2XX HTTP response status code back to let the platform know that you received the webhook data.
In this way, we no longer have to ask the platform if the event has occurred, but the platform notifies us as soon as it occurs.
Prepare our environment to test webhooks locally
1. Install ngrok to test the webhook locally. It will expose our local server ports to the Internet creating a proxy (https://ngrok.com/download)
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null &&
echo “deb https://ngrok-agent.s3.amazonaws.com buster main” | sudo tee /etc/apt/sources.list.d/ngrok.list &&
sudo apt update && sudo apt install ngrok
2. Sign up on https://dashboard.ngrok.com/ to get a token, you can see it here https://dashboard.ngrok.com/
ngrok authtoken <token>
3. Run ngrok to create the proxy using the same port Django uses when you run python manage.py runserver
ngrok http <port>
In this example port, 8000 is used, so in the terminal, you run:
ngrok http 8000
4. Ngrok is running! We will use the http URL
5. Allow our django project to use that URL to host the app
In your settings.py file (config/settings/local if your project uses Django cookiecutter) add the url provided by ngrok to ‘ALLOWED HOSTS’ without the http…
6. Test that the project is running at the ngrok URL
Open a new terminal and execute python manage.py runserver, and then open the URL provided by ngrok in the browser, you should see the django app running.
With this, we will be able to test the created webhooks locally. Now let’s create one!
Configure Django app-side webhook
1. Create an endpoint for the webhook
We must create an URL to receive the platform requests in the Django project
2. Create a view for the URL
This is an example of a view for the case that we have been developing:
The view you develop should have:
- Definition of post
- Eximit the post from csrf validation
- In this case, the system uses a secret that needs to be validated, a Signature Validation. Here, we must give the platform a ‘secret‘ to validate that the received posts actually come from the source we expect. However, other webhooks may use a different authentication approach, so this is not the only way to do it.
3 Definition of post
Here we will receive the request, we will validate the signature and we will put our logic.
4. Eximit the post from csrf validation
The platform will not send us the csrf token so we need to tell Django that these requests are still valid. For this, we import the decorator and add it to the post.
5. Signature validation:
The implementation of this point may vary on each platform. Look in the webhooks documentation of your platform how it should be implemented.
The general idea behind this is that we must give a secret to the platform, we should have this same secret in our .env. The platform is going to send us the requests with a signature using the secret, a hash. If the data does indeed come from the platform where we have the webhook (we’ll create it later), we should be able to recreate this hash with the secret we have in the .env.
This is what this function does (it’s just an example):
Make sure that the body of the request or the info with which you will recreate the hash is exactly the same as what the platform would use, this includes spaces, indentation, type of quotes (double, single), etc.
Create a webhook on the platform of interest
1. Find the webhook option on the platform
Look for the ‘Webhooks’ option on the platform of your interest, you can validate in the documentation if this feature is available and where to find it. You should look for an icon like. In this case, I will do the examples with Typeforms but you will find that it is similar between platforms.
As you can see, Github is also a platform where webhooks can be created and it looks very similar to the previous example.
2. Create a webhook:
For this you will need:
- Endpoint (Required): URL that will receive the notifications (POST type request) from the platform each time the event occurs. We will use the URL provided by ngrok along with the pattern we defined previously in the urls.py file of the django project to receive the notifications.
- Secret (Optional): To validate that the requests that arrive at our endpoint have been sent by the platform, we must add a secret, otherwise it would not be safe to process that request, its origin would be doubtful.
The endpoint for the URL defined in this Django project would be http://12a3-190-93-142-250.ngrok.io/api/webhooks/typeform/submission
Similarly, it would be done on other platforms, here the Payload URL is our endpoint:
3. Test the webhook
You can fire the event manually from the platform, or if it offers a testing option when selecting the webhook, generate a test request:
There you can validate the body and headers of the request made to the Django app, as well as the response received by us:
It works similarly on other platforms:
You will see that the request will appear in both terminals, where our project is running and the ngrok:
With this you are ready!
The webhook is up and running and our Django app can now validate its requests and process them as needed.