Create a Discord trigger for n8n

(This is another advanced user setup)

Continuing the theme using Agentic AI, I encountered a situation where I wanted to use Discord as an interface. My idea was to have a Discord channel listen for a prompt string, then the Agentic AI would execute a workflow containing AI nodes, and then return to the Discord channel the results. For example, a few keywords entered returns a fully prepared Social Media post.

There is no straight forward way to set this up…but WEBHOOKS allow us to integrate Discord and n8n workflows. What is a webhook? It is a specially coded URL that when seen by a server will cause a trigger action…in this case trigger our workflow and return a result.

For this Step-by-Step guide our intent is to Monitor the Discord channel “#theBot” for a key phrase “Punch It!” that Triggers an n8n workflow. (this step-by-step is easily modified to phase variables to the n8n8 server…I added some examples below.

READ THIS ENTIRE POST BEFORE ATTEMPTING….

🔧 1. Set Up the n8n Webhook:

  • In n8n, create a new workflow.
  • Add a Webhook node and use these settings:
  • Method: POST
  • Path: (e.g. discord-punch-it)
  • Copy the full Production URL (you’ll need this for your Discord bot)
  • Any additional nodes/steps in workflow
  • Save your workflow and Activate it.

🧠 2. Create a Discord Bot That Listens for “Punch It!
OK, this is the hardest part. For you to pull this off, you must have a Node.js container or server running.

Step Requirements:

  • Node.js installed
  • Access rights to create a Discord Bot in the Discord Server
  • A way to run the bot (e.g., VPS, local machine, Heroku, etc.)
  • The following two files in a dedicated directory:

📄 sample bot.js using discord.js:

const { Client, GatewayIntentBits } = require('discord.js');
const axios = require('axios');
require('dotenv').config();

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
  ]
});

const WEBHOOK_URL = process.env.N8N_WEBHOOK_URL; 

client.once('ready', () => {
  console.log(`Logged in as ${client.user.tag}`);
});

client.on('messageCreate', async (message) => {
  if (message.channel.name === 'thebot' && message.content.includes('Punch It!')) {
    console.log('Trigger phrase detected!');
    try {
      await axios.post(WEBHOOK_URL, {
        username: message.author.username,
        content: message.content,
        timestamp: message.createdAt
      });
      console.log('Data sent to n8n webhook.');
    } catch (err) {
      console.error('Error posting to n8n:', err.message);
    }
  }
});

client.login(process.env.DISCORD_BOT_TOKEN);


  

📄 sample .env file (for secrets)

DISCORD_BOT_TOKEN=your_discord_bot_token_here
N8N_WEBHOOK_URL=https://your-n8n-domain/webhook/discord-punch-it

⌨️ 3. Set Up the Bot in Discord

  • Go to https://discord.com/developers/applications.
  • Create a new application → Go to Bot tab → Add Bot.
  • Copy the token and paste it into your .env file.
  • Set Permissions under OAuth2 → URL Generator: Scopes: bot Bot Permissions:
  • Read Messages/View Channels,
  • Send Messages,
  • Read Message History
  • Use the generated URL to invite your bot to your server and make sure it has access to #thebot.

Here’s a step-by-step guide to containerizing and running your bot with Docker:

🧰 Prerequisites:

Before you begin, you need:

  • Docker installed on your machine (Docker Desktop on Windows/macOS, or Docker CLI on Linux)
  • Your bot code (bot.js, sample above)
  • Your .env file (.env, sample above)

Your Project Directory Structure should look like this:

discord-n8n-bot/
├── bot.js
├── .env
└── Dockerfile

1️⃣ Step 1: Create the Dockerfile

Here’s a simple Dockerfile to run your Node.js Discord bot:

# Use official Node.js image
FROM node:20-alpine

# Set working directory
WORKDIR /usr/src/app

# Copy files
COPY package*.json ./
COPY . .

# Install dependencies
RUN npm install

# Start the bot
CMD ["node", "bot.js"]

note: I had to specify what version of Node.js to use for my server for this to work correctly. Refer to Docker Hub Node.js repository for information for your environment.

2️⃣ Step 2: Create package.json
Create the file “package.json” for your bot:

{
  "name": "discord-n8n-bot",
  "version": "1.0.0",
  "main": "bot.js",
  "scripts": {
    "start": "node bot.js"
  },
  "dependencies": {
    "axios": "^1.6.0",
    "discord.js": "^14.0.0",
    "dotenv": "^16.0.0"
  }
}

3️⃣ Step 3: complete your .env File (Secrets)

Make sure you have this .env file in your project root (DO NOT commit this file to GitHub)

DISCORD_BOT_TOKEN=your_discord_bot_token_here
N8N_WEBHOOK_URL=https://your-n8n-url.com/webhook/discord-punch-it

4️⃣ Step 4: Build and Run with Docker
From the root of your project directory:

docker build -t discord-n8n-bot .

And then run it:

docker run -d --env-file .env --name discord-bot discord-n8n-bot

This runs your bot in detached mode (-d) and loads environment variables from .env. To view the logs use:

docker logs -f discord-bot

Passing Variables into Your Workflow

Let’s say you send these Discord variables for the user’s name, any channel message content, and a timestamp. Add this to the bot.js file to inform the webhook to pass the variables to n8n:

await axios.post(WEBHOOK_URL, {
  username: message.author.username,
  content: message.content,
  timestamp: message.createdAt
});

In the n8n webhook node, these variables will be available as output JSON:

{
  "username": "JohnDoe",
  "content": "Punch It!",
  "timestamp": "2025-08-04T13:00:00.000Z"
}

How to Use These Variables in n8n

In a Set Node:

Add a Set node after the Webhook. Use expressions like:

{{$json["username"]}} {{$json["content"]}} {{$json["timestamp"]}}

In a Conditional (IF) Node:
You can filter by content or user:

Field. Operation. Value
{{$json["content"]}}. contains. Punch It!

In a Message (e.g., Discord reply or Email)
If you send a response, you can use:

Received command from {{$json["username"]}}: {{$json["content"]}} at {{$json["timestamp"]}}

Want to Pass Custom Parameters?

You can also design your Discord messages like:

Punch It! target=Alpha speed=3

Then in n8n, use a Function node to extract those key-value pairs:

const parts = $json["content"].split(" ");
const data = {};

for (let i = 1; i < parts.length; i++) {
  const [key, value] = parts[i].split("=");
  data[key] = value;
}

return [{ json: { ...$json, ...data } }];

Resulting node JSON Output:

{
  "username": "JohnDoe",
  "content": "Punch It! target=Alpha speed=3",
  "timestamp": "...",
  "target": "Alpha",
  "speed": "3"
}

Leave a Reply

Your email address will not be published. Required fields are marked *