REST API
With REST API v1 you can access server, violation, player and punishment data from your own tools (Discord bot, website, reporting). API keys are available on the Pro and Network plans.
Authentication
Create a key under Integrations → API keys and send it with every request:
curl https://wardenguard.pro/api/v1/servers \
-H "Authorization: Bearer wg_live_..."
The key is shown only once when it is created and stored hashed on the server. Each key is limited to 120 requests per minute; beyond that the API returns 429.
Scopes
| Scope | Endpoints |
|---|---|
read:servers | GET /api/v1/servers |
read:violations | GET /api/v1/servers/:id/violations |
read:players | GET /api/v1/servers/:id/players |
read:punishments | GET /api/v1/servers/:id/punishments |
write:actions | POST /api/v1/servers/:id/players/:uuid/actions |
Endpoints
Servers
GET /api/v1/servers
Violations
GET /api/v1/servers/:id/violations?limit=50&before=1730000000000&player=<uuid>
Results start with the newest violation; pass next as before in the following request.
Players and punishments
GET /api/v1/servers/:id/players?status=online&page=1&pageSize=50
GET /api/v1/servers/:id/punishments?page=1&pageSize=50
Player action
curl -X POST https://wardenguard.pro/api/v1/servers/SERVER_ID/players/UUID/actions \
-H "Authorization: Bearer wg_live_..." \
-H "Content-Type: application/json" \
-d '{"action":"tempban","reason":"Cheating","durationMs":604800000}'
action: kick, ban, tempban, unban, mute, unmute, freeze, unfreeze, exempt, unexempt, reset_vl, message, watch, unwatch. If the server is offline the action waits in the queue for 5 minutes (delivery: "queued").
Errors
All errors share the same shape:
{ "error": { "code": "MISSING_SCOPE", "message": "API key is missing scope: read:players" } }
Webhook signatures
Generic webhooks are signed with the X-WardenGuard-Signature header. Verification (Node.js):
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(secret, timestamp, rawBody, signature) {
const expected = "sha256=" + createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
const ok = expected.length === signature.length && timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
const fresh = Math.abs(Date.now() - Number(timestamp)) < 5 * 60 * 1000;
return ok && fresh;
}
The timestamp value is in the X-WardenGuard-Timestamp header.
Agent protocol
The WebSocket protocol between the plugin and the panel (HMAC-signed envelopes, acks and retries) is documented in detail in docs/PROTOCOL.md in the repository.