<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Oluwatobi </title>
    <description>The latest articles on Forem by Oluwatobi  (@ghvstcode).</description>
    <link>https://forem.com/ghvstcode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F342271%2F5678e93f-1c94-47a1-93bc-d170e5bb6bff.jpeg</url>
      <title>Forem: Oluwatobi </title>
      <link>https://forem.com/ghvstcode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ghvstcode"/>
    <language>en</language>
    <item>
      <title>Tools I Use in my Webhook Development Workflow</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Thu, 06 May 2021 16:44:26 +0000</pubDate>
      <link>https://forem.com/hookdeck/tools-i-use-in-my-webhook-development-workflow-1mkp</link>
      <guid>https://forem.com/hookdeck/tools-i-use-in-my-webhook-development-workflow-1mkp</guid>
      <description>&lt;p&gt;Working with webhooks differs from working with the traditional, forward facing HTTP API’s. When working with webhooks, you are required to verify incoming webhooks and provide an HTTPS secure endpoint URL even during development. In this quick guide, I’ll break down some of the tools I use during various stages of working with webhooks for a better development workflow.   &lt;/p&gt;

&lt;h2&gt;
  
  
  Local tunneling
&lt;/h2&gt;

&lt;p&gt;Local tunnels proxy external requests to a port on your local machine, making the web service running locally on your machine accessible over the internet. Local tunnels are useful when working with webhooks, as most API providers require that a publicly accessible/HTTPS secure URL is provided when registering a webhook.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hookdeck CLI&lt;/strong&gt;
&lt;a href="https://hookdeck.com/docs/using-the-cli#using-the-hookdeck-cli" rel="noopener noreferrer"&gt;The Hookdeck CLI&lt;/a&gt; can be used to forward webhooks to your local server. The Hookdeck CLI is completely free, and offers unlimited and permanent URL’s unlike other local tunneling solutions in the market. One of my favourite features of the Hookdeck CLI is the replay feature. Your webhook history is preserved across sessions and can be replayed/used for testing. Something else that’s convenient is receiving permanent URLs. To get started with using the Hookdeck CLI for receiving incoming webhooks on your local machine, check out this guide.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ngrok.io&lt;/strong&gt;
&lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;Ngrok&lt;/a&gt; is a local tunneling service that exposes local servers behind NATs and firewalls to the public internet over secure tunnels. Ngrok has a lot of great features, such as authenticated access, reserved and custom domains. Personally, when working with Ngrok, I use a node wrapper around Ngrok published on NPM. If you have node installed on your computer, you might find the NPM package more convenient, depending on your needs. Learn &lt;a href="https://dev.to/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779"&gt;how to set up&lt;/a&gt;&lt;a href="https://dev.to/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779"&gt;.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Localtunnel.github.io&lt;/strong&gt;
&lt;a href="https://github.com/localtunnel/localtunnel" rel="noopener noreferrer"&gt;Localtunnel&lt;/a&gt; is an open-source alternative to Ngrok that can be installed via NPM. With Localtunnel, you can clone the repository on GitHub and host your own local tunnel server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Webhook debugging
&lt;/h2&gt;

&lt;p&gt;Webhook debugging is an important step in the webhook development workflow. It entails detecting and removing bugs related to your webhooks. This can be done by inspecting HTTP requests. Webhook debugging tools can be used to examine webhook payloads to detect any configuration errors. A good debugging tool should be able to show you the full details of the webhook request, the request payload and headers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Requestbin.com&lt;/strong&gt;
According to their website, &lt;a href="https://requestbin.com/" rel="noopener noreferrer"&gt;Requestbin&lt;/a&gt; makes it easy to inspect webhook events in a human, friendly way or via REST API’s. This tool comes in handy whenever I need to inspect incoming requests, or view the payloads and headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hookdeck.com&lt;/strong&gt;
&lt;a href="https://hookdeck.com/incoming" rel="noopener noreferrer"&gt;Hookdeck&lt;/a&gt; is a SaaS offering that has features for debugging webhook payloads. I use Hookdeck to inspect webhook payloads as it provides a nice and clear interface for viewing webhook payloads. Using Hookdeck, you also get the ability to retry failed webhook events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hookbin.com&lt;/strong&gt;
&lt;a href="https://hookbin.com" rel="noopener noreferrer"&gt;Hookbin&lt;/a&gt; is a free alternative to Requestbin! Hookbin provides functionality for parsing, collecting &amp;amp; viewing HTTP requests. Hookbin provides SSL secured endpoints, private endpoints and supports multiple content types.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Webhook infrastructures
&lt;/h2&gt;

&lt;p&gt;Webhook infrastructures are systems used for managing webhook connections and working with webhooks. Typically, webhook infrastructures should provide functionality for queuing, monitoring and retrying webhooks. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hookdeck.com&lt;/strong&gt;
&lt;a href="https://hookdeck.com/why-hookdeck" rel="noopener noreferrer"&gt;Hookdeck&lt;/a&gt; focuses on webhook reliability. It provides auto-scaling, throttled delivery, monitoring and webhook replay, making sure developers are never losing their webhooks. Hookdeck isn’t platform specific, so I added all my webhooks onto Hookdeck which makes it easy to manage them from one place. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;These are some of my favourite tools for working with webhooks. &lt;br&gt;
What are your favourite tools for working with webhooks? Leave a comment below.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Doing More With Dev.to Webhooks</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Tue, 04 May 2021 12:25:56 +0000</pubDate>
      <link>https://forem.com/hookdeck/doing-more-with-dev-to-webhooks-695</link>
      <guid>https://forem.com/hookdeck/doing-more-with-dev-to-webhooks-695</guid>
      <description>&lt;p&gt;I love reading and publishing articles on Dev.to! Recently, I discovered the Dev.to API has webhook offerings. I built an integration to automatically notify colleagues within a Slack workspace whenever I make updates to an already published article. This integration saves time and ensures my colleagues and friends are up to date with all the articles I publish. In this short post, I will show you how to build a similar service, leveraging on Dev.to &amp;amp; Slack webhooks. &lt;/p&gt;

&lt;p&gt;In this guide, we will be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a web server to receive webhooks &lt;/li&gt;
&lt;li&gt;Subscribing to Dev.to API to send us webhooks &lt;/li&gt;
&lt;li&gt;Updating our web server to trigger a Slack notification when we receive Dev.to webhooks&lt;/li&gt;
&lt;li&gt;Deploying our integration in production &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building A Web Server
&lt;/h2&gt;

&lt;p&gt;The first step in building out this service is to spin up a web server. The web server we build will receive webhooks from Dev.to and post notifications to Slack. To start, create an index.js file to hold the code for our web server. Within the index.js file, add the following lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhooks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App is running on port 3000`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above snippet is code for a basic NodeJS server that runs on port 3000. As we move along in this guide, we will build on the server to cater for more functionalities required by the service we are building out.&lt;/p&gt;

&lt;p&gt;Next, we run our server using a local tunneling solution so that we can have an HTTPS secured URL even while in development mode. There are various local tunneling tools such as Ngrok &amp;amp; the Hookdeck CLI which could be used to proxy external requests to our server. In this guide, we will be using the Hookdeck CLI as the local tunnelling solution. To learn more about how the Hookdeck CLI can improve your development webflow, &lt;a href="https://dev.to/hookdeck/local-webhook-development-using-hookdeck-cli-1om"&gt;check out this guide I wrote&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To tunnel the above server using the Hookdeck CLI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/hookdeck/hookdeck-cli#installation" rel="noopener noreferrer"&gt;Install Hookdeck CLI&lt;/a&gt; on your local machine&lt;/li&gt;
&lt;li&gt;Run the &lt;code&gt;hookdeck listen 3000&lt;/code&gt; command in your terminal to make Hookdeck CLI listen for incoming connections &lt;/li&gt;
&lt;li&gt;Choose the “Create a New Source” option to create a new connection source &lt;/li&gt;
&lt;li&gt;Respond to the terminal prompt with a desired source label and specify “/webhooks” as the path webhooks should be forwarded to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After following these steps, The Hookdeck CLI will provide you with a webhook URL printed in the terminal. Keep this URL handy because we will be using it in the next step when we set up Dev.to webhooks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tw2f8ii8v3ct18r35pa.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tw2f8ii8v3ct18r35pa.jpeg" width="800" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Dev.to Webhooks
&lt;/h2&gt;

&lt;p&gt;In this section, we will configure Dev.to webhooks to send notifications to the webhook URL from above whenever the &lt;code&gt;article_updated&lt;/code&gt; event is triggered. To register a Dev.to webhook, we will need to make an authenticated POST request to the &lt;code&gt;/webhooks&lt;/code&gt; endpoint of the Dev.to API. &lt;/p&gt;

&lt;p&gt;To get your Dev.to API key:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Head over to your Dev.to Account &amp;amp; &lt;a href="https://dev.to/settings/account"&gt;Navigate to settings&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In the "DEV API Keys" section create a new key by adding a description and clicking on "Generate API Key”
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy2fem39279y4bi60hzxd.jpeg" width="800" height="489"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Right after generating the API key, copy it and keep it safe. It will be used when making the HTTP request to Dev.to.&lt;/p&gt;

&lt;p&gt;The payload of the request to Dev.to will contain the target URL that will receive webhook notifications. The other field to be included in the payload is the event array which will contain the list of events that should trigger the webhook. You can use any tool of your choice, like Postman or CURL to make a POST request to the API. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "webhook_endpoint": {
    "target_url": "Hookdeck-cli-provided-URL",
    "source": "DEV",
    "events": [
      "article_updated"
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A sample JSON payload for the creation of a new Dev.to webhook will look similar to the above snippet.&lt;/p&gt;

&lt;p&gt;After making a POST request to the Dev.to API for the creation of a webhook, whenever the &lt;code&gt;article_update&lt;/code&gt; event is triggered, the web server we created up above will receive notifications, as seen below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxr0wm4luxxfqycrnpehx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxr0wm4luxxfqycrnpehx.png" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending Notifications To Slack
&lt;/h2&gt;

&lt;p&gt;In the previous section, we configured Dev.to webhooks to send notifications to our server whenever an article is updated. In this section, we would add more logic to our server such that it sends a message to a specified workspace whenever a Dev.to webhook notification is received.&lt;br&gt;
Before moving further, we need to set up Slack incoming webhooks. After setting up Slack incoming webhooks, we will receive a URL which we will make POST requests to, whenever we need to send a message to a Slack workspace.&lt;/p&gt;

&lt;p&gt;We will set up Slack incoming webhooks in the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://api.slack.com/apps?new_app=1" rel="noopener noreferrer"&gt;Create a new Slack app&lt;/a&gt; in the workspace you would like to send messages on&lt;/li&gt;
&lt;li&gt;Select the incoming webhooks menu from your newly created app homepage &amp;amp; toggle it on&lt;/li&gt;
&lt;li&gt;Scroll down the incoming webhooks page and click on the &lt;strong&gt;“Add New Webhook to Workspace”&lt;/strong&gt; button&lt;/li&gt;
&lt;li&gt;Pick a channel with the workspace that will receive the updates, then click “Authorize”&lt;/li&gt;
&lt;li&gt;Copy the incoming URL&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With Slack set up, we can then go and update the &lt;code&gt;/webhooks&lt;/code&gt; route from up above, such that the logic for making a POST request to the Slack incoming URL is included. Head to the NodeJS project directory and run the command &lt;code&gt;npm i request&lt;/code&gt; to install “request,” the NPM package that will help us in making HTTP requests. Next, update your index.js file by adding the following lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhooks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;//MAKE POST REQUEST TO SLACK&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://hooks.slack.com/services/T01XXXXXX/B01XXXXXX/XXXXXX&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
              &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hey! Toby Just made an update to an article published on dev.to! You should check it out`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App is running on port 3000`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As seen in the snippet above, we make a POST request to the Slack incoming URL in order to send a message to a workspace right when an article is updated. At this point, when an &lt;code&gt;article-update&lt;/code&gt; event is triggered, you should receive a notification like this on Slack:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzyu14g0mgb6rk7ui7iqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzyu14g0mgb6rk7ui7iqn.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting Ready For Production&lt;/strong&gt; &lt;br&gt;
Great! Now that we have the integration running in development, it’s time to deploy it to production. First, we need to deploy our web server to a proper hosting service like Heroku. We will deploy the server to Heroku in the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log in to the Heroku dashboard&lt;/li&gt;
&lt;li&gt;Create a new Heroku application&lt;/li&gt;
&lt;li&gt;Initialize a git repository for your project if it doesn't exist&lt;/li&gt;
&lt;li&gt;Push the changes to the Heroku server by running the &lt;code&gt;git push heroku master&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy and save the URL address provided by Heroku&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To learn more about deploying to Heroku, &lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;check this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After deploying the service to Heroku, we will be deploying the service on Hookdeck to monitor the webhooks and manage error handling. We will set up our service to use Hookdeck in the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head over to the Hookdeck dashboard and &lt;a href="https://dashboard.hookdeck.com/webhooks/new" rel="noopener noreferrer"&gt;create a new connection&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add the URL of the server from up above as the destination URL of the connection
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feh2lby0izt9rmqba9oqa.jpeg" width="800" height="291"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;To learn more about setting up Hookdeck, check out the &lt;a href="https://dev.to/hookdeck/creating-a-webhook-connection-on-hookdeck-25e0"&gt;comprehensive guide&lt;/a&gt; we wrote on setting up Hookdeck.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;After setting up Hookdeck, we need to replace the Dev.to request URL with that of our new Hookdeck connection to ensure that Dev.to webhook notifications are sent to Hookdeck. We will update the Dev.to webhooks in the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy the URL of your Hookdeck connection &lt;/li&gt;
&lt;li&gt;Make a POST request to the Dev.to webhook endpoint, include the Hookdeck connection URL in the payload as seen below:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    {
      "webhook_endpoint": {
        "target_url": "https://events.hookdeck.com/e/src_FyjvCbbZ4GOBxxxxxxxx",
        "source": "DEV",
        "events": [
          "article_updated"
        ]
      }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You are set up in production to safely receive webhooks from Dev.to! We will trigger the test to ensure everything works just fine, even in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22hmzjswgakgw91n184x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22hmzjswgakgw91n184x.png" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations, you can now keep colleagues and friends in your workspace up to date with access to the latest articles you have written using Dev.to webhooks! &lt;br&gt;
Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>tutorial</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Local Webhook Development Using Hookdeck CLI</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Thu, 29 Apr 2021 22:47:01 +0000</pubDate>
      <link>https://forem.com/hookdeck/local-webhook-development-using-hookdeck-cli-1om</link>
      <guid>https://forem.com/hookdeck/local-webhook-development-using-hookdeck-cli-1om</guid>
      <description>&lt;p&gt;For many developers, working with webhooks can be stressful. Typically, developers need to set up a local tunneling solution for proxying external requests to their local server, and also set up a tool for inspecting webhook payloads. The lack of proper tooling for working with webhooks in a development environment inspired us to build the Hookdeck CLI.&lt;/p&gt;

&lt;p&gt;The Hookdeck CLI is a command line interface which provides functionality for proxying external requests to a port on your local machine and inspecting webhook payloads. Although it uses a different approach and philosophy, the Hookdeck CLI is a replacement for Ngrok and alternative HTTPS tunnel solutions. Using the Hookdeck CLI requires minimal setup, allowing developers to focus on more important parts of their webhook development workflows.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll learn how to use Hookdeck CLI to develop and test webhook integrations locally. We’ll also take a step by step approach and integrate with Dev.to webhook offering as an example.&lt;/p&gt;

&lt;p&gt;After reading this, you will learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Set up Hookdeck CLI &lt;/li&gt;
&lt;li&gt; Receive events on Localhost&lt;/li&gt;
&lt;li&gt; Inspect payloads on Hookdeck Dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting Up The Local Server
&lt;/h2&gt;

&lt;p&gt;To illustrate how the Hookdeck CLI simplifies local webhook development, we will integrate with Dev.to webhooks. The integration will consist of a simple server that receives webhook notifications when a specified event is triggered and prints out the notification to the console. To get started, initialize a NodeJs project and add the following lines of code in the newly created &lt;code&gt;index.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App is running on port 3000`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simple server we just created will receive notifications from Dev.to and print the notifications to the console once we have registered Dev.to webhooks.&lt;/p&gt;

&lt;p&gt;When registering our Dev.to webhook, we are required to provide a target URL which will receive webhook notifications. Since we are in a development mode, we will use the Hookdeck CLI to proxy external requests to our server and generate a target URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working With The Hookdeck CLI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;br&gt;
Before we can get to exploring the various rich features of the Hookdeck CLI, we need to install it onto our local computers. The method of installation will differ slightly based on the operating system your machine runs on. Various installation methods include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MacOS Installation 

&lt;ul&gt;
&lt;li&gt;The Hookdeck CLI can be installed on MacOS using Homebrew. Homebrew is a package manager for MacOS. Run the following command to install the Hookdeck CLI on your Mac:
$ brew install hookdeck/hookdeck/hookdeck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Windows Installation

&lt;ul&gt;
&lt;li&gt;On a Windows machine, the Hookdeck CLI can be installed via the scoop package manager by running the following command:
$ scoop bucket add hookdeck &lt;a href="https://github.com/hookdeck/scoop-hookdeck-cli.git" rel="noopener noreferrer"&gt;https://github.com/hookdeck/scoop-hookdeck-cli.git&lt;/a&gt;
$ scoop install hookdeck&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Linux Installation 

