← Blog

Claude API Discord Bot Setup Guide

2026-10-13 · 5 min read · SubToAPI Team

If you want to put Claude inside a Discord server — answering questions, summarizing threads, or running a help channel — you need three things: a Discord bot application, a way to call the Claude API, and a small Node.js service that connects the two. This guide walks through all three, from registering the bot to deploying a working message handler.

The setup takes about 30 minutes if you already have API access. If you don't, you can either apply for direct Anthropic API access or use a service like SubToAPI that turns your existing Claude access into a standard HTTPS API key — useful if you don't want to manage separate billing or wait on enterprise approval for a side project bot.

Step 1: Create the Discord Application and Bot

  1. Go to the Discord Developer Portal and click New Application.
  2. Under Bot, click Add Bot, then copy the bot token — you'll need it as an environment variable.
  3. Under Bot settings, enable Message Content Intent. Without this, your bot can't read message text.
  4. Under OAuth2 > URL Generator, select the bot scope and permissions for Send Messages, Read Message History, and Use Slash Commands. Use the generated URL to invite the bot to your test server.

Step 2: Get a Claude API Key

You need an API key to send requests to Claude. There are two common paths:

Either way, store the key as an environment variable, never hardcode it:

export DISCORD_TOKEN="your-discord-bot-token"
export CLAUDE_API_KEY="sub_live_xxxxxxxxxxxx"

Step 3: Scaffold the Bot Project

mkdir claude-discord-bot && cd claude-discord-bot
npm init -y
npm install discord.js dotenv

Create index.js:

import { Client, GatewayIntentBits } from "discord.js";
import "dotenv/config";

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

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

client.login(process.env.DISCORD_TOKEN);

Run it with node index.js. If the bot shows as online in your server, you're ready to wire in Claude.

Step 4: Call Claude on Incoming Messages

Add a message listener that forwards user text to Claude and replies with the response. This example uses SubToAPI's /v1/messages endpoint, which follows the same request shape as Anthropic's API:

client.on("messageCreate", async (message) => {
  if (message.author.bot) return;
  if (!message.mentions.has(client.user)) return;

  const prompt = message.content.replace(/<@!?\d+>/, "").trim();
  if (!prompt) return;

  await message.channel.sendTyping();

  const response = await fetch("https://api.subtoapi.app/v1/messages", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.CLAUDE_API_KEY}`,
    },
    body: JSON.stringify({
      model: "claude-sonnet-4-5",
      max_tokens: 800,
      system: "You are a concise, helpful assistant inside a Discord server.",
      messages: [{ role: "user", content: prompt }],
    }),
  });

  const data = await response.json();
  const reply = data.content?.[0]?.text ?? "Something went wrong.";

  // Discord caps messages at 2000 characters
  await message.reply(reply.slice(0, 1990));
});

Mention the bot in a channel (@YourBot what's the deadline for the launch?) and it should reply with Claude's answer. Full request/response details are in /docs/messages; if you're new to the API shape in general, /docs/quickstart covers the basics end to end.

Step 5: Add Streaming for Longer Replies

Discord's rate limits make long single replies slow to send. For a better experience, stream Claude's output and edit the message incrementally:

const stream = await fetch("https://api.subtoapi.app/v1/messages", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${process.env.CLAUDE_API_KEY}`,
  },
  body: JSON.stringify({
    model: "claude-sonnet-4-5",
    max_tokens: 800,
    stream: true,
    messages: [{ role: "user", content: prompt }],
  }),
});

Parse the server-sent events and batch edits every few hundred milliseconds rather than on every token — Discord's message edit rate limit will throttle you otherwise. See /docs/streaming for the event format.

Step 6: Handle Conversation Memory

Discord doesn't give you conversation state for free. For a bot that remembers context within a channel:

const history = new Map(); // channelId -> messages array

function pushHistory(channelId, role, content) {
  const arr = history.get(channelId) ?? [];
  arr.push({ role, content });
  if (arr.length > 20) arr.shift();
  history.set(channelId, arr);
}

Step 7: Deploy It

A Discord bot just needs a long-running process — any small VM, a Fly.io app, or a Railway deployment works. Make sure your DISCORD_TOKEN and CLAUDE_API_KEY are set as environment secrets, not committed to the repo, and that the process restarts automatically on crash (pm2 or a systemd unit is enough for small bots).

If multiple teammates maintain the bot, give each person their own SubToAPI key under a shared workspace rather than passing one key around — see /pricing for Team and Scale plans with seat-based access.

Common Pitfalls

Questions

Do I need an Anthropic Business account to build a Discord bot? No. A standard API key works fine for personal or small-team bots. If you want usage visibility and team seats without separate enterprise billing, a wrapped key from a service like SubToAPI is a lighter-weight option.

Can the bot handle multiple servers at once? Yes — discord.js handles multi-guild connections natively. Just key your conversation history and rate-limit logic by channel or guild ID so contexts don't bleed into each other.

How do I keep API costs predictable? Cap max_tokens per reply, trim conversation history aggressively, and only respond when the bot is mentioned rather than on every message in a channel. Monitoring usage per key through your API provider's dashboard also helps catch runaway channels early.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →