Files
languard-servers-manager/API.md
2026-04-17 20:50:19 +07:00

35 KiB
Raw Blame History

Languard Server Manager — API Reference

Base URL

http://localhost:8000/api

All HTTP endpoints are prefixed with /api. The WebSocket endpoint is at /ws (no /api prefix).

Authentication

All endpoints except POST /auth/login and GET /system/health require a JWT bearer token:

Authorization: Bearer <access_token>

For WebSocket, pass the token as a query parameter:

ws://localhost:8000/ws?token=<access_token>&server_id=1

JWT payload:

{
  "sub": "user_id",
  "username": "string",
  "role": "admin|viewer",
  "exp": 1745000000
}

Roles

Role Access
admin Full access: create, update, delete, start/stop servers
viewer Read-only: list servers, view config (sensitive masked)

Standard Response Envelope

All responses use a consistent envelope:

Success:

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

Error:

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

Some error responses (from FastAPI HTTPException) use a detail object instead:

{
  "detail": {
    "code": "NOT_FOUND",
    "message": "Server 5 not found"
  }
}

HTTP Status Codes

Code Meaning
200 Success
201 Created (resource successfully created)
204 No content (successful DELETE)
400 Bad request (validation error, capability not supported)
401 Unauthenticated (missing or invalid token)
403 Forbidden (insufficient role — admin required)
404 Not found (resource or capability not available)
409 Conflict (already running, port in use, version conflict)
413 Payload too large (file upload exceeds 500 MB)
422 Unprocessable entity (Pydantic validation failure)
500 Internal server error
503 Service unavailable (RCon connection failed)

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 400 with:

{
  "success": false,
  "data": null,
  "error": {
    "code": "NOT_SUPPORTED",
    "message": "Game type 'rust' does not support mission management"
  }
}

Auth Endpoints

POST /auth/login

Authenticate and receive a JWT token. Public endpoint (no auth required).

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"
    }
  },
  "error": null
}

Error 401: Invalid credentials.

{
  "success": false,
  "data": null,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid credentials"
  }
}

POST /auth/logout

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

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": { "message": "Logged out" },
  "error": null
}

GET /auth/me

Return the currently authenticated user.

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": {
    "id": 1,
    "username": "admin",
    "role": "admin"
  },
  "error": null
}

PUT /auth/password

Change the authenticated user's own password. Any authenticated user can change their own password (not admin-only).

Auth: Required (any role)

Request:

{
  "current_password": "old_password",
  "new_password": "new_password"
}

Response 200:

{
  "success": true,
  "data": { "message": "Password changed" },
  "error": null
}

Error 401: Current password is incorrect.


GET /auth/users

List all users.

Auth: Admin required

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "username": "admin",
      "role": "admin",
      "created_at": "2026-04-16T00:00:00",
      "last_login": "2026-04-17T10:30:00"
    }
  ],
  "error": null
}

POST /auth/users

Create a new user.

Auth: Admin required

Request:

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

role defaults to "viewer" if omitted. Valid values: "admin", "viewer".

Response 201:

{
  "success": true,
  "data": {
    "id": 2,
    "username": "viewer1",
    "role": "viewer",
    "created_at": "2026-04-17T12:00:00"
  },
  "error": null
}

Error 409: Username already taken.


DELETE /auth/users/{user_id}

Delete a user. Cannot delete yourself.

Auth: Admin required

Response 204: No content.

Error 400: Attempting to delete your own account.


Games Endpoints

GET /games

List all registered game types with their capabilities.

Auth: Not required (public)

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"
      ]
    }
  ],
  "error": null
}

GET /games/{game_type}

Get details for a specific game type, including capabilities, config sections, and allowed executables.

Auth: Not required (public)

Path params:

Parameter Type Description
game_type string Game type identifier

Response 200:

{
  "success": true,
  "data": {
    "game_type": "arma3",
    "display_name": "Arma 3",
    "version": "1.0.0",
    "schema_version": "1.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"]
  },
  "error": null
}

Error 404: Unknown game type.