&lt;ul&gt;
&lt;li&gt;Installing the Hookdeck CLI on a Linux machine requires a few more steps than other operating systems. To Install Hookdeck CLI on the Linux distro of choice: 

&lt;ol&gt;
&lt;li&gt;Download the latest Linux tar.gz file from &lt;a href="https://github.com/hookdeck/hookdeck-cli/releases/latest" rel="noopener noreferrer"&gt;https://github.com/hookdeck/hookdeck-cli/releases/latest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Unzip the file: tar -xvf hookdeck_X.X.X_linux_x86_64.tar.gz&lt;/li&gt;
&lt;li&gt;Navigate to the unzipped directory &lt;/li&gt;
&lt;li&gt;Run the executable: ./hookdeck&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After following the steps relevant to your operating system, the Hookdeck CLI should be installed on your local machine. To test that the CLI was installed correctly, you can run the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ hookdeck version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If you have correctly installed the Hookdeck CLI, you should see the version of Hookdeck CLI you installed printed out. At the time of writing this, the latest Hookdeck version is 0.2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start a session&lt;/strong&gt;&lt;br&gt;
With the Hookdeck CLI installed, we need to configure it to listen for new connections and incoming requests so that our local server will be able to receive webhook notifications. Before you are able to listen for incoming requests, you need to log in to your Hookdeck account. To log in, run the &lt;code&gt;$ hookdeck login&lt;/code&gt; command. You will be prompted to press the “Enter” key, and will then be directed to your browser where you will be authenticated and authorized to interact with the other features of the Hookdeck CLI. You can also run the &lt;code&gt;$ hookdeck login&lt;/code&gt; command with the &lt;code&gt;-i&lt;/code&gt; flag if you would like to manually provide an API key to  authenticate.&lt;/p&gt;

&lt;p&gt;To start a forwarding session, run the following command: &lt;code&gt;hookdeck listen 3000&lt;/code&gt;. Notice how we use the exact port our local server runs on as an argument when running the Hookdeck “listen” command. After running this command, you will be prompted to choose an existing source or create a new source. Choose the “Create New Source” option and fill in the prompt with your source label, &lt;code&gt;Devto webhooks&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The next question in the CLI prompt requires that we specify the path on our local server where webhooks should be forwarded to, which based on the server created above is the &lt;code&gt;/webhook&lt;/code&gt; route. Fill the prompt asking for the connection label with a friendly alias for your soon to be created connection. Keep the URL provided by Hookdeck handy, as we will use it when registering our Dev.to webhook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jwgfwtja6ho1e6rdo3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jwgfwtja6ho1e6rdo3p.png" alt="Image Showing the Hookdeck CLI in action" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome! We now have the Hookdeck CLI set up and listening for incoming requests. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mf5hrthwpvym9gd9p0y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mf5hrthwpvym9gd9p0y.gif" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In an event where you get stuck down the line run any of the following commands to access the Hookdeck CLI help menu:&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ hookdeck --help
$ hookdeck -h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Registering Dev.to webhooks&lt;/strong&gt;&lt;br&gt;
Now that we have successfully set up the Hookdeck CLI to listen and forward requests to our local server, we can go ahead and register the Dev.to webhook. To register Dev.to webhooks, we need to make a POST HTTP request to the &lt;code&gt;/webhook&lt;/code&gt; route of the Dev.to API. The payload of the request to Dev.to will contain a target URL field, whose value will be the URL of our Hookdeck connection. A sample payload for the POST request to the Dev.to webhook should look similar to the JSON object below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webhook_endpoint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;target_url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://events.hookdeck.com/e/src_5UbKi...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DEV&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;events&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;article_updated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After making the POST request to the Dev.to API, an output like this can be seen printed to your terminal whenever the &lt;code&gt;article_update&lt;/code&gt; event is triggered:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw5ntp729ni3xaishu87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw5ntp729ni3xaishu87.png" alt="Image Showing Payload In Console" width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inspecting payloads&lt;/strong&gt;&lt;br&gt;
Aside from proxying external requests to a port on our local machine, The Hookdeck CLI is very useful for inspecting webhook payloads. We will be inspecting payloads received from Dev.to webhooks in the steps below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Copy the inspect URL Hookdeck provides, after starting a “listen” session.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb90xug1jp2zwg2cm4k3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb90xug1jp2zwg2cm4k3n.png" alt="Image Showing the Hookdeck CLI listening for connections" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visit the URL in the browser to view and inspect the webhook payload. The output of the payload on the Hookdeck dashboard should look similar to the image below, which makes visible the body of the webhook notification sent by Dev.to as well as the headers. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38i5unvm3o8voh9odz4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38i5unvm3o8voh9odz4x.png" alt="Image Showing Webhook Payload" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;We have learned how to set up Hookdeck CLI, proxy external requests to our local server, and inspect payloads. The Hookdeck CLI helps makes the entire process of working with webhooks locally seamless.&lt;br&gt;
Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Glossary&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source — A &lt;a href="https://hookdeck.com/docs/sources" rel="noopener noreferrer"&gt;Source&lt;/a&gt; represents an API sending you a webhook, such as Shopify, Stripe, Github, etc. Each source is assigned a unique &lt;em&gt;Webhook URL&lt;/em&gt; that can be provided to the sender.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://hookdeck.com/docs/destinations" rel="noopener noreferrer"&gt;Destination&lt;/a&gt; represents an endpoint on your own server. Hookdeck will be forwarding all webhooks received to that URL with an HTTP POST request containing the original data from the sender along with additional Hookdeck metadata.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webhooks</category>
      <category>showdev</category>
      <category>tutorial</category>
      <category>development</category>
    </item>
    <item>
      <title>Automating CI/CD with webhooks: Vercel Deploys Via SMS</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Sat, 17 Apr 2021 01:41:44 +0000</pubDate>
      <link>https://forem.com/hookdeck/automating-ci-cd-with-webhooks-vercel-deploys-via-sms-4i1p</link>
      <guid>https://forem.com/hookdeck/automating-ci-cd-with-webhooks-vercel-deploys-via-sms-4i1p</guid>
      <description>&lt;p&gt;In an earlier article on this blog, I taught you how to leverage the power of webhooks to automate Netlify deploys. In this tutorial, you can follow along as we tackle Vercel,a deployment and collaboration platform for frontend developers that is similar to Netlify. I will show you how to build a service that triggers Vercel deploys via SMS so that once an SMS with a specific keyword is received, the Vercel build is triggered. In order to do this, we will be connecting Twilio webhooks with Vercel’s webhook equivalent, deploy hooks.&lt;/p&gt;

&lt;p&gt;After reading this post, you will learn how to :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure Vercel deploy Hooks&lt;/li&gt;
&lt;li&gt;Configure Twilio webhooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;We have written a couple of articles on the basics of working with Twilio webhooks&lt;/em&gt; &lt;em&gt;-&lt;/em&gt; &lt;em&gt;I suggest you&lt;/em&gt; &lt;a href="https://hookdeck.com/platforms/twilio-webhooks-features-and-best-practices-guide#twilio-webhooks-features" rel="noopener noreferrer"&gt;&lt;em&gt;check them out&lt;/em&gt;&lt;/a&gt; &lt;em&gt;before continuing with this post.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Vercel’s Deploy Hooks
&lt;/h2&gt;

&lt;p&gt;To start building this service, we need to configure Vercel’s deploy hooks. Once this is done, you will be provided with a URL that triggers Vercel builds when it receives an HTTP request. &lt;br&gt;
First, head over to your &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; dashboard and select the project that you would like to set up automatic deploys for. Navigate to the Settings page of your project, and select the “Git” menu item. Scroll to the “Deploy Hooks” section, write a suitable name for your deploy hook in the menu, and select a branch to be deployed from the dropdown menu. After filling the form, click the “Create Hook” button. If everything goes well, you should receive a URL, which is your deploy hook trigger. &lt;em&gt;It is important to note that Vercel deploy hooks are only available for projects connected to a&lt;/em&gt; &lt;em&gt;G&lt;/em&gt;&lt;em&gt;it repository.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating A Server
&lt;/h2&gt;

&lt;p&gt;In this section, you will learn how to set up a server that makes an HTTP request to the trigger URL, once it has received a webhook notification from Twilio’s webhooks. Start by initializing a new NodeJS project, and add the following lines of code to the root file of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TriggerDeploy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.vercel.com/v1/integrations/deploy/xxxxxxx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasWord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldTrigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hasWord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deploy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shouldTrigger&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nc"&gt;TriggerDeploy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App is running on port 3000`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As seen in the code snippet above, if you receive a request that contains the word “deploy,” you should configure your Web Server to make an HTTP request to Vercel’s trigger URL. Make sure to update the URL field in the &lt;code&gt;TriggerDeploy&lt;/code&gt; function above with the URL you received after creating the deploy hook over at Vercel. With this server in place, you can use a local tunneling tool like Ngrok in a development environment to get a URL. The URL for this server is required to configure Twilio webhooks in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Twilio Webhooks
&lt;/h2&gt;

&lt;p&gt;It is now time for us to walk through the set-up of Twilio webhooks. To get started, head to the phone number tab on the Twilio console, scroll to the messaging section, and change the value of the “Configure With” field to “Webhooks”. Next, input the URL of the server from above into the “A Message Comes In” field. After filling the form, save the settings! &lt;/p&gt;

&lt;p&gt;At this point, you are good to go. Incoming messages to your Twilio phone number will now automatically trigger Vercel deploy builds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Ready For Production
&lt;/h2&gt;

&lt;p&gt;Before you can deploy your service to production, there are still some loose ends that need tying up. Now, you need to deploy your web server to a proper hosting service like &lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;H&lt;/a&gt;&lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;eroku&lt;/a&gt;. After this, you must also set up Hookdeck. Hookdeck controls ingestion and errors in webhook connections, ensuring that you will not miss out on any webhook notifications sent to Vercel. To get started setting it up, &lt;a href="https://dev.to/hookdeck/creating-a-webhook-connection-on-hookdeck-25e0"&gt;check out our guide&lt;/a&gt;. Once this is done, you just need to update the webhook URL field over at Twilio with the new URL Hookdeck has provided, and your service is complete!&lt;/p&gt;

&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we have learned how to automate deploys to Vercel using the power of Webhooks. It’s not as hard as you think - especially when using Hookdeck! &lt;/p&gt;

&lt;p&gt;Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webhooks</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Automating CI/CD with Webhooks: Netlify Deploys Using A Slack Bot</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Fri, 16 Apr 2021 05:51:55 +0000</pubDate>
      <link>https://forem.com/hookdeck/the-power-of-webhooks-automating-netlify-deploys-using-a-slack-bot-3178</link>
      <guid>https://forem.com/hookdeck/the-power-of-webhooks-automating-netlify-deploys-using-a-slack-bot-3178</guid>
      <description>&lt;p&gt;I believe that everything that can be automated should be automated. That is why I decided to harness the power of webhooks and build a Slack bot, instead of going to my Netlify dashboard to trigger a deploy when I make a change to the code for my website. The Slack bot automates the triggering of new Netlify builds, which saves time and reduces the friction that comes with manually triggering Netlify deploys. In this post, I will help you along as you learn how to build out this service and automate your deploys.&lt;/p&gt;

&lt;p&gt;After reading this post, you will learn how to :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build a Slack bot &amp;amp; configure Slack webhooks&lt;/li&gt;
&lt;li&gt;Configure Netlify Build Hooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Building The Slack Bot&lt;/strong&gt;&lt;br&gt;
The Slack bot is crucial to this service. Once a user on our workspace mentions the bot, the goal is for it to trigger a Netlify deploy. To get started creating this feature, head over to the Slack API dashboard and create a new Slack app by clicking the “Create A Custom App” button at the top of the page. Next, write the name of the app in the Popup menu, select the workspace the bot will be associated with, and save. After creating the Slack app, it’s time to hook into Slack webhooks to receive notifications when your bot gets mentioned in a Slack channel! &lt;/p&gt;

&lt;p&gt;Before you can subscribe to a specific event, you need to provide Slack with a URL. This link is where Slack will send notifications when the event subscribed to is triggered. Slack also requires confirmation that you have control over the URL, and asks you to echo the challenge request parameter they send.&lt;/p&gt;

&lt;p&gt;Below is an implementation of the logic of the web server that Slack will send webhook notifications to, written in NodeJS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;challenge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;challenge&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App is running on port 3000`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This server can then be deployed using a local tunneling tool like &lt;a href="https://dev.to/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779"&gt;Ngrok&lt;/a&gt; or Hookdeck CLI. After deploying the above server, you can continue to set up the Slack bot. In the home page of the Slack app we created above, navigate to the event subscriptions page and toggle the “Enable Events” button. Input the URL of the server created above as the value for the request URL field. Select the &lt;code&gt;app_mention&lt;/code&gt; from the dropdown menu under the "Subscribe to Bot Events” tab. &lt;/p&gt;

&lt;p&gt;The last step in setting up Slack is installing the Slack bot we just configured to our Slack workspace. Click the “Install App” menu on the left hand side of the dashboard, and go ahead and authorize the bot to access your workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Netlify
&lt;/h2&gt;

&lt;p&gt;In the previous section, we set up the Slack bot to send notifications to our URL any time it is mentioned in the workspace. In this section, you will learn how to set up Netlify’s webhook offering, called “build hooks*.&lt;strong&gt;”* In the Netlify dashboard, navigate to **Site settings &amp;gt; Build &amp;amp; deploy &amp;gt; Continuous deployment &amp;gt; Build hooks&lt;/strong&gt;. Select “Add Build Hook,” a suitable name for the hook, as well as the Github branch that should be triggered by the hook. After creating the build hook, you will be provided with a URL that will trigger the build once it receives a request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;Our app is coming together nicely. In a couple more steps, you will be done configuring this service. It must be configured so that immediately after a webhook notification is received from Slack, a request is made to Netlify and the build is triggered. To do that, you will need to modify the code for the server we created above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TriggerDeploy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.netlify.com/build_hooks/xxxxxxxxxxxx3b15ad&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasWord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldTrigger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hasWord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;deploy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shouldTrigger&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
           &lt;span class="nc"&gt;TriggerDeploy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The snippet above contains three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;TriggerDeploy&lt;/code&gt; function — this function simply makes a post request to the Netlify build hook URL.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;hasWord&lt;/code&gt; function, which checks whether a word is contained in a sentence and returns a Boolean value.&lt;/li&gt;
&lt;li&gt;The request handler. Within the request handler function, we extract the notification text sent by Slack from the request body, invoke the hasWord function, and conditionally invoke the TriggerDeploy function (if the word “Deploy” is present in the notification sent by Slack).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, you can go ahead and try this service out. Mention the Slack bot in your workspace, and say deploy! You will notice that a new build on your Netlify dashboard will be triggered, as seen below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84tgbhsmfzmcnjrtpvuo.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84tgbhsmfzmcnjrtpvuo.jpeg" width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Ready For Production
&lt;/h2&gt;

&lt;p&gt;Before you deploy to production, it is important to tidy up your service. You will need to &lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;deploy&lt;/a&gt; &lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;y&lt;/a&gt;&lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;our web server to a proper hosting service like&lt;/a&gt; &lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;H&lt;/a&gt;&lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;eroku&lt;/a&gt;. After this, set up Hookdeck to handle the ingestion and error handling of the webhook connections. This ensures that you will not miss any webhook notifications. (To learn how to set up a webhook connection in Hookdeck, &lt;a href="https://dev.to/hookdeck/creating-a-webhook-connection-on-hookdeck-25e0"&gt;check out this guide&lt;/a&gt; we wrote). Finally, update the request URL field with the new URL Hookdeck has provided. &lt;/p&gt;

&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we have learned how to harness the power of webhooks to automate what could otherwise be a very boring task: manually triggering Netlify deploys. We also learned about Slack bots and webhooks, and gained some confidence in our skills along the way. Thanks for joining me!&lt;/p&gt;

&lt;p&gt;Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Creating a webhook connection on hookdeck</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Sat, 10 Apr 2021 00:55:33 +0000</pubDate>
      <link>https://forem.com/hookdeck/creating-a-webhook-connection-on-hookdeck-25e0</link>
      <guid>https://forem.com/hookdeck/creating-a-webhook-connection-on-hookdeck-25e0</guid>
      <description>&lt;h1&gt;
  
  
  Creating A Webhook Connection On Hookdeck
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://hookdeck.com/" rel="noopener noreferrer"&gt;Hookdeck&lt;/a&gt; offers a complete webhook infrastructure to help tech teams instantly and reliably process, manage and troubleshoot their incoming webhooks. Practically that means it's an infrastructure that scales seamlessly and does all the heavy lifting – error handling, retries, alerting, logging, and queuing.&lt;/p&gt;

&lt;p&gt;I use Hookdeck to manage my webhook connections with various third-party services.&lt;br&gt;
In this quick guide, I will show you how to set up a webhook connection using Hookdeck via the dashboard. &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;In this section, I'll show you step by step how to create a webhook connection using Hookdeck. &lt;br&gt;
The first step in creating a webhook connection using Hookdeck is to sign in to your Hookdeck account. Once signed in, navigate to the Hookdeck dashboard and select the &lt;strong&gt;connections&lt;/strong&gt; tab.&lt;br&gt;
To create a new webhook connection, click the &lt;strong&gt;create&lt;/strong&gt; button at the top of the connections page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwkjrqcpo2uzy9mjylez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwkjrqcpo2uzy9mjylez.png" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, fill the three required fields on the pop-up menu — Source, Destination &amp;amp; Ruleset. Hookdeck gives you the option to either select previous values or to create entirely new ones. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9edt0vhhnu7238qzp7rz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9edt0vhhnu7238qzp7rz.jpeg" width="800" height="941"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating a webhook connection, Hookdeck provides you a unique URL. You should copy and use it as the URL endpoint when registering a webhook with your API provider. Once set up, the API provider will send their webhooks to this destination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we have learned how to set up a webhook connection on Hookdeck. With our current setup, we can deploy webhook integrations in production without having to worry about reliability. Hookdeck gives us full visibility and control over our webhooks. &lt;/p&gt;

&lt;p&gt;I'll be writing about various integrations using webhooks. Follow Hookdeck to stay up to date. &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>tutorial</category>
      <category>showdev</category>
      <category>hookdeck</category>
    </item>
    <item>
      <title>Setting Up Ngrok For Local Webhook Testing</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Wed, 07 Apr 2021 14:45:49 +0000</pubDate>
      <link>https://forem.com/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779</link>
      <guid>https://forem.com/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779</guid>
      <description>&lt;p&gt;Ngrok is a tunneling tool used to expose applications running locally to the public over the internet. Ngrok sits between the public and your local application by proxying external requests to the port your application is running on. Ngrok comes in quite handy when you need a publicly accessible URL.&lt;/p&gt;

&lt;p&gt;If you have been following the guides from this blog, you might have noticed that most webhook providers expect you to provide an HTTPS secured URL while registering a webhook. While this practice among webhook providers is put in place to ensure security, it becomes difficult to work with webhooks in a development environment — Where your local server is yet to have an HTTPS secured URL. Ngrok makes it possible to get a publicly available HTTPS URL that maps to your local server.&lt;/p&gt;

&lt;p&gt;In this guide, we will learn how to set up Ngrok to receive publicly accessible URLs for applications running locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Ngrok On Your Computer
&lt;/h2&gt;

&lt;p&gt;To be able to use Ngrok on your computer, you first have to install it on your machine! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To install Ngrok:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head over to the official website and download the release suitable for your local machine. &lt;/li&gt;
&lt;li&gt;Once downloaded, unzip the file and follow the prompts to install Ngrok to your machine. If you get stuck while installing Ngrok, &lt;a href="https://ngrok.com/docs" rel="noopener noreferrer"&gt;the official download page&lt;/a&gt; has some pretty clear documentation that I definitely recommend you check out.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Asides from manually downloading Ngrok from &lt;a href="https://ngrok.com/" rel="noopener noreferrer"&gt;the official site&lt;/a&gt;, you can install Ngrok on your computer using NPM if you have NPM configured. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To install Ngrok using NPM:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the following command &lt;code&gt;npm i ngrok&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;After running this command, NPM will download the Ngrok binary from the official Ngrok hosting. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To learn more about the NPM method of installing Ngrok, head over to the &lt;a href="https://www.npmjs.com/package/ngrok" rel="noopener noreferrer"&gt;official NPM page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Ngrok Up
&lt;/h2&gt;

&lt;p&gt;Once Ngrok has been installed on the computer, you can go ahead and run your tunnel. Running Ngrok is quite easy: the command to run Ngrok follows this pattern&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;— ngrok http &amp;lt;port-number&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ngrok will start in your terminal, displaying a box that contains your forwarding field. Ngrok will tunnel any external traffic to your application running on  of your machine. The forwarding field's value displayed in the terminal is the most important piece in this puzzle. The forwarding URL receives incoming traffic and maps it to your local application. You can now use the HTTPS secure URL for working with webhooks in a development environment! &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So far, we have learned about Ngrok &amp;amp; how to set it up. While everything is set up to work perfectly for development, we recommend talking to the necessary authorities before starting Ngrok over a public network. It could expose the network to vulnerabilities.&lt;/p&gt;

&lt;p&gt;Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>tutorial</category>
      <category>hookdeck</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Automating Email Follow Ups Using Mailgun Webhooks</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Tue, 06 Apr 2021 19:48:26 +0000</pubDate>
      <link>https://forem.com/hookdeck/automating-email-follow-ups-using-mailgun-webhooks-55ob</link>
      <guid>https://forem.com/hookdeck/automating-email-follow-ups-using-mailgun-webhooks-55ob</guid>
      <description>&lt;p&gt;Mailgun is an email API service for developers. Mailgun makes it possible for users to send emails and manage email subscriptions using their API. &lt;/p&gt;

&lt;p&gt;In this guide, we will build a service to help our imaginary friend Joe who manages a newsletter called WorldEats via Mailgun. Recently, Joe noticed a sudden spike in the number of people who were unsubscribing from his newsletter. Let's help Joe understand the reasons behind his newsletters unsubscription by building a service that sends a follow-up email to a user right after they unsubscribe from WorldEats. &lt;/p&gt;

&lt;p&gt;The service we're building will hook into Mailgun's webhooks offering to get notified when a user unsubscribes from the newsletter and responds by sending a follow-up email.&lt;/p&gt;

&lt;p&gt;After this post, you should have a better understanding of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuring Mailgun webhooks&lt;/li&gt;
&lt;li&gt;Sending emails programmatically using Mailgun&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating A Simple Web Server
&lt;/h2&gt;

&lt;p&gt;The first step to build the service is to create a web server. This web server will receive webhook notifications when a user unsubscribes from the WorldEat's newsletter. We want to set up the server to sends a 200 OK response to the webhook provider as soon as it receives a notification. On top of that, we also have to add additional logic to parse the webhook notification and send an inquiry email when a user unsubscribes.&lt;br&gt;
We are using NodeJS and ExpressJS to build our server. Let's initialize a new NodeJS project and add the following lines of code to create the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App is running on port 3000!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've set up our local server. For us to complete the setup for Mailgun webhooks, we need an SSL secure public URL. You can use a tool like Ngrok to publish your local server to the web(&lt;a href="https://dev.to/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779"&gt;Here&lt;/a&gt; is an excellent guide that shows how to setup Ngrok).&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Mailgun Webhooks
&lt;/h2&gt;

&lt;p&gt;Now that we have our web server ready to receive webhook notifications, let's configure Mailguns webhook to accept events as they occur. To set up Mailgun webhooks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head over to the dashboard and click the &lt;strong&gt;&lt;em&gt;webhook&lt;/em&gt;&lt;/strong&gt; navigation on the sidebar. &lt;/li&gt;
&lt;li&gt;On the webhook page, you can see previously created webhooks or create new webhooks. In our case, to build out the service, we need to create a new webhook. &lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;&lt;em&gt;add webhook&lt;/em&gt;&lt;/strong&gt; button at the top of the webhook page to create a new webhook. For the event type, select unsubscribe from the dropdown list and fill the URL field with the URL of the server created above. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this point, we finished configuring the webhooks! When someone unsubscribes from WorldEats' newsletter, we are going to receive a notification that will be logged in the console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending Emails When an Event Is Triggered
&lt;/h2&gt;

&lt;p&gt;Rather than logging the webhook payload to the console, we want to parse the incoming data, extract the user's email and send an inquiry email to the user. &lt;/p&gt;

&lt;p&gt;To get started, install the official Mailgun client library for NodeJS by running the following command npm install mailgun-js. Next, create a separate file within your project directory and add the following lines of code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form-data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Mailgun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mailgun.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mailgun&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Mailgun&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiverEmail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mailgun&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR-MAILGUN-API-KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;});&lt;/span&gt;
     &lt;span class="nx"&gt;mg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;domain.mailgun.org&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WorldEats &amp;lt;WorldEats@domain.mailgun.org&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;receiverEmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WorldEats Hates To See You Go!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hey there, We hate to see you go! Could you let us know why you unsubscribed from WorldEats&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// logs response data&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// logs any error&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;sendMessage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code snippet above, we created a new sendMessage function that takes in a receiverEmail and sends a message to that address using Mailgun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;At this point, we are almost done building out this service. The next step is to import the sendMessage function and invoke it when a webhook notification is received. To import the sendMessage function to your index.js file, add the following line of code to the top of the file &lt;em&gt;import&lt;/em&gt; sendMessage &lt;em&gt;from&lt;/em&gt; './email'. With the import in place, we need to invoke the sendMessage function within the /webhook route, passing in the receiverEmail address extracted from the webhook payload.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;receiverEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;event-data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
     &lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;receiverEmail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The webhook handler should look similar to the above code snippet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Ready For Production.
&lt;/h2&gt;

&lt;p&gt;Let's first deploy the server on Heroku(&lt;a href="https://dev.to/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779"&gt;Here’s&lt;/a&gt; a guide we wrote that shows how to setup Ngrok). Then, although our service currently works fine, it is noted  production-ready! Various unprecedented errors may occur and cause the server we created to miss webhook notifications. I'll use &lt;a href="https://hookdeck.com/" rel="noopener noreferrer"&gt;Hookdeck&lt;/a&gt; to manage the ingestion and error handling of the webhook connection to ensure I do not miss any webhook notifications.&lt;br&gt;
&lt;strong&gt;Setting up Hookdeck&lt;/strong&gt;&lt;br&gt;
Sign in to Hookdeck and fill out the information for your webhook connection. Ensure that the destination URL you set in the Hookdeck dashboard is the URL endpoint of the newly deployed server. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F545d33y366xolwrv27ie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F545d33y366xolwrv27ie.png" alt="Image Showing Webhook On The Hookdeck Dashboard" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, go ahead and replace the webhook URL on the Mailgun dashboard with the URL provided by Hookdeck.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations, we've built our service that sends an email to users when someone unsubscribes from WorldEats newsletters. With this, Joe will get more information to understand what's happening. &lt;br&gt;
Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>tutorial</category>
      <category>automation</category>
      <category>hookdeck</category>
    </item>
    <item>
      <title>Deploying A Server To Heroku</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Mon, 05 Apr 2021 18:09:49 +0000</pubDate>
      <link>https://forem.com/hookdeck/deploying-a-server-to-heroku-1e4b</link>
      <guid>https://forem.com/hookdeck/deploying-a-server-to-heroku-1e4b</guid>
      <description>&lt;h1&gt;
  
  
  Deploying A Server To Heroku
&lt;/h1&gt;

&lt;p&gt;Heroku is a Platform as a Service(PaaS) that makes it easy to deploy servers to the web. Heroku takes pride in its simplicity and ease by which users can take their local servers to production. Heroku has a very intuitive dashboard making it easy for users to deploy their servers. &lt;br&gt;
After reading this guide, you will learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy servers to Heroku&lt;/li&gt;
&lt;li&gt;Manage Environment variables when deploying to Heroku&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="" class="article-body-image-wrapper"&gt;&lt;img&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The first step in deploying a server to Heroku is creating a server. Since creating web servers is out of the scope of this guide, you can clone this demo web-server from Github to continue along with this tutorial&lt;br&gt;
&lt;code&gt;git clone&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now that you've set up a server on your local machine, we will learn how to deploy it to production.&lt;/p&gt;

&lt;p&gt;Deploying a web server to Heroku can be done in two ways, using either the CLI or the Heroku dashboard. We will be exploring both ways of deploying a server to Heroku, starting with the Heroku CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction To The Heroku CLI
&lt;/h2&gt;

&lt;p&gt;The Heroku CLI makes it easy to deploy web servers to the internet right from your terminal. To be able to use the CLI, you first need to install it on your local machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing Heroku Using The File Binaries&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the standalone binary file compatible with your machine from the &lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;official download page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Extract the downloaded file &lt;/li&gt;
&lt;li&gt;Follow the OS specific prompts that follow to install the Heroku CLI&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also install the Heroku CLI via NPM if you have Node installed on your computer. It is important to note that using NPM to install the Heroku CLI is not the most recommended method. This installation method relies on your system's version of Node.Js, which may be incompatible with Heroku.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing Heroku Using NPM&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure you have Node installed on your computer&lt;/li&gt;
&lt;li&gt;Run the following command &lt;code&gt;npm install -g heroku&lt;/code&gt; to install the Heroku CLI on your local machine&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After installing the Heroku CLI using either of the above methods, you can confirm the installation was successful by running this command &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ heroku --version
//Expected Result
heroku/7.0.0 (darwin-x64) node-v8.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If the installation was successful, you should see the installed version of Heroku printed out. If the above command failed to print any result, you should validate you have git installed on your computer and try again or head over to the &lt;a href="https://devcenter.heroku.com/articles/heroku-cli" rel="noopener noreferrer"&gt;official Heroku help page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploying A Server Using The CLI&lt;/strong&gt;&lt;br&gt;
Now that we've set up everything, we are ready to go ahead and deploy the sample server cloned above to production. We will be deploying the server in the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to the project directory of the file to be deployed&lt;/li&gt;
&lt;li&gt;Create a new file titled &lt;strong&gt;&lt;code&gt;Procfile&lt;/code&gt;&lt;/strong&gt; in the root of the project directory — This Procfile contains necessary commands that instruct Heroku on how to start the server. Since our demo server is in NodeJS, we need to add the following line of code to the newly created Procfile&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;web: node index.js&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Login to your Heroku account via the terminal by running &lt;code&gt;Heroku login&lt;/code&gt;. This command will redirect you to a web page and ask you to authenticate.&lt;/li&gt;
&lt;li&gt;Create a new Heroku application by running &lt;strong&gt;&lt;code&gt;heroku create &amp;lt;unique-app-name&amp;gt;&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Next, initialize a git repository for your project if it doesn't exist. Remember to add a &lt;code&gt;.gitignore&lt;/code&gt; file to ignore the node modules directory &amp;amp; &lt;code&gt;.env file.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If you made any changes, commit the files to git by running the following command&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;$ git add .&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ git commit -m&amp;lt;Commit Message&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push the changes to the Heroku server — In this step, Heroku builds our server and deploys it to the internet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;git push heroku master&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If everything went well, you would notice that Heroku prints a log about the deployment to your terminal and the URL of our new server. You can test it out by running &lt;code&gt;heroku open&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deploying A Server Using The Dashboard&lt;/strong&gt;&lt;br&gt;
In the previous section, we deployed a server in six steps using the Heroku CLI. In this section, we will discuss how to deploy a server right from the Heroku dashboard. Using this method requires that you have your server hosted on Github or any version control system of choice. Deploying a server can be done in the following steps&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to your Heroku account and navigate to the dashboard.&lt;/li&gt;
&lt;li&gt;Once in the dashboard, click the &lt;code&gt;new app&lt;/code&gt; button fill the menu with a unique name for your new server &amp;amp; the region you want to deploy your new server.&lt;/li&gt;
&lt;li&gt;With your newly created app page, navigate the deploy tab and click the &lt;code&gt;**connect to Github**&lt;/code&gt; deployment method. It will prompt you to select the repository name you would like to connect&lt;/li&gt;
&lt;li&gt;After connecting with the Github repository, you can decide whether you want to deploy the server automatically or manually by clicking the check box in the automatic &amp;amp; manual deploys section of the Heroku app page. &lt;/li&gt;
&lt;li&gt;After selecting the &lt;strong&gt;deploy&lt;/strong&gt; form, choose the branch Heroku should deploy and click the deploy branch button — This should print out the log information during your server's deployment. If the build succeeded, you would see your server's live URL, which you can visit.
## Configuring Environment Variables&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this section, we will discuss how to add environment variables for your apps deployed on Heroku. During development, you might need to keep specific values super secure. It is generally recommended you create a &lt;code&gt;.env&lt;/code&gt; file to keep all sensitive information that shouldn't be committed to version control. Since version control systems don't hold your .env files, Heroku will not have access to it when you deploy your application. &lt;/p&gt;

&lt;p&gt;If you are working with Heroku's CLI, you can configure Heroku to use environment values by simply running the following command for all the key value pairs in your &lt;code&gt;.env&lt;/code&gt; &lt;br&gt;
&lt;code&gt;heroku config:set &amp;lt;key=value&amp;gt;&lt;/code&gt;&lt;br&gt;
The above command will set environment values!&lt;/p&gt;

&lt;p&gt;If you choose to deploy your app using the Heroku dashboard, head over to your apps page's settings tab, click the &lt;strong&gt;&lt;code&gt;reveal config vars&lt;/code&gt;&lt;/strong&gt; button. You will see your previously configured environment variables and be able to create new config vars.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c15nhc5txsey87ofwd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c15nhc5txsey87ofwd3.png" alt="Image Showing Config Vars" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So far, we have learned how to deploy servers to Heroku. It has been helpful to get you started on getting your application in production. &lt;/p&gt;

&lt;p&gt;Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>deploy</category>
      <category>tutorial</category>
      <category>servers</category>
      <category>hookdeck</category>
    </item>
    <item>
      <title>Receive Discord Notifications For Heroku App Builds</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Thu, 01 Apr 2021 18:56:31 +0000</pubDate>
      <link>https://forem.com/hookdeck/receive-discord-notifications-for-heroku-app-builds-4kpa</link>
      <guid>https://forem.com/hookdeck/receive-discord-notifications-for-heroku-app-builds-4kpa</guid>
      <description>&lt;p&gt;Heroku makes it easy to deploy local applications to the cloud. I always use it for my small and medium-scale applications. Once I deploy my application, I like to receive notifications of my builds in a Discord channel. It's great for visibility when I work on a project in a team with other developers.&lt;br&gt;
In this guide, I will show you how I wired up an integration for Heroku builds notification to a Discord channel — giving step-by-step instructions on how you can create a similar integration. After reading this guide, you'll be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up Discord and Heroku webhooks&lt;/li&gt;
&lt;li&gt;Fix Heroku's payload format for Discord &lt;/li&gt;
&lt;li&gt;Deploy the integration in production&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Let's get started by setting up Discord.
&lt;/h2&gt;

&lt;p&gt;The first step in getting started with configuring the Discord webhook is logging in to the Discord app and create a Discord server (if we don't have one). This server is going to be associated with the webhook we create. &lt;br&gt;
To create a Discord server:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the + icon on the Discord dashboard, and add a server name.&lt;/li&gt;
&lt;li&gt;Select a channel within your newly created server where you want to receive notifications of Heroku app builds.&lt;/li&gt;
&lt;li&gt;Click the edit channel option and navigate to Integrations.&lt;/li&gt;
&lt;li&gt;Once on the integrations page, Click the Create Webhook button to create a new webhook. Fill the menu with a descriptive name for the new webhook and copy the webhook URL. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This webhook URL will be necessary for the coming steps. Keep it handy!&lt;/p&gt;
&lt;h2&gt;
  
  
  Now it's time to set up Heroku.
&lt;/h2&gt;

&lt;p&gt;In the previous section, we configured Discord webhooks and received a URL! In this section, we move a step further in building our demo service by setting up Heroku webhooks to notify us when a new build for the specified app has been initiated.&lt;/p&gt;

&lt;p&gt;You can subscribe to Heroku webhooks either by using the Heroku dashboard, command-line interface, or API. I will only show how to subscribe to webhooks using the dashboard in this guide because it is more intuitive &amp;amp; requires no extra setup.&lt;/p&gt;
&lt;h2&gt;
  
  
  To get started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Log in to your Heroku account and select an app on the dashboard you want to configure for webhooks. &lt;/li&gt;
&lt;li&gt;Click the more button to the dashboard's top right and select view webhooks from the dropdown menu. &lt;/li&gt;
&lt;li&gt;Go ahead and create a webhook! Fill the name field with the desired name for the webhook in lowercase. For the Payload URL field, temporarily fill it with the Discord webhook URL from the previous step. &lt;/li&gt;
&lt;li&gt;Next, select the api: build option from the list of event types &amp;amp; save the webhook.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Fixing Heroku payload format for Discord
&lt;/h2&gt;

&lt;p&gt;So we have configured both Discord &amp;amp; Heroku webhooks. Now, it's time to put it all together. &lt;/p&gt;

&lt;p&gt;The first thing to know is Discord webhooks expects a different payload format than that which Heroku sends as a webhook notification. We need need to build a simple web server to sit between Heroku &amp;amp; Discord webhooks. This web server will format the JSON data from Heroku webhooks and make a POST HTTP request to the Discord URL, with the formatted JSON data as the request body.&lt;/p&gt;

&lt;p&gt;For this guide, I will use NodeJS &amp;amp; ExpressJS to build out the web server. Although, the following logic can be applied in the stack of your choice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;//Respond To Heroku Webhook&lt;/span&gt;
     &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://discord.com/api/webhooks/XXXXXXXXXXXXXX&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;//Format JSON DATA&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`This is A Webhook notification!A build for your app &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was just triggered`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
     &lt;span class="p"&gt;};&lt;/span&gt;
     &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App is running on port 3000!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code snippet, we created a /webhook route where Heroku will send webhook data. We then acknowledge the receipt of the Heroku webhook by sending a 200 OK response. After which, we format the data and POST it to the Discord URL we copied up above.&lt;br&gt;
At this point, we are almost set to go! To round up, we need to publish our local server — In a development mode, you could use a local tunnel tool like Ngrok to get an SSL secured URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's send a test
&lt;/h2&gt;

&lt;p&gt;Once you have a HTTPS URL for the local server, head over to the Heroku dashboard and edit the webhook we created by replacing the old payload URL with the URL of the web server. Now that everything is in place, you can test what we have worked on so far by triggering a build for your Heroku app. If everything goes well, you should see a message similar to the one below appear in your discord channel!  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9a6499uisj6luzd9far.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9a6499uisj6luzd9far.jpeg" alt="Image Showing Successful Message Response" width="800" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sweet, everything works!
&lt;/h2&gt;

&lt;p&gt;Now the only thing left to do is deploying in production. &lt;br&gt;
Let's first deploy the server on Heroku(&lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;Here&lt;/a&gt; is a guide we wrote that shows how to deploy to Heroku). Then, I'll use Hookdeck to manage the ingestion and error handling of the webhook connection to ensure I do not miss any webhook notifications.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up Hookdeck&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sign in to Hookdeck and fill out the information for your webhook connection. Ensure that the destination URL you set in the Hookdeck dashboard is the URL endpoint of the newly deployed server. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzckqn0cbpk16fxmfi1uy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzckqn0cbpk16fxmfi1uy.png" alt="Image Showing Heroku Webhook On The Hookdeck Dashboard" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All there is left to do is update the URL on Heroku with Hookdeck's URL and trigger a test to see if everything works. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That's it! Everything is set up and deployed in production reliably. I'm excited to receive a notification in Discord whenever there's a build on my Heroku App! &lt;/p&gt;

&lt;p&gt;Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webhooks</category>
      <category>hookdeck</category>
    </item>
    <item>
      <title>Connecting Stripe &amp; Slack via webhooks</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Fri, 26 Mar 2021 18:26:17 +0000</pubDate>
      <link>https://forem.com/hookdeck/connecting-stripe-slack-via-webhooks-3g3h</link>
      <guid>https://forem.com/hookdeck/connecting-stripe-slack-via-webhooks-3g3h</guid>
      <description>&lt;p&gt;A while back, my friends and I built a simple web service that costs 5$ to use but because of our full-time jobs, we gradually stopped working on it. Until recently, we got back together and decided to spend more time on it and release new features. To keep us motivated, I decided to connect Stripe (the payment gateway service we use for processing payments) with the team’s Slack workspace so that when a user makes a payment, we receive a notification. I’m excited to share how I did it so you can also keep your team motivated! &lt;/p&gt;

&lt;p&gt;In this guide, I will show you how I wired up the integration — giving step by step instructions on how you can create a similar integration. After reading this guide, You’ll learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure Stripe Webhooks&lt;/li&gt;
&lt;li&gt;Configure Slack Webhooks&lt;/li&gt;
&lt;li&gt;Connect Stripe &amp;amp; Slack to communicate via webhooks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To connect Stripe and Slack, we need to configure Stripe webhooks to send out notifications when an event is triggered and configure Slack webhooks to post these notifications as a message to a Slack channel.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to learn more about webhooks,&lt;a href="https://dev.to/hookdeck/a-beginners-guide-to-webhooks-3eeb"&gt;here&lt;/a&gt; is a beginner friendly guide to webhooks I wrote&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Configuring Stripe Webhooks
&lt;/h2&gt;

&lt;p&gt;You can configure Stripe webhooks by using the dashboard or by making a HTTP request to the API. &lt;br&gt;
To configure Stripe webhooks using the dashboard, log in to your Stripe account and head over to the dashboard. Once in the dashboard, select the developers option on the dashboard and click the webhooks option. On the webhooks page, click the add endpoint button, you will be prompted to fill out information related to the webhook you intend to configure. For the value of the endpoint field, you could leave it empty or put any random value for now — We will update this once we have configured the Slack webhook. For the events field, you can select any events you would like to receive notifications for, when they occur.&lt;/p&gt;

&lt;p&gt;To configure Stripe webhooks using the API, simply make a POST request to the &lt;code&gt;/v1/webhook_endpoints&lt;/code&gt; endpoint of the Stripe API. The request body should include JSON data about the webhook by following a similar format as the code snippet below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com/my/webhook/endpoint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enabled_events[]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;charge.failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;charge.succeeded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the Stripe webhook setup, we can go ahead and configure the Slack webhooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Slack Webhooks
&lt;/h2&gt;

&lt;p&gt;The first step in configuring Slack webhooks is creating a Slack app for your workspace. To create a slack app, click here and fill the pop up menu with the intended App name &amp;amp; select the Slack workspace you would like the webhook to be associated with. Head over to the features page of the newly created app and toggle the activate incoming webhooks button. Scroll to the bottom of the page and click the “Add New Webhook To Workspace” button to give your newly created Slack app access to your workspace. After a successful authorization you should receive a webhook URL from Slack. The webhook URL will look similar to this “&lt;a href="https://hooks.slack.com/services/TXXXXXXXX/BXXXXXXX/3XXXXX%E2%80%9D" rel="noopener noreferrer"&gt;https://hooks.slack.com/services/TXXXXXXXX/BXXXXXXX/3XXXXX”&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Stripe &amp;amp; Slack
&lt;/h2&gt;

&lt;p&gt;Now that we have configured the webhooks of both platforms, we need to connect them such that when an event is triggered within the Stripe account, a message is sent to the Slack channel.&lt;/p&gt;

&lt;p&gt;While you might be tempted to copy the URL provided by Slack and update the created Stripe endpoint with it, that will not work. Although when using the previously mentioned method, Stripe will post notifications to the Slack URL when an event is triggered but Slack will be unable to parse that data and send a message to the specified channel.&lt;br&gt;
The correct way to approach this problem is to format the JSON data received from Stripe and make a POST request to the Slack webhook URL in a format that adheres to the pattern Slack expects. To format the Stripe webhook, we will create a web server that receives and responds to the Stripe webhook. The webserver will also parse the Stripe webhook data and POST it to the Slack webhook URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//Extract the Stripe Webhook data&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;//Respond to Stripe Webhook notification &lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;//Make HTTP POST Request To Slack Provided URL&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://hooks.slack.com/services/T01XXXXXX/B01XXXXXX/XXXXXX&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;//Format Stripe Webhook Data To Adhere To Slack Standards&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hey! An &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; of type &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; with ID &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; just occured on your Stripe Account`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="c1"&gt;//Start Web Server&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App is running on port 3000!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that everything is set up,  you can go ahead and deploy the web server — In a development mode, you could use a local tunnel tool like Ngrok or the Stripe CLI to get an SSL secured, endpoint URL(&lt;a href="https://dev.to/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779"&gt;Here’s&lt;/a&gt; a guide we wrote that shows how to setup Ngrok). &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Ready For Production
&lt;/h2&gt;

