How to Set up a HTTP Endpoint for Your NodeJS Discord Bot

Setting up an HTTP Endpoint is how your Discord bot gets a public internet address to receive special data directly from Discord. This is essential for features like Slash Commands and message Buttons, giving Discord a secure place to send instructions when users interact with your bot.


Packages:

  • discord.js: A Node.js library for building bots and applications that interact with Discord.
  • tweetnacl: Ed25519 signature verification for Discord requests.

Getting a Discord Public Key:

  1. Log In to the Discord Developer Portal
  2. Select your application
  3. Scroll to “PUBLIC KEY” then select the ‘Copy’ button

Discord Developer Portal, PUBLIC KEY is highlighted

1. Login In to Your Panel


2. Select the ‘Files’ Tab

Cybrancee Panel in the files page, "Files" tab on the sidebar is highlighted

3. Create index.js

This file starts a web server, verifies Discord signatures, responds to type 1 PING events, and responds to other interactions.

Pterodactyl Panel, Create File dialog. Enter File Name (index.js)

Paste the following code into the file:

const http = require('http');
const nacl = require('tweetnacl');

const PUBLIC_KEY = 'YOUR_DISCORD_PUBLIC_KEY_HERE';

function verify(signature, timestamp, body) {
  if (!signature || !timestamp) return false;
  try {
    const sig = Buffer.from(signature, 'hex');
    const pubKey = Buffer.from(PUBLIC_KEY, 'hex');
    const msg = Buffer.concat([Buffer.from(timestamp, 'utf8'), body]);
    return nacl.sign.detached.verify(
      new Uint8Array(msg),
      new Uint8Array(sig),
      new Uint8Array(pubKey)
    );
  } catch {
    return false;
  }
}

const server = http.createServer((req, res) => {
  if (req.method === 'GET' && req.url === '/') {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    return res.end('Discord bot endpoint is running');
  }

  if (req.method === 'GET' && req.url === '/interactions') {
    res.writeHead(405, { 'Content-Type': 'text/plain' });
    return res.end('Invalid request: GET not allowed on /interactions');
  }

  if (req.method !== 'POST' || req.url !== '/interactions') {
    res.writeHead(404);
    return res.end('not found');
  }

  const sig = req.headers['x-signature-ed25519'];
  const ts = req.headers['x-signature-timestamp'];
  const chunks = [];

  req.on('data', chunk => chunks.push(chunk));
  req.on('end', () => {
    const body = Buffer.concat(chunks);

    if (!verify(sig, ts, body)) {
      res.writeHead(401);
      return res.end('invalid request signature');
    }

    let data;
    try {
      data = JSON.parse(body.toString('utf8'));
    } catch {
      res.writeHead(400);
      return res.end('invalid json');
    }

    if (data.type === 1) {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      return res.end(JSON.stringify({ type: 1 }));
    }

    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ type: 4, data: { content: 'Command received' } }));
  });

  req.on('error', () => {
    res.writeHead(500);
    res.end('server error');
  });
});

const PORT = 8000;
server.listen(PORT, '0.0.0.0', () => {
  console.log(`Listening on port ${PORT}`);
});

Ensure that the port number is the same as your server’s port.


4. Get your Public URL and Register in Discord

Once you’ve hosted your web server, ensure your web server is running on https not http.

  1. Copy https://example.com/interaction
  2. Go back to the Discord Developer Portal, then your application.
  3. Paste your copied URL into the “INTERACTIONS ENDPOINT URL” then save changes

Discord Developer Portal, in the GENERAL tab of an application. PUBLIC KEY and SAVE CHANGES are highlighted

Discord Bot Hosting

Starts at $1.49

External link icon

Was this article helpful?
Please Share Your Feedback
How Can We Improve This Article?
Table of Contents