GET /games/{game_type}/config-schema

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

Auth: Not required (public)

Path params:

Parameter Type Description
game_type string Game type identifier

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" }
  },
  "error": null
}

GET /games/{game_type}/defaults

Default config values for new server creation.

Auth: Not required (public)

Path params:

Parameter Type Description
game_type string Game type identifier

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 }
  },
  "error": null
}

System Endpoints

GET /system/health

Public health check. Used by load balancers and Docker health probes.

Auth: Not required

Response 200:

{
  "status": "ok"
}

Note: This endpoint does not use the standard envelope.


GET /system/status

System status including version and running server counts.

Auth: Required (any role)

Response 200:

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

Server Endpoints

GET /servers

List all servers with current status and live metrics.

Auth: Required (any role)

Query params:

Parameter Type Description
game_type string Filter servers by game type

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,
      "auto_restart": true,
      "max_restarts": 3,
      "restart_count": 0,
      "player_count": 15,
      "cpu_percent": 34.2,
      "ram_mb": 1850.5,
      "started_at": "2026-04-16T10:00:00Z"
    }
  ],
  "error": null
}

cpu_percent, ram_mb, and player_count are merged from live metrics. They will be null if no metrics are available.


POST /servers

Create a new server. The game_type determines which adapter handles this server.

Auth: Admin required

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
}
Field Type Required Default Validation
name string Yes
description string No null
game_type string No "arma3" Must be a registered type
exe_path string Yes Filename must be in allowlist
game_port integer Yes 102465535, must not be in use
rcon_port integer No auto 102465535, auto = game_port + 3
auto_restart boolean No false
max_restarts integer No 3 020

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 creation response only.

Response 201: Returns the full server object.

Errors:

  • 400 GAME_TYPE_NOT_FOUND — Unknown game type
  • 400 EXE_NOT_ALLOWED — Executable filename not in adapter allowlist
  • 409 PORT_IN_USE — Game port or RCon port already in use

GET /servers/{server_id}

Get server detail with full status.

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": {
    "id": 1,
    "name": "Main Server",
    "description": "Primary COOP server",
    "game_type": "arma3",
    "status": "running",
    "pid": 12345,
    "exe_path": "C:/Arma3Server/arma3server_x64.exe",
    "game_port": 2302,
    "rcon_port": 2306,
    "auto_restart": true,
    "max_restarts": 3,
    "restart_count": 0,
    "player_count": 15,
    "cpu_percent": 34.2,
    "ram_mb": 1850.5,
    "started_at": "2026-04-16T10:00:00Z",
    "uptime_seconds": 3600
  },
  "error": null
}

Error 404: Server not found.


PUT /servers/{server_id}

Update server metadata (name, description, exe_path, ports). Only provided fields are updated; omitted fields keep their current values.

Auth: Admin required

Request:

{
  "name": "Updated Server Name",
  "description": "New description",
  "exe_path": "C:/Arma3Server/arma3server_x64.exe",
  "game_port": 2302,
  "rcon_port": 2306,
  "auto_restart": false,
  "max_restarts": 5
}

All fields are optional. Port validation (102465535) applies if provided.

Response 200: Returns the updated server object.


DELETE /servers/{server_id}

Delete a server. The server must be in a stopped, crashed, or error state.

Auth: Admin required

Response 204: No content.

Error 409: SERVER_NOT_STOPPED — Server is currently running.

Note: Also deletes the server's directory on disk (servers/{id}/).


POST /servers/{server_id}/start

Start the server. The system resolves the adapter, writes config files atomically, builds launch arguments, starts the process, and attaches monitoring threads.

Auth: Admin required

Response 200:

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

Errors:

  • 400 EXE_NOT_ALLOWED — Executable not in adapter allowlist
  • 400 INVALID_CONFIG — Config validation or launch args failed
  • 409 SERVER_ALREADY_RUNNING — Server is already running or starting
  • 409 PORT_IN_USE — Game port or RCon port already in use
  • 500 CONFIG_WRITE_ERROR — Failed to write config files to disk