&lt;p&gt;In a Production environment you would want to deploy the web server we created up above to a hosting platform like Heroku(We wrote a &lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;guide&lt;/a&gt; on deploying servers to Heroku)&lt;br&gt;
Next, We will create a new webhook connection using Hookdeck to manage the ingestion and error handling of the webhook connection to ensure we do not miss any webhook notifications(Check out this &lt;a href="https://dev.to/hookdeck/creating-a-webhook-connection-on-hookdeck-25e0"&gt;guide&lt;/a&gt; to get started with creating webhook connections on Hookdeck).&lt;br&gt;
Finally, head back to the Stripe dashboard, select the specific endpoint and update the URL, replacing it with that provided by Hookdeck when a new connection was created. At this point, we are all set. You can test if the integration is working by clicking the &lt;strong&gt;&lt;em&gt;send test webhook&lt;/em&gt;&lt;/strong&gt; button. Once the button is clicked, you should notice a new message from the Slack app is sent to the Slack workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations you have connected Stripe &amp;amp; Slack via webhooks to receive notifications when a payment is processed. I hope this can help keep motivation high!&lt;/p&gt;

&lt;p&gt;Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>webhook</category>
      <category>hookdeck</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Receive Slack Notifications for Typeform Submissions via webhooks!</title>
      <dc:creator>Oluwatobi </dc:creator>
      <pubDate>Tue, 23 Mar 2021 19:03:53 +0000</pubDate>
      <link>https://forem.com/hookdeck/receive-slack-notifications-for-typeform-submissions-via-webhooks-3o7o</link>
      <guid>https://forem.com/hookdeck/receive-slack-notifications-for-typeform-submissions-via-webhooks-3o7o</guid>
      <description>&lt;p&gt;Typeform is tool for conversational data collection. Using Typeform, you can create personalized conversational forms. With Typeform webhooks, you can receive submissions to your forms on external applications. In this guide, we will wire up Typeform such that when submissions/responses to a form are received,  a message is sent to a specified slack channel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To build out this application, we will have to interact with both Typeform &amp;amp; Slack’s webhooks. To be able to receive a notifications/messages when an event(submission) occurs in Typeform, we will first have to configure Slack’s incoming webhooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Slack Webhooks
