The recent log, then every new line as it happens (the control API's event stream), a header with the TPS, MSPT, players and RAM refreshed every second on a terminal (an ANSI scroll region; no TUI framework), and a command line whose lines run as console commands. Ctrl-D detaches and leaves the server running; when stdout isn't a terminal it prints plain lines. The admin e2e attaches through a pipe and runs two commands. Co-Authored-By: Claude Opus 5.5 <[email protected]>
5.5 KiB
Server API
What a host, a panel or a bot can do with a Horizon server: the horizon-server commands, server.toml and the
control API. How to host: hosting.md; the design: server.md.
Overview
horizon-server sets up a server folder, runs the game as a dedicated server under a supervisor (restarts on a crash,
backups on a schedule, updates with a rollback), and lets other programs manage it through a local HTTP API with a
token. The web panel uses that API, and so can a moderation bot: players, kick, ban and pardon (by name or
address), op and deop, the whitelist, and metrics as Prometheus text.
| Count | |
|---|---|
| Commands | 29 (init, run, start, stop, restart, status, cmd, logs, console, backup, backups, restore, service, panel, update, rollback, config, config set, import, op, deop, whitelist, players, kick, ban, pardon, ban-ip, pardon-ip, version) |
server.toml keys |
25 in 7 sections, plus [properties] for any other vanilla key |
| Control API endpoints | 28 under /api/v1 |
Guide
horizon-server initin an empty folder, thenhorizon-server start(hosting.md).- From a script:
horizon-server status --json,horizon-server cmd say hi,horizon-server backup. By hand:horizon-server consoleattaches to the running server (live log, status header, command line). - From a program: read
.horizon/api.json(address and token), thenGET /api/v1/statuswithAuthorization: Bearer <token>. A program that runs elsewhere or keeps its settings (a Discord bot) uses a fixed address and token:[api] bindand[api] tokeninserver.toml(hosting.md). - Moderate:
horizon-server players,horizon-server ban NAME [REASON], orPOST /api/v1/players/ban. An action runs vanilla's console command on the running game, so it kicks, logs and savesbanned-players.jsonexactly as an operator's/bandoes; the reply says whether anythingchangedand has the console's lines. - Monitor: point Prometheus (or any scraper that sends a bearer token) at
GET /api/v1/metrics/prometheus. - Watch:
GET /api/v1/eventswithAccept: text/event-streamstreams what happens as server-sent events: every log line (log), the supervisor'sphase, and the game's typedjoin,leave,kick,chatanddeathevents with the player's name and UUID (?types=chat,deathpicks some).Last-Event-ID(or?since=N) resumes after a reconnection; withoutAccept: text/event-streamit answers the events aftersinceas JSON.
Reference
server-reference.md, generated from horizon-server's source: the help text, every
server.toml key with its default and the server.properties key it writes, and every endpoint.
Examples
token=$(jq -r .token .horizon/api.json); address=$(jq -r .address .horizon/api.json)
curl -s -H "Authorization: Bearer $token" "http://$address/api/v1/status"
curl -s -H "Authorization: Bearer $token" -d '{"line": "list"}' "http://$address/api/v1/command"
curl -s -H "Authorization: Bearer $token" "http://$address/api/v1/players"
curl -s -H "Authorization: Bearer $token" -d '{"name": "Steve", "reason": "griefing"}' "http://$address/api/v1/players/ban"
# {"changed":true,"output":["Banned Steve: griefing"]}
curl -s -H "Authorization: Bearer $token" "http://$address/api/v1/metrics/prometheus"
curl -sN -H "Authorization: Bearer $token" -H "Accept: text/event-stream" "http://$address/api/v1/events?types=join,chat,death"
# id: 41
# event: chat
# data: {"id":41,"type":"chat","name":"Steve","uuid":"...","message":"hi","time":1793451234567}
curl -s -H "Authorization: Bearer $token" -X PATCH -d '{"changes": {"world.difficulty": "hard"}}' "http://$address/api/v1/config"
# {"applied":["world.difficulty"],"restart":[],"running":true,"saved":["world.difficulty"]}
curl -s -H "Authorization: Bearer $token" -o world.zip "http://$address/api/v1/backups/download?name=2026-10-31T12-00-00Z-manual.zip"
Stability
Stable (stability.md): the commands, server.toml's keys and /api/v1. A new key or endpoint is an
addition; a change to one starts /api/v2, served beside /api/v1.
Not there yet
- Players: positions in
players; editing the lists while the game is stopped through the API (the CLI'sop,deopandwhitelistalready do). - Metrics: entities and per-dimension counts in the Prometheus text.
- Backups: restore a single dimension.
- Mods on a dedicated server: list, turn on and off, and their settings, once native mods can be built for the server (mods.md, native-mods.md).
- An MCP server for the same endpoints, so a host's agent manages the server as it manages the game.
- Compatibility tests: golden replies per endpoint, and a
server.tomlfrom each release line.
Changelog
api::ROUTESlists the endpoints; the reference is generated from it./api/v1: status, metrics, logs, command, stop, restart, backups, restore, update, panel login.- Commands:
players,kick,ban,pardon,ban-ip,pardon-ip. /api/v1additions:players,players/{kick,ban,pardon,ban-ip,pardon-ip,op,deop},whitelist,whitelist/{add,remove},metrics/prometheus,GET/PATCH config,DELETE backups,GET backups/download;server.tomlgets[api](bind,token,allow_public);GET events(server-sent events, or JSON).