Docs menu

API reference

Server reference

Everything horizon-server offers a host or a tool: its commands, every server.toml key and the control API. How to host: hosting.md; the design: server.md; stability and versions: stability.md.

Commands

horizon-server help prints:

horizon-server: host a Horizon (Minecraft Java Edition 26.3) server

Usage: horizon-server [--dir DIR] <command>

  init        Set up a server here: the EULA, the world, the port, who may join (asks, or takes flags:
              --eula --world NAME --seed SEED --port N --whitelist/--no-whitelist --player NAME... --op NAME
              --offline --yes)
  run         Run the server in the foreground; type console commands, Ctrl-C stops it cleanly. It
              restarts the game if it crashes.
  start       Run the server in the background (its output goes to logs/supervisor.log)
  stop, restart
  status [--json]
              Up or not, TPS, MSPT, players, RAM and CPU
  cmd COMMAND...
              Run a console command on the running server and print what it answers
  logs [-f] [-n N]
              The last N lines of the log (default 50); -f follows it
  backup [NAME]
              Zip the world and the settings into backups/ (a running server saves first and stays up)
  backups [--json]
              List the backups
  restore BACKUP [--yes]
              Put a backup's world in place (the current one is kept in backups/); a running
              server restarts with it
  service install|uninstall|print [--system]
              Start the server at boot or login: a systemd unit on Linux (--system: for every user,
              with sudo), a launchd agent on macOS, a task at logon on Windows
  panel       A one-time login link for the web panel ([panel] in server.toml; 127.0.0.1:8130 by
              default)
  update [--check [--json]] [--version TAG] [--timeout SECONDS]
              Install the newest release (checked against GitHub's SHA-256), back up the world and
              restart on it; goes back by itself if the game isn't up within the timeout (300 s).
              --archive FILE --version NAME installs an archive you have
  rollback    Back to the release used before the update
  config [--json]
              The settings in server.toml
  config set KEY=VALUE... [--json]
              Change settings (for example world.difficulty=hard server.max_players=10), checked first;
              a running server takes the difficulty, default game mode and whitelist at once, the rest
              at its next start
  import FILE Write server.toml from a vanilla server.properties
  op NAME, deop NAME
  whitelist on|off|list, whitelist add|remove NAME
              Who may join (on the running server, or in the files when it is stopped)

  --dir DIR   The server folder (default: the current folder)

Settings live in server.toml; the server writes server.properties from it before every start.

server.toml

Horizon server settings (docs/server.md). The server writes them into server.properties before every start: edit this file, not that one. Unknown keys are refused. horizon-server init writes this file with these defaults; horizon-server config set SECTION.KEY=VALUE changes it.

[server]

KeyDefaultIn server.propertiesWhat it does
motd"A Minecraft Server"motdthe line under the server's name in the server list
port25565server-portthe port players connect to
bind""server-iplisten on every address, or only on this one (server-ip)
max_players20max-playershow many players can be online at once
online_modetrueonline-modecheck players' Minecraft accounts (false: anyone joins under any name)
whitelisttruewhite-listonly whitelisted players and operators can join
enforce_whitelistfalseenforce-whitelistkick online players taken off the whitelist
view_distance10view-distancechunks sent around each player
simulation_distance10simulation-distancechunks around each player where mobs, crops and redstone tick

[world]

KeyDefaultIn server.propertiesWhat it does
name"world"level-namethe world folder
seed""level-seedempty: a random seed on the first start
game_mode"survival"gamemodesurvival, creative, adventure or spectator
difficulty"easy"difficultypeaceful, easy, normal or hard
hardcorefalsehardcoreone life: a player who dies becomes a spectator

[properties]

Any other server.properties key, spelled as vanilla spells it, for example: spawn-protection = 16

[engine]

KeyDefaultIn server.propertiesWhat it does
path""the game program; empty: the one installed beside horizon-server
resources""the prepared game files; empty: resources/ here, else the usual places
restart_on_crashtruestart the game again when it crashes

[backups]

KeyDefaultIn server.propertiesWhat it does
every"6h"automatic backups while the server runs: 30m, 6h, 1d...; "0" turns them off
keep12automatic backups kept (backups made by hand are never deleted)

[updates]

KeyDefaultIn server.propertiesWhat it does
keep1other releases kept by updates, besides the one in use and the one rollback goes to

[panel]

KeyDefaultIn server.propertiesWhat it does
bind"127.0.0.1:8130"the web panel: this computer only, or a tailnet address (100.x); "" turns it off
allow_publicfalsetrue lets bind be any address; never put the panel on the open internet

Control API (/api/v1)

HTTP and JSON on 127.0.0.1. A running server writes its address and a random token to .horizon/api.json, readable only by its own user; every request sends Authorization: Bearer <token> and a Host that is that address. Errors answer {"error": "..."} with 400, 401, 403, 404, 405 or 409. The web panel uses the same routes with its session.

MethodPathTakesAnswersWhat it does
GET/api/v1/statusnothingphase, version, pid, uptime_seconds, engine_pid, engine_uptime_seconds, crashes, last_crash, sample (TPS, MSPT, players, RAM, CPU), updateHow the server does
GET/api/v1/metrics?since=T (seconds since 1970){"samples": [...]}: one a second, the last 10 minutesThe samples taken after T, for graphs
GET/api/v1/logs?since=N{"next": N, "lines": [...]}The log lines after the Nth (the last 2000 are kept)
POST/api/v1/command{"line": "<one command>"}the lines the command loggedRun a console command on the running game
POST/api/v1/stopnothing{"ok": true}Stop the game and the supervisor
POST/api/v1/restartnothing{"ok": true}Restart the game
GET/api/v1/backupsnothing{"backups": [{"name", "bytes"}]}List the backups
POST/api/v1/backups{"name": "..."} (optional){"name": "<file>"}Back up now (a running game saves first and stays up)
POST/api/v1/restore{"name": "<backup>"}{"name": "<backup>"}Restart the game with that backup's world (the current one is kept in backups/)
POST/api/v1/update{"tag": "...", "timeout": seconds} (both optional){"ok": true}; status says how it went (update)Restart on that installed release, or download the newest first; goes back if the game isn't up within the timeout
POST/api/v1/panel/loginnothing{"url": "..."}A one-time login link for the web panel (with the token only, not from the panel)

Edit this page on GitHub · Spotted something wrong? Open an issue or ask on Discord.

Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft.