Unofficial Not official Wardogs docs, not affiliated with the devs, and may change. Dev hub →
WARDOGS.TECH Unofficial · Community reference

Wardogs Server Reference

A community reference for running a Wardogs dedicated server: the RCON HTTP API and the ServerSettings.ini config, in one place. Unofficial.

RCON API/v1 · 35 endpoints
AuthBearer token
TransportHTTP · TLS for remote
ConfigServerSettings.ini

01 Overview

Two references in one: the RCON HTTP API (everything under /v1, one bearer token) and the ServerSettings.ini config the server reads at startup.

Servers vary in what they enable. GET /v1/capabilities lists what a given one supports, so check there rather than assume.

Building with an AI assistant? Grab the copy-paste version for Claude or ChatGPT.

02 Base URL & transport

Requests go to the server's RCON host and port. The scheme depends on how the listener is bound:

// loopback listener (BindAddress=127.0.0.1) — plaintext allowed
http://<host>:<port>/v1/

// network listener (BindAddress=0.0.0.0) — TLS required
https://<host>:<port>/v1/

Any server you reach remotely is bound to the network, and a network-exposed RCON listener requires TLS (and a hashed password) to start. Plain HTTP is only for a loopback listener on the box itself. The default RCON port is 7776 (settable in config or with -RCONPort=).

Bodies and responses are JSON (Content-Type: application/json). The two config-document endpoints are the exception: they send and receive text/plain.

A browser page can call a TLS server directly. It can't call a plaintext loopback listener from an HTTPS page (mixed content is blocked), so for local/plaintext setups call from a server.

03 Authentication

Send the RCON password as a bearer token on every request:

Authorization: Bearer <rcon-password>

There's no separate login step. To check a connection, call GET /v1/status; if it succeeds, the token is good.

One token, full access

The same token authorizes every endpoint, read and write. That includes kick, ban, config replacement, and ending a match. There's no read-only key, so treat it as a full-access secret and keep it server-side.

04 Conventions

Errors

Failures return a non-2xx status with a JSON body:

{ "error": { "code": string, "message": string } }

The config write endpoints return 412 when your revision is out of date (see Response shapes).

Feature detection

GET /v1/capabilities tells you which routes a server supports:

{ "routes": string[],   // e.g. "PATCH /v1/players/{id}"
  "config": { "writable": boolean } }

The admin panel uses exactly this: it shows "change team" only when PATCH /v1/players/{id} is in routes, and the config editor only when config.writable is true.

05 Endpoints

The full /v1 surface. Path parameters are in violet, and request bodies are noted where an endpoint takes one. Filter by access or search by path, method, or description.

↗ Open the interactive API console

A Scalar console backed by the OpenAPI spec (openapi.json) — browse, and generate a client in any language.

MethodPathGroupAccessDescription & body

06 Response shapes

The fields you can count on in each response. Servers may include more, but these are the ones the panel reads and relies on.

GET /v1/status

{
  serverName:    string,
  map:           string,              // map id, e.g. "Kavkazi"
  experiences:   string[],
  lighting:      string,
  alternator:    string,
  scoreTick:     { current, min, max },
  scoreCap:      number,
  matchSeconds:  number,
  players:       { current, max },
  factionScores: [ { name, colorHex, … } ],  // one row per faction
  rotation:      { nowIndex, nextIndex }     // integer, or null
}

GET /v1/players

{ players: [ { name, steamId, faction, kills, deaths, cash, pingMs } ] }

faction is a server-defined name; match it to a faction row by colorHex from factionScores. Steam names and avatars aren't here, see Player names.

GET /v1/rotation

{
  enabled: boolean,
  mode:    string,   // "ordered" | "random"
  entries: [ {
    map, experiences[], lighting,
    zoneAlternator,
    status,          // "now" | "next" | …
    denied: boolean
  } ]
}

GET /v1/bans

{ bans: [ {
  steamId,
  bannedAtUtc,
  bannedBy,
  reason
} ] }

GET /v1/reserved-slots

{ reservedSlots: string[] }
// array of steamId strings

GET /v1/audit?limit=N

{ entries: [ {
  timestampUtc, peer,
  sessionId, event,
  detail
} ] }
// limit 1–500, default 50

GET /v1/config

{
  revision: string,
  writable: boolean,
  text:     string,   // the config document
  sections: [ … ],
  warnings: [ … ]
}

PUT /v1/config & POST /v1/config/validate — result

{
  ok: boolean,  revision: string,
  error: { code, message },
  outcomes: [], shadowed: [], stripped: [], errors: [], changed: [],
  conflict: [],   // present on HTTP 412 (revision mismatch)
  warnings: [], timingsMs: object|null
}

Send the document as the raw request body with Content-Type: text/plain. Pass the current revision as an If-Match: "<revision>" header for safe concurrent edits; a stale revision returns 412. Optional query params: force=true, fullApply=true.

