Files
languard-servers-manager/API.md
Tran G. (Revernomad) Khoa 624d7594e2 feat: multi-game adapter revamp, council protocol merge, and frontend design doc
- Revamp architecture for modular game server support (Arma 3 first, extensible)
- Merge ConfigSchema into ConfigGenerator per council decision (8→7 protocols)
- Add has_capability() method to GameAdapter protocol for explicit capability probing
- Add FRONTEND.md: production-grade dark neumorphism design with amber/orange palette
- Update all docs (ARCHITECTURE, MODULES, DATABASE, API, IMPLEMENTATION_PLAN, THREADING)
  to reflect protocol merge and multi-game adapter patterns
2026-04-16 17:05:04 +07:00

20 KiB

Languard Servers Manager — API Contract

Base URL

http://localhost:8000/api

Authentication

  • All endpoints except POST /auth/login and GET /system/health require: Authorization: Bearer <JWT>
  • WebSocket: pass token as query param: ws://localhost:8000/ws/{server_id}?token=<JWT>
  • JWT payload: { "sub": "user_id", "username": "string", "role": "admin|viewer", "exp": timestamp }

Common Response Envelope

{
  "success": true,
  "data": { ... },
  "error": null
}

Error response:

{
  "success": false,
  "data": null,
  "error": {
    "code": "NOT_FOUND",
    "message": "Server with id 5 not found"
  }
}

HTTP Status Codes

Code Meaning
200 Success
201 Created
204 No content (DELETE)
400 Validation error
401 Unauthenticated
403 Forbidden (insufficient role)
404 Not found (or capability not supported by adapter)
409 Conflict (already running, duplicate)
422 Unprocessable (Pydantic validation)
500 Internal server error

Capability-Based Routing

Some endpoints depend on the server's game adapter supporting a specific capability. If the adapter does not support the capability, the endpoint returns 404 with a clear message:

{
  "success": false,
  "data": null,
  "error": {
    "code": "CAPABILITY_NOT_SUPPORTED",
    "message": "Missions not supported for game type 'rust'"
  }
}

Auth Endpoints

POST /auth/login

Login and receive JWT.

Request:

{
  "username": "admin",
  "password": "secret"
}

Response 200:

{
  "success": true,
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIs...",
    "token_type": "bearer",
    "expires_in": 86400,
    "user": {
      "id": 1,
      "username": "admin",
      "role": "admin"
    }
  }
}

POST /auth/logout

Invalidate token (client-side token deletion; server-side blacklist optional).

GET /auth/me

Return current user info.

PUT /auth/password

Change password. Admin only.

{ "current_password": "old", "new_password": "new" }

GET /auth/users

List all users. Admin only.

POST /auth/users

Create user. Admin only.

{ "username": "viewer1", "password": "pass", "role": "viewer" }

DELETE /auth/users/{user_id}

Delete user. Admin only.


Game Type Discovery Endpoints

GET /games

List all registered game types and their capabilities.

Response 200:

{
  "success": true,
  "data": [
    {
      "game_type": "arma3",
      "display_name": "Arma 3",
      "version": "1.0.0",
      "capabilities": ["config_generator", "process_config",
        "log_parser", "remote_admin", "mission_manager", "mod_manager", "ban_manager"]
    }
  ]
}

GET /games/{game_type}

Get details for a specific game type.

Response 200:

{
  "success": true,
  "data": {
    "game_type": "arma3",
    "display_name": "Arma 3",
    "version": "1.0.0",
    "capabilities": ["config_generator", "process_config",
      "log_parser", "remote_admin", "mission_manager", "mod_manager", "ban_manager"],
    "config_sections": ["server", "basic", "profile", "launch", "rcon"],
    "allowed_executables": ["arma3server_x64.exe", "arma3server.exe"]
  }
}

GET /games/{game_type}/config-schema

Returns JSON Schema for each config section defined by the adapter. Used by frontend to build dynamic config forms.

Response 200:

{
  "success": true,
  "data": {
    "server": { /* JSON Schema for server.cfg params */ },
    "basic": { /* JSON Schema for basic.cfg params */ },
    "profile": { /* JSON Schema for Arma3Profile params */ },
    "launch": { /* JSON Schema for launch params */ },
    "rcon": { /* JSON Schema for RCon params */ }
  }
}

