What are webhooks and how to use them?

According to OpenAI’s ChatGPT, webhooks are:

Webhooks are like a messenger that tells your computer or phone when something happens on another website.

Imagine you have a friend who loves baking cakes, and you love eating them. Your friend wants to let you know when a new cake is ready, so they send you a message. In the same way, when something happens on a website, like a new user signs up or a new post is created, that website sends a message to your computer or phone using a webhook.

This message tells your computer or phone what happened, and gives it some information about it. Then, you can use that information to do something, like update a file or send a notification to someone.

So, webhooks are a way for websites to talk to your computer or phone and let it know when something important happens!

This is a great explanation even for non-technical people.

For technical folks, it’s easier to understand webhooks as “reverse APIs” or “push APIs” where one server is sending an API request to another server.

What are examples of webhooks?

Most common examples of webhooks are:

  1. Payments - when a payment is made, a webhook is sent to the merchant’s website to notify them that a payment is now complete and you should process the order.
  2. Software testing - when a new change is pushed to GitHub, a webhook is sent to a CI/CD system to notify them that they should run the tests and deploy the new version.
  3. Connecting various services together - when you want to integrate two or more 3rd party services, often they will support webhooks and when they don’t - you can use Webhook Relay to glue them together.
  4. Posting messages to Discord channel is a great way to build bots.

How to receive a webhook in an application?

Webhook, in its essence, is just a POST request to a specific URL on your web server. Instead of a person visiting your website or a CLI application making an API request, it’s a POST request from another website. So, to receive a webhook, you need to have a server that is listening for POST requests on a specific URL.

Le’ts do it in Node.js Express framework as it’s really easy to set up:

npm init
npm install express

Then, create a file index.js and add the following code:

const express = require('express')
const app = express()

const port = 3000

app.post('/webhooks', (req, res) => {
  res.send('webhook received')
})

app.listen(port, () => {
  console.log(`Listening for webhooks on port ${port}`)
})

To start the server:

node index.js

And then, we can send the webhook using curl:

curl -X POST --data '{"important":"data"}' http://localhost:3000/webhooks

This is pretty much as complicated as it gets. You can now receive webhooks from any website and process them in your application.

Webhook best practices

Here are some best practices to follow when using webhooks:

  • When receiving a webhook, always respond with 200 OK. If you respond with a different status code, the sender will try to send the webhook again and again. Only return 5XX status codes if something is failing on your end and you can’t process the webhook (for example can’t connect to the database).
  • Sign webhooks to validate authenticity. The most common way to do it is to use a secret key that is shared between the sender and the receiver. The sender will sign the webhook with the secret key and the receiver will verify the signature. If the signature is invalid, the webhook is discarded. You can check how GitHub does it here.
  • Do not expect webhooks to arrive in the same order as they were sent. Some sender systems try to order them, some don’t but you should not rely on that. If you need to process webhooks in a specific order, you should use a queue system like GCP PubSub, RabbitMQ or just put them into a database and have a background process to go through them in order.
  • If you are building a server that will be sending webhooks, keep the payload size small and specific. Focus on metadata so the receiver can pull any data they need after receiving the webhook.
  • If you need to have multiple different data types types, have the type itself declared at the top level of the payload. For example, if you are sending a webhook when a new user is created, you can have a type field that will be set to user_created and then have all the user data in the payload. This way, the receiver can easily filter out the webhooks they don’t need and carefully decode the payload into the type they can process.

Next steps

  • Our other tutorials tutorials with a bunch of examples
  • Docs can be found here
  • Receiving webhooks on your computer with a help of Webhook Relay