Site icon Mailtrap

Webhooks Explained

So, what’s the catch with webhooks?

Not using them nowadays would be like commuting to work on a horse. Charming? Yes, definitely, but not very efficient I’m afraid.

In this article, I explain webhooks and provide you with all the technical tidbits you need to know in order to be webhook-fluent.

What are webhooks?

Webhooks are user-defined HTTP callback functions that allow two applications to communicate with each other. They operate via the web, and refer to hooks in software that trigger actions based on specific events. Hence, the name webhooks. 🪝

Put simply, webhooks are automated messages sent from apps when something happens.

You can think of them as hotel receptionists who, when a new guest arrives (specific event), update the hotel’s records (your app) and check the guests in. Similarly, if a new user registers on your website, a webhook will tell your app, which processes the registration and updates the database.

While user registrations are a common trigger, webhooks can be triggered for other events and have more complex use cases, which I delve into a bit later in the article.

How do webhooks work?

When a specified event triggers your app (e.g., a user registers), the webhook sends an HTTP request, which consists of:

Once the app receives the HTTP request from a webhook, it sends a response that lets your trigger app know if the request is completed successfully. Once processed and added to the database, every component of the request will be available on all client connections that may need the data it contains.

And don’t worry, I’ll also show you how webhooks work in detail via practical examples in a minute.

Webhooks vs API

Both webhooks and APIs (application programming interface) are equally important for communication between software. However, although they are similar in their essence, they work in vastly different ways.

Consider APIs and webhooks as siblings, and let’s say those siblings are on a road trip, sitting comfortably in the backseat. APIs will constantly ask: “Are we there yet? Are we there yet?.” In tech terms, this is called polling, a process that asks another system, or even another API, for an update to see if something has changed.

A webhook, on the other hand, is the silent type, the kid who tells you: hey, just let me know when we arrive!” and will elegantly leave when the car stops. Again, in tech terms, this is called pushing, a process that sends, or ‘pushes’ data to a client or server when a specific event occurs. Hence why webhooks are also known as ‘push APIs’ or ‘reverse APIs’.

In a nutshell:

If you’re interested in the more technical side of this comparison, check out the table below:

FeatureWebhooksAPIs
Data transferEvent-based (push data/pushing)Request-based (pull data/polling)
InitiationInitiated by the serverInitiated by client
EfficiencyMore efficient as it sends data only when there’s an updateLess efficient due to constant polling
ComplexitySimpler for the client as it only listens for incoming dataRequires constant checking by the server
Use caseBest for receiving real-time updatesBest for retrieving data on demand
ImplementationTypically more simple and scalable in real-time applicationsCan be complex, depending on the frequency of data needed
ControlLess control and dependent on the event triggers set up on the serverHigh control over when and what data to fetch

Webhooks vs WebSockets

As a user from a Stack Overflow thread would put it, webhooks and WebSockets solve different aspects of one problem in very different ways. 

The main difference between the two is that webhooks are event-driven, acting only after a specific trigger. On the other hand, WebSockets keep the connection between two apps (or APIs) open, waiting for something to happen. This allows for real-time communication, updates, and synchronization between both sides of the ‘conversation.’

For a clearer picture, here’s how WebSockets work:

Okay, now it’s time for, you guessed it, another allegory! If webhooks are hotel receptionists who only wait for someone to arrive, we can think of WebSockets as some kind of special (quite inefficient) receptionists who keep the doors open all the time, scouting for guests in front of the hotel, even if it’s a very, very slow night.

In a nutshell:

And of course, a tech-table for all you lovers of geeky info out there:

FeatureWebhooksWebSockets
CommunicationOne-way (server to client)Two-way (bidirectional)
Connection typeStateless, triggered by eventsStateful, continuous connection
Data transferData is pushed only when specific events occursContinuous data flow without specific requests
EfficiencyEfficient for sporadic, event-driven updatesMore efficient for frequent and real-time updates
Use caseIdeal for notifications, automated workflows, etc.Best suited for interactive applications requiring real-time communications (e.g., chat apps)
ComplexitySimpler to implement for specific tasks triggered by eventsMore complex due to managing open, persistent connections
Resource usageLower, since connections are made only when events occurHigher due to maintaining open connections
ControlServer controlled, client responds to received dataBoth client and server can initiate communication anytime
ScalabilityScalable with less overhead per message but can face bottlenecks with very high event volumesScalable in terms of concurrent communications but requires more resources to manage connections

What are webhooks used for?

Okay, now that you’re familiar with webhooks, it’s time to go over what they’re typically used for, which includes:

Examples of webhooks

Now, as promised, let me show you some real-world uses and examples of webhooks.

Slack

Slack allows you to modify the platform to send a notification to a channel whenever a critical error occurs in your web application. For example, when the error occurs, the webhook will send a detailed message to a specific Slack channel, with the payload containing all the details and a link to the logs.

Here’s an example of a JSON payload:

{
  "channel": "#alerts",
  "username": "ErrorBot",
  "text": "A critical error occurred in the web application:\n*Error Message:* Unexpected token in JSON\n*Timestamp:* 2024-07-25T14:30:00Z\n*Logs:* <http://example.com/logs/error-1234>",
  "icon_emoji": ":warning:"
}

And here’s a code breakdown with principles you can apply to other examples as well:

Also, did you know that you can combine Slack, Zapier, and ESPs? My colleague Piotr talks about it in his Slack email integration article.

GitHub

With GitHub webhooks, you can make a webhook send a notification to a CI/CD service to trigger a build when a new push is made to a repository.

Here’s what you’d have to do:

Then, you need to set up a new job to handle builds in your CI/CD service and configure it to listen for incoming webhooks from GitHub. And finally, parse the incoming JSON payload to extract relevant information.

JSON example:

{
  "ref": "refs/heads/main",
  "before": "9c54a35c4d76d567bb5e4b2387bd2c5b4bc1c8d2",
  "after": "de8251ff97a4b5b2e8ad488ebcbd4b12c8d8b987",
  "repository": {
    "id": 123456,
    "name": "example-repo",
    "full_name": "user/example-repo"
  },
  "pusher": {
    "name": "user",
    "email": "user@example.com"
  },
  "commits": [
    {
      "id": "de8251ff97a4b5b2e8ad488ebcbd4b12c8d8b987",
      "message": "Fixed bug in API",
      "timestamp": "2024-07-25T14:30:00Z",
      "url": "https://github.com/user/example-repo/commit/de8251ff97a4b5b2e8ad488ebcbd4b12c8d8b987"
    }
  ]
}

Stripe

Now, let’s say you want to update the order status when a payment is successful. Who do you call? Stripe and webhooks, of course!

Here’s how the process would look like:

Then, you’d set up a route in your server to listen to incoming HTTP POST requests from Stripe, verify the Stripe signature, and parse the incoming JSON payload to extract new data.

JSON example:

{
  "id": "evt_1HUz9LFbuFVVSY1hKwJMcHmy",
  "object": "event",
  "api_version": "2020-08-27",
  "created": 1599677774,
  "data": {
    "object": {
      "id": "ch_1HUz8zFbuFVVSY1hkWfyJMWP",
      "object": "charge",
      "amount": 2000,
      "currency": "usd",
      "description": "Payment for order #1234",
      "status": "succeeded"
    }
  },
  "livemode": false,
  "type": "charge.succeeded"
}

With this setup, your server would process the payload and event type and elegantly update the order status in your database. 

Moreover, you can even send a confirmation message with the payment details to the customer.

Shopify

Okay, so you’ve successfully set up webhooks to update orders, but how do you notify your packaging/delivery service that a new order has been created? It’s simple—set up a webhook in Shopify.

Source: Shopify.dev

And here’s how you can set them up:

The next few steps will sound familiar: set up a route in your server to handle POST requests from Shopify and (you know it by now) parse the incoming JSON payload to extract data:

{
  "id": 820982911946154508,
  "email": "user@example.com",
  "closed_at": null,
  "created_at": "2024-07-25T14:30:00-04:00",
  "updated_at": "2024-07-25T14:30:00-04:00",
  "number": 234,
  "note": null,
  "token": "1234567890abcdef",
  "gateway": "credit_card",
  "test": false,
  "total_price": "298.50",
  "subtotal_price": "298.50",
  "total_weight": 0,
  "total_tax": "0.00",
  "currency": "USD",
  "financial_status": "paid",
  "confirmed": true,
  "total_discounts": "0.00",
  "total_line_items_price": "298.50",
  "cart_token": null,
  "buyer_accepts_marketing": true,
  "name": "#1001",
  "total_price_usd": "298.50",
  "line_items": [
    {
      "id": 466157049,
      "variant_id": 39072856,
      "title": "Awesome Product",
      "quantity": 1,
      "price": "199.00",
      "sku": "12345",
      "variant_title": null,
      "vendor": "Awesome Vendor",
      "fulfillment_service": "manual",
      "product_id": 12345678,
      "requires_shipping": true,
      "taxable": true,
      "gift_card": false,
      "name": "Awesome Product",
      "variant_inventory_management": null,
      "properties": [],
      "product_exists": true,
      "fulfillable_quantity": 1,
      "grams": 0,
      "total_discount": "0.00",
      "fulfillment_status": null
    }
  ]
}

Mailtrap

I know, I know, this chapter seems like your typical CTA section where I ask you to buy something from us but trust me, I won’t. Providing a Mailtrap webhook example seemed only logical as I’m well acquainted with the platform.

Anyhow, let’s imagine you want to make your Laravel app send emails and keep an eye out on key deliverability metrics. In such a case, you could use Mailtrap webhooks, which will provide you with information on:

And here’s a JSON example from our webhook documentation:

{
  "events": [
    {
      "event": "delivery",
      "email": "mike@mailtrap.io",
      "category": "Password reset",
      "message_id": "aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
      "sending_stream": "bulk",
      "event_id": "aaaaaaaa-bbbb-cccc-ddd

To learn how to set them up, you can simply follow our in-depth knowledge base article

When shouldn’t you use webhooks? 

As with everything in life, even webhooks have their downsides. So, here are some cases when you shouldn’t use them:

Lastly, I’d also suggest you pass webhooks if you think you don’t need to act on the data immediately. In such a case, you’d be better off using batch processing or simply regular polling.

Moreover, webhooks don’t support bi-directional syncs or HTTP action methods such as PATCH or DELETE. For these purposes, APIs would be your best bet.

Wrapping up

And there you have it; now you know what the catch is with webhooks! 

If you want to cement your knowledge, why not try out webhooks yourself and learn in practice by trial and error? For this, I recommend following our step-by-step tutorial on using webhooks.

Bonus tip: you can test webhooks on the conveniently named Webhooks.site

Up for more reads? I found the original article about webhooks from 2007, written by their creator, John Lindsay, super interesting. Or, even better, visit the Mailtrap blog and read all things email!

Exit mobile version