GET /games/{game_type}/defaults

Default config values for new server creation.

Response 200:

{
  "success": true,
  "data": {
    "server": { "hostname": "My Arma 3 Server", "max_players": 40, ... },
    "basic": { "min_bandwidth": 800000, ... },
    "profile": { "reduced_damage": 0, ... },
    "launch": { "world": "empty", "limit_fps": 50, ... },
    "rcon": { "max_ping": 200, "enabled": 1 }
  }
}

Server Endpoints

GET /servers

List all servers with current status. Supports filtering by game type.

Query params: ?limit=50&offset=0&game_type=arma3

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "name": "Main Server",
      "description": "Primary COOP server",
      "game_type": "arma3",
      "status": "running",
      "pid": 12345,
      "game_port": 2302,
      "rcon_port": 2306,
      "player_count": 15,
      "max_players": 40,
      "cpu_percent": 34.2,
      "ram_mb": 1850.5,
      "started_at": "2026-04-16T10:00:00Z"
    }
  ]
}

POST /servers

Create a new server. Admin only. game_type determines which adapter handles this server.

Request:

{
  "name": "Main Server",
  "description": "Primary COOP server",
  "game_type": "arma3",
  "exe_path": "C:/Arma3Server/arma3server_x64.exe",
  "game_port": 2302,
  "rcon_port": 2306,
  "auto_restart": true,
  "max_restarts": 3
}

The adapter provides default config values for all sections. Auto-generated credentials (e.g., password_admin, rcon_password for Arma 3) are returned in the response and not stored in plaintext.

Response 201: Returns full server object including auto-generated credentials.

GET /servers/{server_id}

Get server detail with full status.

Response 200:

{
  "success": true,
  "data": {
    "id": 1,
    "name": "Main Server",
    "game_type": "arma3",
    "status": "running",
    "pid": 12345,
    "game_port": 2302,
    "rcon_port": 2306,
    "auto_restart": true,
    "restart_count": 0,
    "player_count": 15,
    "max_players": 40,
    "cpu_percent": 34.2,
    "ram_mb": 1850.5,
    "started_at": "2026-04-16T10:00:00Z",
    "uptime_seconds": 3600
  }
}

PUT /servers/{server_id}

Update server metadata (name, description, exe_path, ports). Admin only.

DELETE /servers/{server_id}

Delete server (must be stopped first). Admin only. Removes DB rows and servers/{id}/ directory.

POST /servers/{server_id}/start

Start the server. Admin only. Core resolves the adapter and delegates config generation + launch arg building.

Response 200:

{ "success": true, "data": { "status": "starting", "pid": null } }

Response 409: Server already running.

POST /servers/{server_id}/stop

