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#
| Route | Access | Purpose |
|---|---|---|
POST /api/login | Public | Opens a session, sets the cookie |
POST /api/logout | Session | Revokes the session in the database and clears the cookie |
GET /api/status | status:read | Server status, cached |
GET /api/actions | Session | Catalogue filtered by role. ?locale=fr for custom command text |
POST /api/actions | Per action | Runs a catalogue action |
POST /api/rcon | rcon:raw | Raw console |
GET /api/audit | audit:read | Latest audit entries, ?limit= |
GET /api/metrics | status:read | Time series, ?range=1h|6h|24h|7d. 404 when metrics are off |
GET /api/health | Public | Liveness: the process is alive |
GET /api/ready | Public | Readiness: 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/statusRunning 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/actionsA 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/actionsError 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#
| Status | When |
|---|---|
400 | Malformed body, or input rejected by validation |
401 | No session, expired, revoked, or invalid signature |
403 | Insufficient permission, or foreign origin on a mutating request |
404 | Unknown action, or feature turned off (metrics) |
413 | Request body beyond 16 KiB |
429 | Rate limit reached; the Retry-After header is set |
500 | Invalid configuration, or internal error |
502 / 504 | Factorio unreachable, RCON authentication refused, or timeout |
503 | RCON queue full, or panel shutting down |
Validation codes#
| Code | Meaning |
|---|---|
validation_required | Required field left empty |
validation_player | Invalid player name |
validation_identifier | Invalid prototype name |
validation_number | A number was expected |
validation_min / validation_max | Outside the declared bounds |
validation_enum | Value outside the list |
validation_bool | A yes/no value was expected |
validation_too_long | Maximum length exceeded |
validation_newline | Line breaks are not allowed |
validation_control_char | Control characters are not allowed |
validation_comment | -- is not allowed in a value |