POST /servers/{server_id}/stop

Graceful stop. Sends a shutdown signal via the adapter's remote admin, then force-kills after 30 seconds if the process has not exited.

Auth: Admin required

Request (optional body):

{
  "force": false,
  "reason": "Scheduled maintenance"
}
Field Type Required Default Description
force boolean No false Skip graceful shutdown, terminate immediately
reason string No null Optional reason for the stop

Response 200:

{
  "success": true,
  "data": { "status": "stopped" },
  "error": null
}

Error 409: SERVER_NOT_RUNNING — Server is already stopped or crashed.


POST /servers/{server_id}/restart

Stop then start the server. Equivalent to calling stop then start sequentially.

Auth: Admin required

Response 200: Returns the start result (same shape as start).


POST /servers/{server_id}/kill

Force-kill the server process immediately. Use for emergency situations only; does not attempt graceful shutdown.

Auth: Admin required

Response 200:

{
  "success": true,
  "data": { "status": "stopped" },
  "error": null
}

Server Config Endpoints

Config sections are defined by the server's game adapter. The core game_configs table stores them as JSON. Each section tracks a config_version for optimistic locking.

GET /servers/{server_id}/config

Get all config sections combined. Sensitive fields (passwords) are masked with "***".

Auth: Required (any role — sensitive fields are masked for non-admin viewers)

Response 200:

{
  "success": true,
  "data": {
    "server": {
      "hostname": "My Server",
      "max_players": 40,
      "_meta": { "config_version": 3, "schema_version": "1.0" }
    },
    "basic": {
      "max_bandwidth": 50000000,
      "_meta": { "config_version": 1, "schema_version": "1.0" }
    },
    "profile": {
      "third_person_view": 0,
      "_meta": { "config_version": 2, "schema_version": "1.0" }
    },
    "launch": {
      "world": "empty",
      "limit_fps": 50,
      "_meta": { "config_version": 1, "schema_version": "1.0" }
    },
    "rcon": {
      "rcon_password": "***",
      "max_ping": 200,
      "enabled": 1,
      "_meta": { "config_version": 1, "schema_version": "1.0" }
    }
  },
  "error": null
}

GET /servers/{server_id}/config/schema

Returns per-field widget hints for the frontend config editor. Used by ConfigEditor to render the correct UI widget (text box, toggle, select, tag list, etc.) for each field.

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": {
    "server": {
      "hostname":          { "widget": "text",     "label": "Server Hostname" },
      "max_players":       { "widget": "number",   "label": "Max Players", "min": 1, "max": 1000 },
      "password":          { "widget": "password", "label": "Player Password" },
      "forced_difficulty": { "widget": "select",   "label": "Difficulty Preset", "options": ["Recruit", "Regular", "Veteran", "Custom"] },
      "battleye":          { "widget": "toggle",   "label": "BattleEye Anti-Cheat" },
      "motd_lines":        { "widget": "textarea", "label": "Message of the Day (one line per row)" },
      "admin_uids":        { "widget": "tag-list", "label": "Admin Steam UIDs", "placeholder": "76561198000000000" }
    },
    "rcon": {
      "rcon_password": { "widget": "password", "label": "RCon Password" }
    }
  },
  "error": null
}

Returns {} if the adapter does not implement get_ui_schema().


GET /servers/{server_id}/config/preview

Rendered config for preview. Admin only because it may contain plaintext credentials.

Auth: Admin required

Returns a dict of {label: rendered_content} where 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": "hostname = \"My Server\";\nmaxPlayers = 40;\n...",
    "basic.cfg": "// Generated basic.cfg\n...",
    "server.Arma3Profile": "// Generated profile\n..."
  },
  "error": null
}

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).

Auth: Required (any role — sensitive fields are masked)

Response 200:

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

Error 404: Config section not found (not a valid section for this adapter).


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

Update a config section. Uses optimistic locking — the request must include config_version from the last read. Validated against the adapter's Pydantic model for that section. Omitted fields keep their current values (partial update).

Auth: Admin required

Request:

