Skip to content

Alderon Server REST API

HTTP/JSON administration API for a Path of Titans dedicated server — a resource-oriented alternative to Source RCON. Enable it with -EnableServerApi and set [AlderonServerAPI] Port + ApiKey in Game.ini.

Base URL: http://<host>:<port>/v1/api77 endpoints, OpenAPI 3.2.0 served at GET /openapi.json.

Conventions

Auth

Every request needs Authorization: Bearer <ApiKey>. The API is fail-closed: a missing/wrong key returns 401. Each endpoint requires one permission (listed per-endpoint below, via GET /permissions, and as x-permission in OpenAPI). The default ApiKey has full access; ReadOnlyApiKeys hold only read. Define finer keys in [AlderonServerAPI] by assigning a role or an explicit permission list:

+ApiRole=(Name="Moderator", Permissions="read,players,bans,whitelist,chat,reports")
+ApiKeyDef=(Key="d41d8cd98f00b204e9800998ecf8427ee2c1f0a9b7d3c6584f21ba90de7c3315", Role="Moderator")
+ApiKeyDef=(Key="9b1c7e42a5f80d36c4e19af27b0d58e63a7c21fd48b6e095c3d7a1f2b8604e75", Permissions="read,rcon")
Keys must be at least MinApiKeyLength characters (default 64) or the server refuses them at startup and logs which were too short — the key is the only thing protecting full server administration and it is reachable over the network. Generate them: openssl rand -hex 32. Permission tokens: read, players, bans, whitelist, admins, chat, world, settings, config, maintenance, reports, rcon, database (* = full). A key missing an endpoint's permission gets 403. Note reads are not all read: /config, /webhooks, /database and /backups need their own token even for a GET.

Transport

Plain HTTP. Intended for localhost / a private network, or behind a TLS-terminating reverse proxy. Do not expose it directly to the internet.

Response envelope

Responses are JSON objects with a success boolean. Reads put their payload under a named key (e.g. players); actions return a human string under response. Errors use the matching HTTP status and a body of {success:false, error, code}, where code is a stable machine-readable slug (bad_request, unauthorized, forbidden, not_found, rate_limited, server_error).

Rate limits & safety

Requests are rate-limited (a 429 includes a Retry-After header), the client IP can be allowlisted, and admin actions require an admin-scoped key.

Content-Length

Requests with a body must send Content-Type: application/json and an explicit Content-Length — the server rejects chunked transfer encoding (411). Bodyless POST/PUT/DELETE should send Content-Length: 0.

Encoding

Query values are x-www-form-urlencoded — both %20 and + decode to a space, so reason=a+b and reason=a%20b are equivalent.

Player IDs (agid)

Path params named {agid} accept either the dashed Alderon display id (525-053-709) or the raw 9-digit id (525053709) — targeted actions and GET /players/{agid} both normalize the input.

Discovery

GET /

readonly — Endpoint index

Responseendpoints[] (method, path, scope, summary) + openapi link.

GET /openapi.json

readonly — OpenAPI 3.2 description of this API

Response — A tool-consumable OpenAPI 3.2.0 document — path params, request bodies, typed error responses (shared Error schema), tags, operationIds, and bearer security. Point Swagger UI / Postman / a code generator at it.

3.2 specifically, not 3.0/3.1: it is the first version with query as a first-class operation key, so it is the only one that can describe QUERY /events at all. Earlier versions have a closed set of operation keys and would silently omit that endpoint. Tooling that only understands 3.0/3.1 may reject the document or skip the query operation.

GET /healthz

readonly — Lightweight liveness probe (for monitoring)

Responsestatus: "ok" + uptimeSeconds. Cheap — no game-thread work.

GET /readyz

readonly — Readiness probe: is the server joinable yet?

Responseready: true with 200 once the world is loaded, has begun play, is not tearing down, and the game mode + session are up. Otherwise 503 with reasons[] naming what is missing. Distinct from /healthz, which only says the process is alive: use this one for orchestration and load-balancer membership, since it answers with the status code rather than in the body.

GET /permissions

readonly — List the API permission catalog

Responsepermissions[] — the tokens you can assign to keys/roles: read, players, bans, whitelist, admins, chat, world, settings, config, maintenance, reports, rcon.

GET /capabilities

readonly — Feature tokens this server supports