07 Player names

The API gives you steamId, not display names or avatars. Resolve those yourself against the Steam Web API.

Call ISteamUser/GetPlayerSummaries with your own Steam Web API key, passing the steamId values from /v1/players. Batch them and cache the results, since names change rarely.

The admin panel does the same thing through a small proxy on its own host (GET /api/steam/profiles?ids=…, key in an X-Steam-Api-Key header, up to 32 ids per call, returning { "<steamId>": { name, avatar } }). That proxy isn't part of the game server API, so most tools just call Steam directly.

08 ServerSettings.ini

The dedicated server reads a single config file at startup. Only whitelisted sections and keys are honored — anything else is stripped. Omitted keys keep their default. RCON commands for bans, reserved slots, and rotation edit this file and persist back to it.

↓ Download a starter ServerSettings.ini

A commented template with every key at its default. Edit it and drop it in your server's config location.

The RCON listener

This section decides whether, where, and how you can connect at all:

[/Script/WDRCON.WDRCONSettings]
bEnabled=true              // listener is OFF by default
BindAddress=127.0.0.1      // loopback = plaintext ok; 0.0.0.0 = all interfaces, needs TLS
Port=7776                 // default; or launch with -RCONPort=
Password=                 // plaintext; if empty, auto-generated to Saved/RCON/ADMIN-PASSWORD.txt
PasswordHash=""           // from `WardogsServer -GenerateRCONHash=`; wins over Password

A network-facing listener (0.0.0.0) will not start without a TLS cert and key, and uses PasswordHash. Loopback may use a plaintext Password. That is the whole auth model: the password (or the password behind the hash) is the bearer token.

Every honored key

KeyDefaultAppliesWhat it does
Session [/Script/WDGame.WDGameSession]
ServerNameimmediatelyName in the server browser.
ServerPassword(empty)next restartJoin password. Empty = open server.
ServerMinPlayerCash0next restartMinimum cash to join. 0 = no limit.
ServerMaxPlayerCash0next restartMaximum cash to join. 0 = no limit.
ServerMinPlayerLevel0next restartMinimum level to join. 0 = no limit.
ServerMaxPlayerLevel0next restartMaximum level to join. 0 = no limit.
ServerImageURLpendingSponsor banner. 1024×256 PNG/JPEG on the allow-list.
MaxReservedSlots20immediatelyHow many reserved slots exist.
+DefaultReservedPlayerIdsOne line per SteamID64. The RCON reserve command edits these.
+DefaultBannedPlayerIdsOne line per SteamID64. The RCON ban / unban commands edit these.
Player slots [/Script/Engine.GameSession]
MaxPlayers128immediatelyTotal player slots. Clamped by a developer-set min/max.
Pre-match [MatchState.PreMatch.WaitingForPlayers.PlayerCount]
MinimumRequiredPlayers60next matchPlayers required before pre-match becomes a live match.
KOTH scoring [MatchState.Playing.KOTH]
ScorePeriod24next matchSeconds between score ticks (18–30). A faster tick pays less each time.
Team balancing [/Script/WDGame.WDGameStateSession]
bLockOverpopulatedTeamsConfigtruenext matchStop players joining a team that already leads by the threshold.
OverpopulatedTeamThresholdConfig2next matchHow many players ahead a team must be before it locks.
Map rotation [/Script/WDGame.WDServerMapRotationSettings]
bEnabledtrueimmediatelyAdvance through the rotation after each match.
RotationModeOrderedimmediatelyOrdered walks top to bottom; Random picks each next entry.
+RotationEntriesimmediatelyOne map entry per line (format below).

Rotation entry format

+RotationEntries=(Map="Kavkazi",Experience="Bakurani_KOTH_01",Lighting="DayClear",ZoneAlternator="ZoneAlternator.Factory.Circle")
+RotationEntries=(Map="Europe",Experiences="Madrid_KOTH_01+KOTH_InfantryOnly",Lighting="DayLateGray")

Experience (singular) is one; Experiences (plural) joins several with +. ZoneAlternator is optional — omit it for the map's authored default.

09 Prompt for AI tools

Building with Claude or ChatGPT? Copy the block below and paste it in as context. It's the whole API in plain text, so your assistant can write correct requests against it without guessing.

Paste into Claude / ChatGPT

10 Notes

  • Check capabilities per server. Not every server enables every route. GET /v1/capabilities is the real list for the server you're talking to.
  • Poll gently. There's no published rate limit. A few seconds between calls is plenty for live status; the panel itself refreshes on a 3–5 second cadence.
  • Match factions by color. A player's faction is a name; the stable key across a server is the colorHex on each factionScores row.
  • Keep the token off the client. Since the token is the full-access RCON password, requests belong on a server you control, never in a browser.