{
  "hostname": "Updated Server Name",
  "max_players": 64,
  "config_version": 3
}

config_version is required for conflict detection. Any omitted field retains its current value.

Arma 3 section examples:

server section:

{
  "hostname": "My Arma Server",
  "max_players": 40,
  "battleye": 1,
  "verify_signatures": 2,
  "motd_lines": ["Welcome!", "Have fun"],
  "motd_interval": 5.0,
  "config_version": 3
}

basic section:

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

profile section:

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

launch section:

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

rcon section:

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

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

Response 200: Returns the updated section (sensitive fields masked).

Error 409 — Optimistic locking conflict:

{
  "success": false,
  "data": null,
  "error": {
    "code": "CONFIG_VERSION_CONFLICT",
    "message": "Config was modified by another user. Re-read and merge.",
    "current_config": { "...": "latest values" },
    "current_version": 5
  }
}

Error 422: Pydantic validation failure — the submitted values do not match the adapter's schema.


RCon Endpoints

POST /servers/{server_id}/rcon/command

Send an RCon command to a running server. Requires the adapter to support the remote_admin capability.

Auth: Admin required

Request:

{
  "command": "#restart"
}

Response 200:

{
  "success": true,
  "data": {
    "response": "Command executed"
  },
  "error": null
}

Errors:

  • 400 NOT_SUPPORTED — Game type does not support RCon
  • 400 NO_RCON_PASSWORD — RCon password not configured for this server
  • 503 RCON_ERROR — RCon connection or command failed

Arma 3 available RCon commands:

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

Player Endpoints

GET /servers/{server_id}/players

List currently connected players (cached from RemoteAdminPollerThread).

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": {
    "server_id": 1,
    "player_count": 2,
    "players": [
      {
        "slot_id": "1",
        "name": "PlayerOne",
        "ping": 45
      },
      {
        "slot_id": "2",
        "name": "PlayerTwo",
        "ping": 78
      }
    ]
  },
  "error": null
}

GET /servers/{server_id}/players/history

Get historical player session records.

Auth: Required (any role)

Query params:

Parameter Type Default Description
limit integer 100 Maximum records to return
offset integer 0 Pagination offset
search string Filter by player name

Response 200:

{
  "success": true,
  "data": {
    "total": 150,
    "items": [
      {
        "id": 1,
        "player_name": "PlayerOne",
        "guid": "abc123...",
        "joined_at": "2026-04-16T10:15:00Z",
        "left_at": "2026-04-16T11:30:00Z"
      }
    ]
  },
  "error": null
}

Ban Endpoints

GET /servers/{server_id}/bans

List all active bans for a server.

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "server_id": 1,
      "guid": "abc123...",
      "name": null,
      "reason": "Cheating",
      "banned_by": "admin",
      "ban_type": "GUID",
      "duration_minutes": 0,
      "expires_at": null,
      "created_at": "2026-04-16T10:00:00Z"
    }
  ],
  "error": null
}

POST /servers/{server_id}/bans

Create a new ban. Writes to the database and syncs to the game's bans.txt file (if adapter supports ban_manager).

Auth: Admin required

Request:

{
  "player_uid": "abc123...",
  "ban_type": "GUID",
  "reason": "Cheating",
  "duration_minutes": 0
}
Field Type Required Default Description
player_uid string Yes GUID or IP to ban
ban_type string No "GUID" Must be "GUID" or "IP"
reason string No "" Reason for the ban
duration_minutes integer No 0 0 = permanent, >0 = timed ban

Response 201:

{
  "success": true,
  "data": {
    "id": 2,
    "server_id": 1,
    "guid": "abc123...",
    "reason": "Cheating",
    "ban_type": "GUID",
    "expires_at": null
  },
  "error": null
}

Note: If the bans.txt file sync fails, the database ban is still created. The error is logged but does not fail the request.


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

Revoke (deactivate) a ban. Removes from bans.txt if the adapter supports ban_manager.

Auth: Admin required

Response 200:

{
  "success": true,
  "data": { "message": "Ban 2 revoked" },
  "error": null
}

