Skip to main content
This page describes the integration pattern for letting Discord users manage the PopLock server through slash commands — without ever exposing the API key or requiring direct server access.
This page covers the integration pattern and how it maps to the PopLock API. It does not walk through setting up a Discord bot or configuring n8n from scratch — see the n8n and Discord developer documentation for those steps.

How it works

The architecture places n8n between Discord and the PopLock API. The API key never leaves n8n.
Discord user
    │  slash command

Discord bot → n8n webhook

                 ├─ check Discord role / permissions

                 ├─ (if authorized) HTTP request to PopLock API
                 │         with X-API-Key stored in n8n credentials

                 └─ send response back to Discord
  1. n8n stores the secret API key — nobody else has it.
  2. Discord users trigger slash commands, which hit n8n webhooks.
  3. n8n validates the user’s Discord role and permissions before forwarding anything.
  4. n8n proxies the authorized request to the PopLock API, attaching the key.
  5. End-users can manage the server via Discord, but nobody interacts with the server directly.

Why this pattern

  • The API key never appears in Discord messages or channel history.
  • n8n owns all authorization logic — role checks, user allowlists, and rate limits all live in the workflow, not in the API.
  • No one needs SSH access to the server to perform common management tasks.
  • Read endpoints (status, players, backups) are public, so status-check workflows need no credentials at all.
Store your API key as an n8n credential (a Header Auth credential with X-API-Key as the name) rather than hardcoding it in HTTP Request nodes. This way the key is managed in one place, masked in the n8n UI, and never visible in exported workflow JSON.

Example flow: /serverstatus

A read-only flow that requires no API key.
1

Discord slash command fires

The user runs /serverstatus in Discord. Discord calls your n8n Webhook node.
2

n8n calls GET /api/status

An HTTP Request node makes a GET request to http://your-server:6767/api/status. No authentication header is needed.
3

n8n formats the response

A Function or Set node reads the online, uptime, memory, and version fields and assembles a Discord embed or plain message string.
4

n8n replies to Discord

n8n sends the formatted message back to Discord via the webhook response or a Discord bot node.

Example flow: /serverstart

A write flow that requires role validation and an API key.
1

Discord slash command fires

The user runs /serverstart in Discord. Discord calls your n8n Webhook node, which receives the interaction payload including the user ID and guild roles.
2

n8n checks the user's role

An IF node checks whether the triggering user holds the required role (e.g. Admin). If not, n8n sends an error message back to Discord and the workflow stops.
3

n8n calls POST /api/server/start

An HTTP Request node makes a POST request to http://your-server:6767/api/server/start with the X-API-Key header pulled from n8n credentials.
4

n8n replies to Discord

On success, n8n sends a confirmation message. On failure (non-2xx from the API), n8n sends an error message.

HTTP Request node configuration

Below is an example n8n HTTP Request node configuration for sending a console command. The API key is referenced from an n8n credential rather than hardcoded.
{
  "method": "POST",
  "url": "http://your-server:6767/api/command",
  "headers": {
    "X-API-Key": "={{ $credentials.poplockApi.apiKey }}",
    "Content-Type": "application/json"
  },
  "body": {
    "command": "say {{ $json.command }}"
  }
}
For read endpoints, omit the X-API-Key header entirely:
{
  "method": "GET",
  "url": "http://your-server:6767/api/status"
}

Mapping Discord commands to API endpoints

Discord commandAPI endpointAuth required
/serverstatusGET /api/statusNo
/playersGET /api/players/onlineNo
/backupsGET /api/backupsNo
/serverstartPOST /api/server/startYes
/serverstopPOST /api/server/stopYes
/serverrestartPOST /api/server/restartYes
/command <cmd>POST /api/commandYes
/whitelist add <name>POST /api/whitelist/addYes
/whitelist remove <name>POST /api/whitelist/removeYes
/backupPOST /api/backupYes