Build Webhooks using Javascript and Node.js (Sample App) April 2022 · ian

Introduction

We've gotten a handful of requests from javascript developers on how to integrate HostedHooks webhooks into their Node.js web applications. So we decided to put together a walkthrough and sample application to show how easy it is.

If you are a Javascript developer that uses Node, then this article is for you. Today we are going to walk through what it takes to add webhooks to an ecommerce application that manages order states (think an overly simplified Shopify app). The app will emulate the backend state management for orders which will trigger webhook events ( via HostedHooks ) whenever the state changes on an order in the example app. The app is fully open sourced (see the resources below) so you can clone the code and run it locally alongside this demo.

We hope you enjoy it and let us know if you have any questions or feedback!

Getting Started

Resources

Here are some additional resources that you may need before we get started:

To integrate the Node.js demo app with the HostedHooks webhook service you will need to start by creating a HostedHooks account. It will only take a few minutes and then we can get started on the fun part.

Step 1: Create an account

Go to www.hostedhooks.com/sign_up to create an account and fill in your organization info.

Step 2: Generate an app for your webhooks

Next, you need to create a new app, this app is where your webhooks will be sent from, just click on "Setup new app" in your dashboard and enter the app name.

For more info, check out our documentation.

Step 3. Create a Webhook Event for your app instance

After creating your app, it's the time to prepare our app to recieve webhooks, let's create a Webhook Event that subscribers can subscribe to.

In our online store demo app, we created an order.created event, that triggers whenever a new order is created.

HostedHooks - Webhook event

More info on how to create webhook events can be found here

Here are some additional events that you may want to create for an ecommerce order tracking application:

  • order.fulfilled - triggered whenever an order is fulfilled.

  • order.shipped - triggered whenever an order is shipped.

  • order.canceled - triggered whenever an order is canceled.

  • order.returned - triggered whenever an order is returned.

We recommend you follow a convention when naming your events, something like namespace.event would work.

Note: The event name being sent from your application must match the event name of the webhook event created in your app instance and the webhook events must be created first.

Nodejs 'Expressjs' app

Now that we are all set with our setup, let's move onto the code, you can clone our ready-to-go app and follow along with us.

First we will set our environemnt variables.

Copy the .env.example file in root directory to .env (which will be ignored by Git):

$ cp .env.example .env

Then set each variable on .env :

  • HOSTEDHOOKSAPIKEY must be the API Key from your account settings.

  • APP_UUID must be the ID of your HostedHooks app instance.

Your .env file should look like this:

HOSTEDHOOKS_API_KEY=...
APP_UUID=...

Running the app

# install dependencies
$ npm install

# start your app
$ npm start

Your app is now running at http://localhost:3000

Setting up the app:

In this app, we route all requests to the /api path:

// app.js
const express = require('express');

// load environment variables
require('dotenv').config();

const orderRoutes = require('./routes/order');

const app = express();

// App global middleware
app.use(express.json());

// Routing your http requests
app.use('/api', orderRoutes);

Here we create two POST request handlers, one for creating an order, and the other for receiving events of a specific order from something like a shipping service:

// routes/order.js
const router = require('express').Router();

const {
    createOrder,
    createEvent
} = require('../controllers/order');

// POST request handler for creating an order
router.post('/order', createOrder);

// This is where your events are processed for a confirmed order
router.post('/orders/:order_id/event', createEvent);

module.exports = router;

Triggering an event:

After processing your POST request and creating the order, you can send a webhook message by calling the sendWebhookMessage function which is a wrapper around the HostedHooks API.

// controllers/order.js
const createOrder = (req, res, next) => {
    const {
        user_id,
        product_id,
        price,
        amount,
        tax,
        total
    } = req.body.order;

    // you may want to store it in a database, and generate the ID automatically
    const data = {
        order_id: 'a1b2c3d4e5f6g7h8i9', // demo ID
        user_id,
        product_id,
        price,
        amount,
        tax,
        total,
    };

    // you can pass in whatever data you want to send with the event
    sendWebhookMessage('order.created', data)
        .then((result) => {
            res.status(201).json({
                message: 'Order has been created successfully',
                result
            });
        })
        .catch((error) => {
            res.status(error.status).json({
                message: error.message
            });
        });
};

The data object is what you want to send to your webhook subscribers, you can customize it however you want.

Building your webhook message:

const fetch = require('node-fetch');

const sendWebhookMessage = (event, data) => {
    var url = new URL(
        `https://www.hostedhooks.com/api/v1/apps/${process.env.APP_UUID}/messages`
    );

    // webhook message
    var messagePayload = JSON.stringify({
        data: {
            order: data, // order data
    },
    version: '1.0',
    event_type: event, // ex: 'order.created'
});

var requestOptions = {
    method: 'POST',
    headers: {
        Authorization: `Bearer ${process.env.HOSTEDHOOKS_API_KEY}`,
        'Content-Type': 'application/json',
    },
    body: messagePayload,
    redirect: 'follow',
};

fetch(url, requestOptions)
    .then((result) => result.text())
    .catch((error) =>
        throw error);
};                                          

The payload of the webhook message is very simple:

  • data: It is your custom payload and the information that will be passed on to your webhook subscribers

  • version: This is the version of the payload that you want to send. You can build different versions of your payloads without breaking your existing subscriber's integrations.

  • event_type: This is the webhook event that was triggered. It is the attribute that we use to route your webhook to the correct subscribers

Add Subscribers

Lastly, before we test the full flow, we will need to setup a subscriber to receive the webhook message. In our example this would be the store or an application that needs to receive order data via webhooks.

We've covered how to setup a subscriber in another article which is linked here here. Please follow along there and come back here once ready.

Testing the app

Now your app is ready to go, copy and paste this curl into your terminal to create an order which will kick off the webhook message.

curl -X POST http://localhost:3000/api/order \
     -H "Content-type: application/json" \
     -d '{ "order": {
              "user_id": "123456789",
              "product_id": "a1b2c3d4e5f6g7h8i9",
              "price": "20.99",
              "amount": "2",
              "tax": "3.8",
              "total": "45.78"
            }
         }'

You should get a 201 Created success status response code which indicates that your webhook message has been sent, and your subscribers were notified.

Webhook Message API

If you hop back to your HostedHooks dashboard, you will also see that the message that we sent has been recieved.

webhook message

To recap the flow: Frontend (cURL request) -> Orders Demo App -> HostedHooks -> Subscriber endpoint (the gif below).

Webhook Repsonse

This is showing us creating an order on our backend (via cURL) , then sending that event over to the HostedHooks API, routing to the subscriber that we created and ultimately passing on the webhook message to the subscribers endpoint (simulated by our HookHelper).

Recap

To recap, we've just walked through how simple and straightforward it is to connect a NodeJS application with HostedHooks to send out webhooks. We hope this was helpful and if you have any questions, please reach out!

Follow Us

You can follow us @hostedhooks or sign up below to receive our updates.

Ready to start sending Webhooks? Get started for Free