Error 404: Ban not found or does not belong to this server.


Mission Endpoints

All mission endpoints require the adapter to support the mission_manager capability. Returns 400 NOT_SUPPORTED if the game type does not support missions.

GET /servers/{server_id}/missions

List all available mission/scenario files on disk.

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": {
    "server_id": 1,
    "total": 2,
    "missions": [
      {
        "name": "MyMission.Altis",
        "filename": "MyMission.Altis.pbo",
        "size_bytes": 102400,
        "terrain": "Altis"
      }
    ]
  },
  "error": null
}

POST /servers/{server_id}/missions

Upload a mission file. Multipart form-data. Maximum file size: 500 MB. File extension is validated by the adapter (e.g., .pbo for Arma 3).

Auth: Admin required

Request: multipart/form-data with field file.

Response 201:

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

Errors:

  • 400 NO_FILENAME — No filename provided in upload
  • 400 ADAPTER_ERROR — Upload failed (wrong extension, etc.)
  • 413 FILE_TOO_LARGE — File exceeds 500 MB

GET /servers/{server_id}/missions/rotation

Get the current mission rotation from the server config.

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": {
    "missions": [
      { "name": "MyMission.Altis", "difficulty": "Regular" },
      { "name": "TvT.Stratis", "difficulty": "Veteran" }
    ]
  },
  "error": null
}

PUT /servers/{server_id}/missions/rotation

Replace the mission rotation. Uses optimistic locking — must include config_version from the last server config read.

Auth: Admin required

Request:

{
  "missions": [
    { "name": "MyMission.Altis", "difficulty": "Regular" },
    { "name": "TvT.Stratis", "difficulty": "" }
  ],
  "config_version": 3
}

difficulty can be "" for default, or one of "Recruit", "Regular", "Veteran", "Custom".

Response 200:

{
  "success": true,
  "data": { "missions": [ ... ] },
  "error": null
}

Error 409: Config version conflict — re-fetch and retry.


DELETE /servers/{server_id}/missions/{filename}

Delete a mission file by filename. Removes the file from disk.

Auth: Admin required

Path params:

Parameter Type Description
filename string Mission filename (e.g. MyMission.Altis.pbo)

Response 200:

{
  "success": true,
  "data": { "message": "Mission 'MyMission.Altis.pbo' deleted" },
  "error": null
}

Error 404: Mission file not found.


Mod Endpoints

All mod endpoints require the adapter to support the mod_manager capability. Returns 400 NOT_SUPPORTED if the game type does not support mods.

GET /servers/{server_id}/mods

List all available mods and which are currently enabled for this server.

Auth: Required (any role)

Response 200:

{
  "success": true,
  "data": {
    "server_id": 1,
    "enabled_count": 2,
    "mods": [
      {
        "name": "@CBA_A3",
        "folder_path": "C:/Arma3Server/@CBA_A3",
        "enabled": true
      },
      {
        "name": "@ACRE2",
        "folder_path": "C:/Arma3Server/@ACRE2",
        "enabled": true
      },
      {
        "name": "@USAF",
        "folder_path": "C:/Arma3Server/@USAF",
        "enabled": false
      }
    ]
  },
  "error": null
}

PUT /servers/{server_id}/mods/enabled

Set the list of enabled mods. This replaces the entire enabled list — send the complete list every time. The server must be restarted for changes to take effect.

Auth: Admin required

Request:

{
  "mods": ["@CBA_A3", "@ACRE2"]
}
Field Type Required Description
mods array[string] Yes Complete list of mod names to enable

Response 200:

{
  "success": true,
  "data": {
    "message": "Enabled mods updated. Restart the server for changes to take effect.",
    "enabled_mods": ["@CBA_A3", "@ACRE2"]
  },
  "error": null
}

Error 409 VERSION_CONFLICT — Config was modified by another request while updating mods.


WebSocket API

Connection

ws://localhost:8000/ws?token=<JWT>&server_id=1&server_id=2

Parameters:

Parameter Type Required Description
token string Yes JWT access token
server_id integer (repeatable) No Server IDs to subscribe to. Omit for all servers

Authentication: JWT is passed as a query parameter because the browser WebSocket API does not support custom headers. If the token is missing or invalid, the connection is closed with code 4001.

Welcome message on connect:

{
  "type": "connected",
  "data": {
    "user": "1",
    "subscriptions": [1, 2]
  }
}

If server_id is omitted, subscriptions will be "all".

Server-Sent Event Types

All events follow this format:

{
  "type": "<event_type>",
  "server_id": 1,
  "data": { ... }
}

server_status

Emitted when a server's status changes (starting, running, stopping, stopped, crashed, error).

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

log

Emitted for each log line from the server process.

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

players

Emitted when the player list changes.

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

metrics

Periodic resource usage update.

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

Subscription Model

  • Each connection subscribes to zero or more server_id values.
  • Subscribing to server_id=None (omitting the parameter) means "all servers."
  • broadcast(server_id, message) delivers to all clients subscribed to that server_id plus all global subscribers.
  • If the event loop is closed, events are silently dropped.

Rate Limiting

Endpoint Limit
POST /auth/login 5 attempts per minute per IP
All other endpoints 60 requests per minute per token

Exceeded limits return 429 Too Many Requests.

Implemented via slowapi middleware.


Error Codes Reference

Code HTTP Status Description
UNAUTHORIZED 401 Missing or invalid token
FORBIDDEN 403 Insufficient role (admin required)
NOT_FOUND 404 Resource not found
NOT_SUPPORTED 400 Adapter lacks required capability
CONFLICT 409 Duplicate resource (e.g., username taken)
SERVER_ALREADY_RUNNING 409 Start called on running server
SERVER_NOT_RUNNING 409 Stop/command on stopped server
SERVER_NOT_STOPPED 409 Delete called on running server
PORT_IN_USE 409 Game or RCon port already occupied
CONFIG_VERSION_CONFLICT 409 Optimistic locking conflict on config update
VERSION_CONFLICT 409 Config modified by another request during mod update
GAME_TYPE_NOT_FOUND 404/400 No adapter registered for this game type
EXE_NOT_ALLOWED 400 Executable not in adapter allowlist
INVALID_CONFIG 422/400 Config validation failed (adapter-specific)
CONFIG_WRITE_ERROR 500 Config file write failed (disk, permissions)
NO_RCON_PASSWORD 400 RCon password not configured
RCON_ERROR 503 RCon connection or command failed
ADAPTER_ERROR 400/500 Generic adapter error
FILE_TOO_LARGE 413 Upload exceeds 500 MB
NO_FILENAME 400 No filename in upload request
VALIDATION_ERROR 400 General validation failure
INTERNAL_ERROR 500 Unexpected server error

Upcoming Endpoints (UX Enhancement Plan)

Endpoints planned during the Arma 3 UX Enhancement. = implemented.

Phase 1 — Config UI Schema

Method Path Auth Description
GET /servers/{server_id}/config/schema Bearer Returns widget hints per field for the frontend config editor

Phase 2 — Mission Rotation

Method Path Auth Description
GET /servers/{server_id}/missions/rotation Bearer Get current mission rotation list
PUT /servers/{server_id}/missions/rotation Admin Replace mission rotation (requires config_version for optimistic locking)

Phase 4 — Player Kick / Ban

Method Path Auth Description
POST /servers/{server_id}/players/{slot_id}/kick Admin Kick player by slot ID via RCon; requires reason in body
POST /servers/{server_id}/players/{slot_id}/ban Admin Ban player by slot ID via RCon + DB; requires reason and optional duration_minutes (null = permanent)

Phase 5 — Log File Browser

Method Path Auth Description
GET /servers/{server_id}/logfiles Bearer List historical .rpt log files with filename, size_bytes, modified_at
GET /servers/{server_id}/logfiles/{filename}/download Bearer Download a historical .rpt log file as text/plain
DELETE /servers/{server_id}/logfiles/{filename} Admin Delete a historical .rpt log file