Factorio Admin RCON Source code

HTTP API

The routes the panel exposes, their access control and the shape of their errors.

Every route lives under /api, answers JSON and authenticates with the session cookie. They are usable from curl: a request with no Origin header is accepted, since it did not come from a browser and therefore cannot be a CSRF attack.

Routes#

RouteAccessPurpose
POST /api/loginPublicOpens a session, sets the cookie
POST /api/logoutSessionRevokes the session in the database and clears the cookie
GET /api/statusstatus:readServer status, cached
GET /api/actionsSessionCatalogue filtered by role. ?locale=fr for custom command text
POST /api/actionsPer actionRuns a catalogue action
POST /api/rconrcon:rawRaw console
GET /api/auditaudit:readLatest audit entries, ?limit=
GET /api/metricsstatus:readTime series, ?range=1h|6h|24h|7d. 404 when metrics are off
GET /api/healthPublicLiveness: the process is alive
GET /api/readyPublicReadiness: configuration, command catalogue, database and RCON

Signing in#

curl -sc cookies.txt \
  -H 'Content-Type: application/json' \
  -d '{"password":"your-admin-password"}' \
  http://127.0.0.1:3010/api/login
# {"ok":true,"username":"admin","role":"admin"}

curl -sb cookies.txt http://127.0.0.1:3010/api/status

Running an action#

The body only carries an id and values. The server builds the command.

curl -sb cookies.txt \
  -H 'Content-Type: application/json' \
  -d '{"action":"kick","values":{"player":"bob","reason":"spam"}}' \
  http://127.0.0.1:3010/api/actions

A custom command is called by its prefixed id:

curl -sb cookies.txt \
  -H 'Content-Type: application/json' \
  -d '{"action":"custom:kill-enemies","values":{"player":"Edwins"}}' \
  http://127.0.0.1:3010/api/actions

Error format#

An error always carries the same envelope. code is the translation key and is authoritative for the interface; error is only an English fallback, readable for whoever calls the API from a shell.

{
  "ok": false,
  "error": "player: invalid player name (no spaces or quotes, 60 max).",
  "code": "validation_player",
  "params": { "field": "player" }
}

HTTP statuses#

StatusWhen
400Malformed body, or input rejected by validation
401No session, expired, revoked, or invalid signature
403Insufficient permission, or foreign origin on a mutating request
404Unknown action, or feature turned off (metrics)
413Request body beyond 16 KiB
429Rate limit reached; the Retry-After header is set
500Invalid configuration, or internal error
502 / 504Factorio unreachable, RCON authentication refused, or timeout
503RCON queue full, or panel shutting down

Validation codes#

CodeMeaning
validation_requiredRequired field left empty
validation_playerInvalid player name
validation_identifierInvalid prototype name
validation_numberA number was expected
validation_min / validation_maxOutside the declared bounds
validation_enumValue outside the list
validation_boolA yes/no value was expected
validation_too_longMaximum length exceeded
validation_newlineLine breaks are not allowed
validation_control_charControl characters are not allowed
validation_comment-- is not allowed in a value