&lt;/h2&gt;

&lt;p&gt;To get started with the Slack webhooks, we will create a new Slack app in the workspace we intend to get notified from the Typeform submissions. To create a slack app, click here and fill the pop up menu with the intended App name &amp;amp; select a workspace. Head over to the features page of the newly created app and toggle the activate incoming webhooks button. Scroll to the bottom of the page and click the “Add New Webhook To Workspace” button to give your newly created Slack app access to your workspace. After a successful authorization you should receive a webhook URL from Slack. The webhook URL will look similar to this “&lt;a href="https://hooks.slack.com/services/TXXXXXXXX/BXXXXXXX/3XXXXX%E2%80%9D" rel="noopener noreferrer"&gt;https://hooks.slack.com/services/TXXXXXXXX/BXXXXXXX/3XXXXX”&lt;/a&gt;. This is the URL(endpoint) which we use to subscribe to Typeform webhooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Typeform Webhooks
&lt;/h2&gt;

&lt;p&gt;With Slack’s webhook in place, the next step is to set up Typeform so that notifications are sent to Slack! To set up a webhook, log into your Typeform account and select a form you would like to receive notifications on Slack when there is submission. Next, Navigate to Connect &amp;gt; Webhooks and click the “Add a webhook” button. Provide your endpoint URL( Slack’s URL from the previous step) &amp;amp; save the webhook. You should see your newly created webhook listed down below. By default, newly created webhooks are turned off. You need to toggle the button on the webhook list to set the webhook live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing Typeform’s JSON Data Pattern for Slack
&lt;/h2&gt;