Graceful stop (sends shutdown via adapter's RemoteAdmin, then force-kill after 30s). Admin only.

Request (optional):

{ "force": false, "reason": "Maintenance" }

POST /servers/{server_id}/restart

Stop then start. Admin only.

POST /servers/{server_id}/kill

Force-kill the process immediately. Admin only. Emergency use only.


Server Config Endpoints

Config sections are defined by the server's game adapter. The core game_configs table stores them as JSON. The adapter's Pydantic models validate input.

GET /servers/{server_id}/config

Get all config sections combined. Each section includes its config_version for optimistic locking.

Response 200:

{
  "success": true,
  "data": {
    "server": { /* section JSON */, "_meta": {"config_version": 3, "schema_version": "1.0"} },
    "basic": { /* section JSON */, "_meta": {"config_version": 1, "schema_version": "1.0"} },
    "profile": { /* section JSON */, "_meta": {"config_version": 2, "schema_version": "1.0"} },
    "launch": { /* section JSON */, "_meta": {"config_version": 1, "schema_version": "1.0"} },
    "rcon": { "rcon_password": "***", "max_ping": 200, "enabled": 1, "_meta": {"config_version": 1, "schema_version": "1.0"} }
  }
}

GET /servers/{server_id}/config/{section}

Get a single config section. Section names are defined by the adapter (e.g., server, basic, profile, launch, rcon for Arma 3).

Response 200:

{
  "success": true,
  "data": {
    "hostname": "My Server",
    "max_players": 40,
    "_meta": { "config_version": 3, "schema_version": "1.0" }
  }
}

PUT /servers/{server_id}/config/{section}

Update a config section. Admin only. Validated against the adapter's Pydantic model for that section. Sensitive fields (passwords) are encrypted before storage. Optimistic locking — client must send config_version from their last read.

Request: Partial object matching the adapter's section schema. Any omitted field keeps current value. Must include config_version for conflict detection.

Arma 3 server section example:

{
  "hostname": "Updated Server Name",
  "max_players": 64,
  "battleye": 1,
  "verify_signatures": 2,
  "motd_lines": ["Welcome!", "Have fun"],
  "motd_interval": 5.0,
  "config_version": 3
}

Response 409 (Conflict): Another admin updated this section since you read it.

{
  "success": false,
  "data": {
    "current_config": { /* latest values */ },
    "current_version": 5
  },
  "error": {
    "code": "CONFIG_VERSION_CONFLICT",
    "message": "Config section 'server' was modified by another user. Re-read and merge your changes."
  }
}

Arma 3 basic section example:

{
  "max_bandwidth": 50000000,
  "max_msg_send": 256
}

Arma 3 profile section example:

{
  "third_person_view": 0,
  "weapon_crosshair": 0,
  "ai_level_preset": 3,
  "skill_ai": 0.7,
  "precision_ai": 0.6
}

Arma 3 launch section example:

{
  "world": "empty",
  "limit_fps": 50,
  "auto_init": false,
  "load_mission_to_memory": true
}

Arma 3 rcon section example:

{
  "rcon_password": "newpassword",
  "rcon_port": 2306,
  "max_ping": 300,
  "enabled": true
}

Note: rcon_port is stored in the servers table, not in the config JSON. The service layer updates both tables as needed.

GET /servers/{server_id}/config/preview

Returns rendered config for preview in UI. Admin only — may contain plaintext credentials. Returns a dict of {label: rendered_content} — labels are filenames for file-based configs, variable names for env-var configs, or argument names for CLI configs.

Response 200:

{
  "success": true,
  "data": {
    "server.cfg": "// Generated server.cfg\nhostname = \"My Server\";\n...",
    "basic.cfg": "// Generated basic.cfg\n...",
    "server.Arma3Profile": "// Generated profile\n..."
  }
}

(Non-file games would return e.g. {"SERVER_NAME": "My Server", "MAX_PLAYERS": "40"} for env-var configs.)

GET /servers/{server_id}/config/download/{filename}

Download generated config file. Filename must be in adapter's allowlist (whitelist-validated, no path traversal). Admin only.


Mission Endpoints (Capability: mission_manager)

Returns 404 if adapter does not support mission_manager.

GET /servers/{server_id}/missions

List all mission/scenario files for a server.

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "filename": "MyMission.Altis.pbo",
      "mission_name": "MyMission.Altis",
      "terrain": "Altis",
      "file_size": 102400,
      "uploaded_at": "2026-04-16T09:00:00Z"
    }
  ]
}

POST /servers/{server_id}/missions/upload

Upload a mission/scenario file. Admin only. multipart/form-data. File extension validated by adapter's MissionManager.file_extension.

Form fields:

  • file: the mission file (filename sanitized; only adapter-allowed extensions accepted)

Response 201:

{
  "success": true,
  "data": {
    "id": 2,
    "filename": "NewMission.Stratis.pbo",
    "mission_name": "NewMission.Stratis",
    "terrain": "Stratis",
    "file_size": 51200
  }
}

DELETE /servers/{server_id}/missions/{mission_id}

Delete a mission file (removes file from disk). Admin only.

GET /servers/{server_id}/missions/rotation

Get current mission/scenario rotation (ordered list).

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "sort_order": 0,
      "mission": { "id": 1, "mission_name": "MyMission.Altis" },
      "difficulty": "Regular",
      "params_json": { "RespawnDelay": 15 }
    }
  ]
}

PUT /servers/{server_id}/missions/rotation

Replace the entire mission rotation. Admin only.

{
  "rotation": [
    { "mission_id": 1, "difficulty": "Regular", "params": {} },
    { "mission_id": 2, "difficulty": "Veteran", "params": { "RespawnDelay": 30 } }
  ]
}

Mod Endpoints (Capability: mod_manager)

Returns 404 if adapter does not support mod_manager.

GET /mods

List all registered mods. Optionally filter by game type.

Query params: ?game_type=arma3

POST /mods

Register a mod folder. Admin only.

{
  "game_type": "arma3",
  "name": "@CBA_A3",
  "folder_path": "C:/Arma3Server/@CBA_A3",
  "workshop_id": "450814997",
  "description": "Community Base Addons"
}

DELETE /mods/{mod_id}

Delete mod registration. Admin only.

GET /servers/{server_id}/mods

Get mods enabled for a server.

Response 200:

{
  "success": true,
  "data": [
    {
      "mod_id": 1,
      "name": "@CBA_A3",
      "folder_path": "C:/Arma3Server/@CBA_A3",
      "is_server_mod": false,
      "sort_order": 0
    }
  ]
}

PUT /servers/{server_id}/mods

Replace the mod list for a server. Admin only.

{
  "mods": [
    { "mod_id": 1, "is_server_mod": false, "sort_order": 0 },
    { "mod_id": 2, "is_server_mod": true,  "sort_order": 1 }
  ]
}

Player Endpoints

GET /servers/{server_id}/players

Get currently connected players.

Response 200:

{
  "success": true,
  "data": [
    {
      "slot_id": "1",
      "name": "PlayerOne",
      "guid": "abc123...",
      "ping": 45,
      "game_data": { "verified": true, "steam_uid": "76561198..." },
      "joined_at": "2026-04-16T10:15:00Z"
    }
  ]
}

POST /servers/{server_id}/players/{slot_id}/kick

Kick a player. Admin only. Requires adapter remote_admin capability.

{ "reason": "AFK" }

POST /servers/{server_id}/players/{slot_id}/ban

Ban a player. Admin only. Requires adapter remote_admin capability.

{
  "reason": "Griefing",
  "duration_minutes": 0
}

GET /servers/{server_id}/players/history

Player connection history. Supports pagination.

Query params: ?limit=50&offset=0&search=PlayerName


Ban Endpoints

GET /servers/{server_id}/bans

List all bans for a server.

Query params: ?active_only=true&limit=50&offset=0

POST /servers/{server_id}/bans

Add ban manually. Admin only. If adapter has ban_manager, also syncs to the game's ban file.

{
  "guid": "abc123...",
  "name": "PlayerName",
  "reason": "Cheating",
  "duration_minutes": 0
}

DELETE /servers/{server_id}/bans/{ban_id}

Remove a ban. Admin only. If adapter has ban_manager, also removes from the game's ban file.


Remote Admin Endpoints (Capability: remote_admin)

Returns 404 if adapter does not support remote_admin.

POST /servers/{server_id}/remote-admin/command

Send raw remote admin command. Admin only.

{ "command": "#restart" }

Arma 3 available commands:

  • #restart — Restart mission
  • #reassign — Restart with roles unassigned
  • #missions — Open mission selection
  • #lock / #unlock — Lock/unlock server
  • #mission NAME.TERRAIN [difficulty] — Load specific mission
  • #shutdown — Shut down server
  • #monitor N — Toggle performance monitoring
  • say -1 MESSAGE — Message all players

POST /servers/{server_id}/remote-admin/say

Broadcast a message to all players. Admin only.

{ "message": "Server restarting in 5 minutes!" }

Log Endpoints

GET /servers/{server_id}/logs

Query stored log lines.

Query params: ?limit=200&offset=0&level=error&since=2026-04-16T10:00:00Z&search=BattlEye

Response 200:

{
  "success": true,
  "data": {
    "total": 1542,
    "logs": [
      {
        "id": 100,
        "timestamp": "2026-04-16T10:05:23Z",
        "level": "info",
        "message": "Player PlayerOne connected"
      }
    ]
  }
}

DELETE /servers/{server_id}/logs

Clear all stored log lines for a server. Admin only.


Metrics Endpoints

GET /servers/{server_id}/metrics

Get time-series metrics.

Query params: ?from=2026-04-16T00:00:00Z&to=2026-04-16T23:59:59Z&resolution=5m

Response 200:

{
  "success": true,
  "data": [
    {
      "timestamp": "2026-04-16T10:00:00Z",
      "cpu_percent": 34.2,
      "ram_mb": 1850.5,
      "player_count": 15
    }
  ]
}

Event Log Endpoints

GET /servers/{server_id}/events

Get server event history (audit trail).

Query params: ?limit=50&offset=0&event_type=crashed


System Endpoints

GET /system/status

Overall system status. Requires authentication (admin or viewer).

{
  "success": true,
  "data": {
    "version": "1.0.0",
    "running_servers": 2,
    "total_servers": 3,
    "supported_games": ["arma3"],
    "uptime_seconds": 86400
  }
}

GET /system/health

Health check (for load balancer/Docker). Returns 200 if healthy.


WebSocket API

Connection

ws://localhost:8000/ws/{server_id}?token=<JWT>

Use server_id = "all" to subscribe to events from all servers.

Client → Server Messages

{ "type": "ping" }
{ "type": "subscribe", "channels": ["logs", "players", "metrics", "status"] }
{ "type": "unsubscribe", "channels": ["metrics"] }

Channel subscription: The ConnectionManager tracks per-connection channel subscriptions. Only messages matching subscribed channels are delivered. Default subscriptions on connect: ["status"].

Server → Client Messages

Status Update

{
  "type": "status",
  "server_id": 1,
  "data": {
    "status": "running",
    "pid": 12345,
    "started_at": "2026-04-16T10:00:00Z"
  }
}

Log Line

{
  "type": "log",
  "server_id": 1,
  "data": {
    "timestamp": "2026-04-16T10:05:23Z",
    "level": "info",
    "message": "BattlEye Server: Initialized (v1.240)"
  }
}

Player List Update

{
  "type": "players",
  "server_id": 1,
  "data": {
    "players": [
      { "slot_id": "1", "name": "PlayerOne", "ping": 45 }
    ],
    "count": 1
  }
}

Metrics Update

{
  "type": "metrics",
  "server_id": 1,
  "data": {
    "cpu_percent": 34.2,
    "ram_mb": 1850.5,
    "player_count": 1,
    "timestamp": "2026-04-16T10:05:25Z"
  }
}

Server Event

{
  "type": "event",
  "server_id": 1,
  "data": {
    "event_type": "crashed",
    "detail": { "exit_code": 1 },
    "timestamp": "2026-04-16T10:30:00Z"
  }
}

Pong

{ "type": "pong" }

Adapter-Specific Routes

Adapters may register additional routes under /api/servers/{server_id}/game/{game_type}/... for features that have no generic counterpart.

Arma 3 example:

POST /api/servers/{server_id}/game/arma3/battleye/reload

These routes are registered at app startup by iterating over all registered adapters.


Rate Limiting

  • POST /auth/login: 5 attempts per minute per IP. Exceeded returns 429 Too Many Requests.
  • All other endpoints: 60 requests per minute per token. Exceeded returns 429.
  • Implemented via FastAPI middleware (e.g., slowapi).

Error Codes Reference

Code Description
UNAUTHORIZED Missing or invalid token
FORBIDDEN Role insufficient
NOT_FOUND Resource not found
CAPABILITY_NOT_SUPPORTED Adapter lacks required capability for this endpoint
SERVER_ALREADY_RUNNING Start called on running server
SERVER_NOT_RUNNING Stop/command on stopped server
REMOTE_ADMIN_UNAVAILABLE Remote admin connection failed
INVALID_CONFIG Config validation failed (adapter-specific)
CONFIG_WRITE_ERROR Config file write failed (disk, permissions)
CONFIG_VERSION_CONFLICT Optimistic locking conflict on config update
EXE_NOT_ALLOWED Executable not in adapter's allowlist
PORT_IN_USE Game port already occupied
UPLOAD_FAILED File upload error
VALIDATION_ERROR Pydantic validation failure
GAME_TYPE_NOT_FOUND No adapter registered for this game type
INTERNAL_ERROR Unexpected server error
MOD_IN_USE Cannot delete mod — enabled on one or more servers
MISSION_IN_ROTATION Cannot delete mission — in active rotation
RATE_LIMITED Too many requests