ResponseapiVersion + features[] — named tokens for optional behaviour, so a client can tell what this server supports instead of guessing from a version number. Purely additive: tokens are never renamed or removed, and an absent token means not supported. A server too old to have this endpoint returns 404, which clients should read as “baseline server”, not as an error.

Example response

json
{
  "success": true,
  "apiVersion": 1,
  "count": 15,
  "features": [
    "waters",
    "players.groupId",
    "backups.list",
    "list.pagination"
  ]
}

GET /commands

readonly — List of RCON/console commands (DumpCommands)

Responsecommands[] — the console commands available via POST /rcon.

Server

GET /info

readonly — Server identity + population summary

ResponseserverName, motd, discord, playersOnline, maxPlayers, mapName, gameVersion (e.g. 1337h1), buildRevision, engineVersion, uptimeSeconds.

Example response

json
{
  "success": true,
  "serverName": "My Server",
  "playersOnline": 12,
  "maxPlayers": 100,
  "mapName": "Panjura",
  "gameVersion": "1337h1",
  "uptimeSeconds": 84213
}

GET /metrics

readonly — Performance metrics

Responsefps, frameTimeMs, playersOnline, uptimeSeconds.

GET /log

readonly — Recent server log lines (tail)

Query parameters

NameDescription
countint, optional (default 200) — number of trailing lines

Responselines[] (strings, oldest first).

POST /save

admin — Force a world/database save

Responseresponse string.

POST /restart

admin — Schedule a restart

Request body

NameDescription
secondsint, optional — delay before restart
messagestring, optional — broadcast shown to players

Example request body

json
{ "seconds": 300, "message": "Restarting for an update in 5 min" }

POST /cancelrestart

admin — Cancel a scheduled restart

GET /restart/schedule

readonly — Recurring auto-restart schedule

ResponsebServerAutoRestart, restartLengthInSeconds, times[] etc.

PUT /restart/schedule

admin — Update the recurring auto-restart schedule

Request body

NameDescription
(schedule object)same shape returned by GET /restart/schedule

POST /rcon

admin — Run any RCON/console command

Note: Requires bAllowGenericCommand=true on the server.

Request body

NameDescription
commandstring, required — the console command line

Example request body

json
{ "command": "Announce Server maintenance in 10 minutes" }

Players

GET /players

readonly — Connected players

Responseplayers[] — each: name, alderonId, ping, role, roleHierarchy, platform, species, gender, growth, growthStage, marks, location{x,y,z}, spectator, characterSelect, inHomeCave, groupId, groupLeader, discordId. groupId/groupLeader appear only when the player is in a party, and discordId only when they have a Discord account linked.

Example response

json
{
  "success": true,
  "players": [
    {
      "name": "RexHunter",
      "alderonId": "525053709",
      "ping": 42,
      "species": "Tyrannosaurus",
      "growth": 1.0,
      "spectator": false,
      "characterSelect": false
    }
  ]
}

GET /players/

readonly — A single connected player, or 404

Path parameters

NameDescription
agiddashed (525-053-709) or raw (525053709) id

Response — A single player object (as in /players).

DELETE /players/

admin — Kick a player

Path parameters

NameDescription
agiddashed display id, e.g. 525-053-709

Query parameters

NameDescription
reasonstring, optional — shown to the kicked player

POST /players/{agid}/heal

admin — Heal a player

Path parameters

NameDescription
agiddashed display id

POST /players/{agid}/cleareffects

admin — Clear a player's buffs/debuffs (leaves state effects alone)

Path parameters

NameDescription
agiddashed display id

POST /players/{agid}/damage

admin — Deal damage to a player. No instigator is recorded, so a lethal hit is not credited to anyone as a kill

Path parameters

NameDescription
agiddashed display id

Request body

NameDescription
amountnumber — damage to apply, must be > 0

POST /players/{agid}/growth

admin — Reward growth to a player

Path parameters

NameDescription
agiddashed display id

Request body

NameDescription
amountnumber — growth to add (0..1 scale)

POST /players/{agid}/marks

admin — Add/remove a player's marks

Path parameters

NameDescription
agiddashed display id

Request body

NameDescription
deltaint — signed change to the player's marks

POST /players/{agid}/mute

admin — Server-mute/unmute a player

Path parameters

NameDescription
agiddashed display id

Request body