&lt;p&gt;At this point, you can go ahead and test the webhook by submitting a form. You will notice that despite submitting a response, you will not receive a slack notification, that sucks! We will get to debugging — click the “view deliveries” button on the specific webhook on the Typeform dashboard. You will notice that Typeform actually sent a response to Slack but Slack was unable to parse this response and send a message to the channel. Slack expects a specific pattern of JSON data which Typeform does not adhere to. To solve this problem, we will have to write some code to format the data Typeform provides and send it as a POST request to the Slack URL we got above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;extended&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/webhook&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//Extract Information About TypeForm Submission From Request Body &lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TypeformResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form_response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;//Send 200 OK response to Typeform&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;//Make HTTP POST Request To Slack Provided URL&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Slack_Provided_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hey! There is a new submission for your Typeform &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tfResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App is running on port 3000!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With above code snippet in place, go ahead and deploy the web server — In a development mode, you could use a local tunnel tool like Ngrok to get an SSL secured URL(&lt;a href="https://dev.to/hookdeck/setting-up-ngrok-for-local-webhook-testing-3779"&gt;Here’s&lt;/a&gt; a guide we wrote that shows how to setup Ngrok).&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Ready For Production
&lt;/h2&gt;

&lt;p&gt;In a Production environment you would want to deploy the web server we created up above to a hosting platform like Heroku(We wrote a &lt;a href="https://dev.to/hookdeck/deploying-a-server-to-heroku-1e4b"&gt;guide&lt;/a&gt; on deploying servers to Heroku)&lt;br&gt;
Next, We will create a new webhook connection using Hookdeck to manage the ingestion and error handling of the webhook connection to ensure we do not miss any webhook notifications(Check out this &lt;a href="https://dev.to/hookdeck/creating-a-webhook-connection-on-hookdeck-25e0"&gt;guide&lt;/a&gt; to get started with creating webhook connections on Hookdeck).&lt;br&gt;
The last step in fixing this problem is to edit the Typeform webhook endpoint by replacing it with the URL obtained when a new webhook connection was created in Hookdeck. With the correct URL in place, you could go ahead and test it by responding a Typeform. Once submitted, you should receive a Slack notification telling you there has been a new form submission.  🎉 &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So far, we have seen how receive Slack notifications for Typeform form submission via webhooks! &lt;br&gt;
Interested to learn more? Follow Hookdeck where I'll be sharing tutorials and guide about webhooks! &lt;br&gt;
&lt;a href="https://hookdeck.com/?utm_source=devto&amp;amp;utm_medium=forum&amp;amp;utm_campaign=devto" rel="noopener noreferrer"&gt;Try Hookdeck For Free&lt;/a&gt;. Receive, monitor and manage all your webhooks from a single place. We handle the complexity so you can focus on building your product. &lt;/p&gt;

</description>
      <category>webhooks</category>
      <category>hookdeck</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
