Bot Gateway
The NexusGuild Bot Gateway delivers real-time events to your bot over a persistent Socket.io connection. Your bot connects once and receives events for every guild it's installed in, no polling required.
Overview
| Property | Value |
|---|---|
| Transport | Socket.io (WebSocket + HTTP long-poll fallback) |
| Namespace | /bot-gateway |
| Auth method | Bot token via Socket.io handshake auth |
| Connections per bot | 1 (connecting again disconnects the previous session) |
| Gateway version | v: 1 (returned in READY) |
Connecting
Use the Socket.io client library to connect to the /bot-gateway namespace:
import { io } from 'socket.io-client';
const gateway = io('https://nexusguild.gg/bot-gateway', {
auth: {
token: 'YOUR_BOT_TOKEN',
},
transports: ['websocket'], // prefer WebSocket
reconnection: true,
reconnectionDelay: 5000,
});
gateway.on('connect', () => {
console.log('Connected to NexusGuild gateway');
});
gateway.on('connect_error', (err) => {
console.error('Gateway connection failed:', err.message);
});
Authentication
Pass your bot token in the Socket.io auth object at connection time.
If the token is missing or invalid, the connection is rejected with an error message.
Heartbeat
Send a HEARTBEAT event periodically to verify connectivity.
The server responds with HEARTBEAT_ACK.
// Send heartbeat every 30 seconds
setInterval(() => {
gateway.emit('HEARTBEAT');
}, 30000);
gateway.on('HEARTBEAT_ACK', () => {
// Connection is alive
});
HEARTBEAT event
is an optional application-level health check, not a requirement for staying connected.Gateway Events
After connecting and authenticating, the gateway delivers these events to your bot.
READY
Sent immediately after a successful connection. Contains bot identity and gateway version.
{
"bot": {
"id": "snowflake",
"name": "MyBot"
},
"v": 1
}
Following READY, one GUILD_CREATE is emitted per guild the bot is installed in.
GUILD_CREATE
Sent once per guild on connection, providing a complete snapshot of each guild's state.
{
"id": "snowflake",
"name": "My Server",
"icon": null,
"owner_id": "snowflake",
"approximate_member_count": 42,
"channels": [
{
"id": "snowflake",
"type": 0,
"name": "general",
"topic": null,
"position": 0,
"parent_id": null
}
],
"roles": [
{
"id": "snowflake",
"name": "@everyone",
"color": 0,
"permissions": "103926848",
"position": 0,
"mentionable": false
}
],
"members": [
{
"user": { "id": "snowflake", "username": "Alice", "bot": false },
"nick": null,
"roles": [],
"joined_at": "2026-01-01T00:00:00.000Z"
}
]
}
MESSAGE_CREATE
Fired when any message is sent in a guild the bot is in. Payload mirrors the REST message object.
{
"id": "snowflake",
"channel_id": "snowflake",
"user_id": "snowflake",
"username": "Alice",
"avatar": null,
"content": "Hello!",
"created_at": "2026-03-07T12:00:00.000Z",
"attachments": null,
"reply_to_content": null,
"thread_channel_id": null
}
MESSAGE_UPDATE
Fired when a message is edited. Payload is the updated message object (same shape as MESSAGE_CREATE).
MESSAGE_DELETE
Fired when a message is deleted (including bulk deletes — one event per deleted message).
{
"id": "snowflake", // message ID
"channel_id": "snowflake",
"guild_id": "snowflake"
}
MEMBER_JOIN
Fired when a user joins a guild.
{
"user": {
"id": "snowflake",
"username": "Bob",
"avatar": null
},
"guild_id": "snowflake",
"joined_at": "2026-03-07T12:00:00.000Z"
}
MEMBER_LEAVE
Fired when a user leaves or is removed from a guild.
{
"user": { "id": "snowflake", "username": "Bob" },
"guild_id": "snowflake"
}
CHANNEL_CREATE
Fired when a channel is created in a guild. Payload is a channel object.
{
"id": "snowflake",
"type": 0,
"guild_id": "snowflake",
"name": "announcements",
"topic": null,
"position": 1,
"parent_id": null
}
CHANNEL_UPDATE
Fired when a channel is updated. Same payload shape as CHANNEL_CREATE.
CHANNEL_DELETE
Fired when a channel is deleted.
{
"id": "snowflake",
"guild_id": "snowflake"
}
ROLE_UPDATE
Fired when a role is created, edited, or deleted. Check for a deleted: true
field to distinguish deletion from creation/update.
// Created or updated:
{
"id": "snowflake",
"name": "Mod",
"color": 3447003,
"permissions": "8",
"position": 1,
"mentionable": false,
"hoist": false
}
// Deleted:
{
"deleted": true,
"id": "snowflake",
"guild_id": "snowflake"
}
INTERACTION_CREATE
Fired when a user invokes one of your bot's slash commands. Respond using the
interaction callback endpoint with the
interactionId and token from this event.
You have 3 seconds to respond (or send a deferred response first).
{
"id": "snowflake", // interactionId
"token": "interaction_token", // use in callback URL
"type": 2, // APPLICATION_COMMAND
"guild_id": "snowflake",
"channel_id": "snowflake",
"member": {
"user": { "id": "snowflake", "username": "Alice" },
"roles": []
},
"data": {
"name": "ping", // command name
"options": [] // command arguments
}
}
GUILD_MEMBER_UPDATE
Fired when a member's roles change (via the role management REST endpoints).
{
"guild_id": "snowflake",
"user": { "id": "snowflake", "username": "Alice" },
"nick": null,
"roles": ["roleSnowflake"],
"joined_at": "2026-01-01T00:00:00.000Z"
}
Example: Basic Bot
A minimal bot that connects, logs guild names, and echoes messages:
import { io } from 'socket.io-client';
const BOT_TOKEN = 'your_token_here';
const BASE_URL = 'https://nexusguild.gg';
const guilds = new Map();
const gateway = io(`${BASE_URL}/bot-gateway`, {
auth: { token: BOT_TOKEN },
transports: ['websocket'],
});
gateway.on('READY', ({ bot }) => {
console.log(`Logged in as ${bot.name} (${bot.id})`);
});
gateway.on('GUILD_CREATE', (guild) => {
guilds.set(guild.id, guild);
console.log(`In guild: ${guild.name} (${guild.members.length} members)`);
});
gateway.on('MESSAGE_CREATE', async (msg) => {
if (msg.content === '!ping') {
await fetch(`${BASE_URL}/api/v1/channels/${msg.channel_id}/messages`, {
method: 'POST',
headers: {
'Authorization': `Bot ${BOT_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: 'Pong!' }),
});
}
});
Example: Slash Command Bot
Registering a command and responding to it:
// 1. Register the command (one-time setup, session auth required)
await fetch(`/api/bots/${botId}/servers/${guildId}/commands`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
// session cookie sent automatically
body: JSON.stringify({
name: 'roll',
description: 'Roll a dice',
options: [
{
name: 'sides',
description: 'Number of sides',
type: 4, // INTEGER
required: false,
}
]
}),
});
// 2. Handle the INTERACTION_CREATE event
gateway.on('INTERACTION_CREATE', async (interaction) => {
if (interaction.data.name !== 'roll') return;
const sides = interaction.data.options?.[0]?.value ?? 6;
const result = Math.floor(Math.random() * sides) + 1;
await fetch(
`/api/interactions/${interaction.id}/${interaction.token}/callback`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 4,
data: { content: `🎲 You rolled a **${result}** (d${sides})` },
}),
}
);
});