NameDescription
mutedbool — true to mute, false to unmute

POST /whisper

admin — Direct-message one player

Request body

NameDescription
alderonIddashed display id (alias accepted: agid)
messagestring

Moderation

GET /mutes

readonly — Persisted server mutes

Query parameters

NameDescription
offsetint, optional
limitint, optional

Responsemutes[] — each: alderonId, expiration (0 = permanent, else a unix timestamp), adminReason, userReason, expired. This is the PERSISTED store, not the connected players: a mute outlives the session that applied it, so offline players appear here too. expired is reported rather than left to the client, because an expired entry survives in the file until the next load prunes it.

GET /bans

readonly — List active bans

Query parameters

NameDescription
offsetint, optional — skip this many (default 0)
limitint, optional — max to return (default: all)

Responsetotal, count + bans[] — each: alderonId, ipAddress, expiration (0 = permanent), adminReason, userReason.

PUT /bans/

admin — Ban a player

Path parameters

NameDescription
agiddashed display id

Request body

NameDescription
reasonstring, optional

DELETE /bans/

admin — Lift a ban

Path parameters

NameDescription
agiddashed display id

GET /whitelist

readonly — List whitelisted players

Query parameters

NameDescription
offsetint, optional — skip this many (default 0)
limitint, optional — max to return (default: all)

Responseenforced (bool), total, count + whitelist[] — each: alderonId.

PUT /whitelist/

admin — Whitelist a player

Path parameters

NameDescription
agiddashed display id

DELETE /whitelist/

admin — Remove from whitelist

Path parameters

NameDescription
agiddashed display id

GET /admins

readonly — Players with an assigned role, including offline ones

Responsecount + admins[] — each: alderonId, role, online plus name when the player is currently connected. Read from the persisted role assignments, so OFFLINE admins are included — unlike /players, which only shows who is on right now. A player promoted by name while offline is stored under that name, and is reported verbatim in alderonId.

PUT /admins/

admin — Promote (assign an admin role)

Path parameters

NameDescription
agiddashed display id

Request body

NameDescription
rolestring — role name to assign

DELETE /admins/

admin — Demote (remove admin roles)

Path parameters

NameDescription
agiddashed display id

GET /reports

readonly — In-game player reports queue

Query parameters

NameDescription
offsetint, optional — skip this many (default 0)
limitint, optional — max to return (default: all)

Responsetotal, count + reports[] — each: id, time, reporterName, reporterAlderonId, reportedName, reportedAlderonId, reason, category, resolved.

PATCH /reports/

admin — Update a report. Every field is optional and only applied when present, so you can assign a ticket without clearing its reply. Sending a reply shows it to the reporter in game immediately if they are online, and on their next join if not

Path parameters

NameDescription
idreport id

Request body

NameDescription
statusstring, optional — open | investigating | resolved | rejected
assignedTostring, optional — moderator handling it
actionstring, optional — action taken
responsestring, optional — reply shown to the reporter in game
resolvedbool, optional — kept in step with status

Database editor

GET /database/characters/

admin — Every stored character record for a player, including deleted ones (so a character removed by mistake can be recovered). Needs the 'database' permission, which is deliberately NOT part of an ordinary admin key — these are the raw save records

Path parameters

NameDescription
agiddashed display id

PUT /database/characters/{agid}/

admin — Overwrite one character record. Takes a backup first. Rejected without confirm:true, because a malformed record costs the player their character and the only undo is that backup. The player must reconnect for the change to load

Path parameters

NameDescription
agiddashed display id
cidcharacter id

Request body

NameDescription
dataobject — the complete character record
confirmbool — must be true

Chat & Events

GET /chat

readonly — Recent player chat messages

Responsemessages[].

POST /chat

admin — Post a message to global chat as the server

Request body

NameDescription
messagestring

POST /announce

admin — Broadcast a message (HUD announcement)

Request body

NameDescription
messagestring

QUERY /events

readonly — Filtered event search (structured body, GET semantics)

Request body

NameDescription
typesarray of strings, optional — only these event types
containsstring, optional — substring match on the event text
countint, optional — how many to return

Response — The same events[] shape as GET /events, filtered. Every field is optional, and an empty body is equivalent to the plain newest-N tail.

HTTP QUERY is a safe, idempotent read that carries a body (draft-ietf-httpbis-safe-method-w-body): GET semantics with POST transport, for filters too structured for a query string. It needs an engine that recognises the verb — older builds reject it before routing, so check the query.events capability first.

Example request body

json
{
  "types": ["PlayerKilled"],
  "contains": "Rex",
  "count": 50
}

GET /events

readonly — Recent server events (webhook feed)

Query parameters

NameDescription
countint, optional (default 200)

Responseevents[] — the same events webhooks emit (joins, kills, admin actions...).

World

GET /world

readonly — Current weather + time of day

Responseweather, timeOfDay (+ related fields).

POST /world/weather

admin — Set the weather

Request body

NameDescription
typestring — weather type name

POST /world/time

admin — Set the time of day

Request body

NameDescription
timeOfDaystring/number — e.g. "day", "night", or 0..2400

GET /waters

readonly — Water bodies + current quality

Responsecount + waters[] — each: identifier, quality (0..1).

POST /waters/refresh

admin — Refresh water quality to full

Query parameters

NameDescription
identifierstring, optional — one water body; omit for all

Responserefreshed — number of water bodies set back to full.

Settings & Config

GET /settings

readonly — Current mutable server settings

Response — Flat object of setting key -> current value.

GET /settings/all

readonly — All mutable settings with metadata + values

Responsesettings[] — each: key, value, type, default, needsRestart, description.

PATCH /settings

admin — Update server settings

Request body

NameDescription
(key: value)object of setting keys to new values

Responseresults — per-key outcome.

Example request body

json
{ "MaxPlayers": 100, "bServerPassword": false }

GET /config/

admin — Read a raw config ini

Path parameters

NameDescription
whichgame | engine | curveoverrides | mods | webhooks

Responsecontent — the raw ini text — plus exists. For mods and webhooks, an absent dedicated file falls back to the legacy location and sets usingFallback (see the config.legacyFallback capability). A file that is simply not there (Mods.ini and Webhooks.ini are optional) answers 200 with exists: false and empty content, NOT a 500. Keep the two apart: for Mods.ini, absent means "fall back to GameUserSettings" while present-but-empty means "no mods", so collapsing them would turn a save into a silent mod wipe.

PUT /config/

admin — Overwrite a raw config ini (needs restart)

Path parameters

NameDescription
whichgame | engine | curveoverrides | mods | webhooks

Request body

NameDescription
contentstring — full ini file text

ResponseneedsRestart + bytes. The previous contents are copied to &lt;name&gt;.ini.bak first, and the write is staged to a temp file and atomically renamed, so a failed write cannot truncate the live config. Creates the file if it did not exist.

POST /config/{which}/reload

admin — Re-read a config ini that was edited outside the API

Path parameters

NameDescription
whichgame | engine | curveoverrides | mods | webhooks

Response — Picks up a hand edit or a hosting-panel change without a restart. Branch-shape aware: game/engine rebuild the whole combined hierarchy (Default*.ini layers plus the generated file), standalone files re-read in place. Audited into the events feed like a write.

Player state

POST /players/{agid}/teleport

admin — Teleport a player to coordinates, a POI, or another player

Path parameters

NameDescription
agidplayer id, dashed or raw

Request body

NameDescription
destinationstring — a player name, a POI name, or Unreal coordinates (X=..,Y=..,Z=..)
x / y / znumbers — an alternative to destination for coordinates, which is what a JSON client naturally produces
safebool, optional (default true) — a safe teleport finds ground and avoids dropping the player inside geometry. Send false to place them exactly where asked.

Response — The command's response text. Forwards to the same Teleport RCON command an admin would type, so player resolution and permissions match chat.

Example request body

json
{
  "destination": "(X=45000,Y=-60000,Z=1500)"
}

GET /players/{agid}/attributes

readonly — Read a player's live gameplay attributes

Path parameters

NameDescription
agidplayer id, dashed or raw

Response — The GetAllAttr response text — health, stamina, growth and the rest of the attribute set. Returned as the command's own text rather than parsed: the set is large and game-specific, and parsing it in the plugin would put a second copy of that knowledge out of step with the game.

POST /players/{agid}/attributes

admin — Set one live gameplay attribute

Path parameters

NameDescription
agidplayer id, dashed or raw

Request body

NameDescription
namestring — the attribute, e.g. Health or Growth. Must be a plain identifier; the game resolves it and reports an unknown name as an error.
valuenumber — the new value

Response — The SetAttr response text. These exist so an integration does not need bAllowGenericCommand, a far broader grant than “may adjust a player’s health”.

Example request body

json
{
  "name": "Health",
  "value": 1450
}

MOTD & rules

GET /motd

readonly — Server MOTD, with its character limit

Response — The text under both motd and content, plus length and maxLength (16384) so you can check before sending rather than after a 400.

PUT /motd

admin — Replace the server MOTD

Request body

NameDescription
motdstring — the new MOTD
contentstring — accepted as an alias for the above

Response — Applies live; players see it immediately, so needsRestart is false. Over the limit is refused with a 400 naming the length and the limit — the setter would otherwise truncate silently. Newlines and the in-game rich-text tags both work. Needs the settings permission.

Example request body

json
{
  "motd": "Welcome!\nRaiding is allowed."
}

GET /rules

readonly — Server rules, with their character limit

Response — As GET /motd, under rules / content.

PUT /rules

admin — Replace the server rules

Request body

NameDescription
rulesstring — the new rules
contentstring — accepted as an alias for the above

Response — As PUT /motd. Both are also readable and writable through /settings; these exist because a single-value resource is the shape a bot actually wants. Stored as Saved/MOTD.txt and Rules.txt, not in an ini, which is why they do not appear in the config editor.

Webhooks

GET /webhooks

admin — Configured webhooks, section defaults, and every trigger this build can fire

Responseglobals (the [ServerWebhooks] defaults actually in effect), webhooks[] (each: key, url, bAllowRetries, retryCount, timeoutSeconds, maxQueued, critical, perKeyOverrides) and availableKeys[] — every trigger name this build can fire, so a client can offer a picker instead of expecting the owner to know them. Per-key values are the EFFECTIVE ones: a key with no overrides reports the section defaults, and perKeyOverrides says which it is.

Needs the config permission, not read. A webhook URL is a bearer credential — whoever holds a Discord webhook URL can post to that channel as the server indefinitely — so listing them is exactly as privileged as reading Game.ini.

PUT /webhooks

admin — Replace the webhook set

Request body

NameDescription
webhooksarray — the FULL set to keep; an omitted entry is a deletion, and an entry with an empty url is removed rather than written blank
globalsobject, optional — the [ServerWebhooks] section defaults

Responsecount written. Applies immediately (needsRestart: false): webhook config is re-read on every trigger. The section is rewritten wholesale, and a struct line is only emitted for a key that genuinely overrides a default, so a simple config stays simple. Keys are validated as plain identifiers before becoming ini key names.

Curves

GET /curves

readonly — Active curve/stat overrides

Response — The overrides set in the server ini alongside what actually resolved and applied, so a value that was accepted but never matched a real curve is visible rather than silently ignored.

PUT /curves

admin — Replace the server's curve overrides

Response — Applies live and persists to CurveOverrides.ini — no restart. Replaces the whole set, so send the full list, not a delta.

Roles

GET /roles

readonly — Configured player roles + permissions

Responseroles[] — each role with its permissions/flags (incl. spectatorAccess).

PUT /roles/

admin — Create or edit a role definition (hot-reloaded)

Path parameters

NameDescription
namerole name

Request body

NameDescription
(role definition)permissions/flags object

DELETE /roles/

admin — Delete a role definition

Path parameters

NameDescription
namerole name

Mods

GET /mods

readonly — Enabled + installed mods on this server

ResponseenabledMods[] + installed[] — the installed list is the Mods folder itself (see mods.disk), each entry with hasFiles and detailsKnown.

GET /mods/available

readonly — Browse the Alderon mod catalog

Responseavailable[].

PUT /mods/

admin — Enable a mod (needs restart)

Path parameters

NameDescription
skumod SKU, e.g. UGC_..._SK

Request body

NameDescription
buildSkustring, default "release"

DELETE /mods/

admin — Disable a mod (needs restart)

Path parameters

NameDescription
skumod SKU

Backups

GET /backups

admin — List database backups

Responsecount + backups[] — each: id, name (id is what /backups/{id}/restore takes).

POST /backups

admin — Create a database backup

POST /backups/{id}/restore

admin — Restore a database backup

Path parameters

NameDescription
idbackup id
Footer Image

1dc96e3