Skip to content

Game host API

The part of the panel’s API that integrations use: read and write a server’s files, send commands, follow the console live, and power the server.

Every endpoint with its parameters: the API reference, generated from the panel’s OpenAPI document. Each panel also serves it at /openapi/v1.json, browsable at /api/docs.

  • Authenticate with an API token: Authorization: Bearer ….
  • All server paths start with /api/v1/tenants/{tenantId}/servers/{serverId}.
  • Errors are application/problem+json with a stable code.
Method and path Permission Notes
GET (the path itself) server.view state: installing · installFailed · offline · starting · running · stopping. allocations[] has role (game, query, rcon…), ip, port, protocol, address. stats has CPU, memory, disk, uptime. permissions[] is what the caller may do.
POST /power { "action": "start" } power.<action> start, stop, restart, kill. 409 invalid_state while installing.
POST /command { "command": "say hi" } console.write 409 invalid_state when the server isn’t running.
POST /rcon { "command": "list" } console.write Returns { "response": "…" }, for games with RCON.
GET /console/stream console.read Server-Sent Events, see below.
GET /console/log console.read The whole console log as a file.
GET /metrics?range=1h monitor.view One-minute averages; 1h, 6h, 24h or 7d.
GET /files?path=/config files.list Only entries the caller may access are listed.
GET /files/content?path=whitelist.txt files.read Up to 4 MiB, for editing. ETag: "<sha256>", X-File-Size, X-File-Truncated.
GET /files/download?path=world.zip files.read Any size, streamed.
GET /files/archive?path=/world files.list A folder as zip, with the files the caller may read. names= (repeatable) picks entries of the folder.
PUT /files/content?path=whitelist.txt files.write The body is the new content. Conditions below. Large files in parts: &offset=<position>&final=false, the last part with final=true.
DELETE /files?path=… files.delete
POST /files/delete { "paths": [] } files.delete per path Returns { "done", "failed": [{ "path", "error" }] }.
POST /files/move { "paths": [], "to": "/old" } files.write on both paths Same answer as delete.
POST /files/rename { "from", "to" } files.write on both paths
POST /files/directory { "path" } files.write
Status code
400 invalid_action, variable_invalid, range_invalid
401 missing, invalid, revoked or expired token, or wrong network
403 forbidden (the server exists for you, but this action or path isn’t allowed), token_not_allowed
404 server unknown, or no permission on it at all
409 node_offline (the node’s agent isn’t connected), invalid_state
412 precondition_failed

For files an integration manages, such as a whitelist, so it never overwrites someone else’s edit:

1. GET …/files/content?path=whitelist.txt → body + ETag "abc…"
2. compute the new content
3. PUT …/files/content?path=whitelist.txt If-Match: "abc…"
4. on 412: someone edited the file in between → go back to 1

If-None-Match: * writes only if the file doesn’t exist yet.

GET …/console/stream sends text/event-stream:

event: state
data: {"state":"running"}
event: console
data: {"lines":["[12:00:01] Done (3.9s)!"],"history":true}
event: console
data: {"lines":["<Steve> hello"]}
: keep-alive
  • On connect: the current state, then recent history (marked "history": true), then live events.
  • Keep-alive: a comment every 15 seconds.
  • Reconnect when the connection drops. History is sent again, so de-duplicate if your use case needs it.
  • Behind nginx: the panel sends X-Accel-Buffering: no.