Skip to content

Latest commit

 

History

History
218 lines (174 loc) · 8.14 KB

File metadata and controls

218 lines (174 loc) · 8.14 KB

API reference

mcpd exposes one REST surface, used by two kinds of caller.

  • The Plesk extension authenticates with the master token from /etc/plesk-minecraft/config.json and adds X-Mcpd-Actor and X-Mcpd-Client-Id headers so the daemon can scope and audit the request. The browser never sees this token: it calls the panel, and ApiController proxies.
  • External clients authenticate with a token created in Settings → REST API tokens. These are Exaroton-style: scoped, optionally pinned to one server, and stored only as a SHA-256 hash.

Authentication

Authorization: Bearer <token>

X-Api-Token: <token> is accepted as an alternative. Everything except GET /api/v1/health requires a token.

Scopes

Scopes are cumulative — each one implies the ones before it.

Scope Grants
read list servers, read status, players, metrics, catalogues
console plus read the console and send commands
control plus start, stop, restart, kill, edit settings
files plus the file manager, backups and content installs
admin plus create and delete servers, tokens and daemon settings

A token with a server_id may only touch that server. A token with a non-zero client_id sees only the servers owned by, or shared with, that Plesk client.

Errors

Errors are JSON with an error key and a meaningful status: 400 malformed input, 401 bad token, 403 scope or ownership, 404 unknown route or server, 409 the server is in the wrong state (for example editing a port while running), 502 an upstream catalogue failed.

Console

Two ways to follow a console, because they suit different callers.

Polling — what the panel uses, since Plesk's nginx buffers streamed responses:

GET /api/v1/servers/{id}/console?since=<cursor>&wait=1

Returns {"lines": [{"seq", "ts", "line"}], "cursor": N, "state": "..."}. Pass the returned cursor as the next since. since=-1 returns the tail. A cursor older than the retained window is fast-forwarded rather than returning nothing, so a client that fell behind resumes cleanly. wait=1 long-polls for up to 20 seconds.

WebSocket — for external clients:

GET /api/v1/servers/{id}/console/ws     (Upgrade: websocket)

The server sends {"type":"hello"|"console"|"state"|"players", ...} frames. Send {"type":"command","command":"say hi"} to run a command (needs the console scope).

Endpoints

Server-wide

Method Path Scope
GET /api/v1/info read
GET /api/v1/settings admin
PUT /api/v1/settings admin
GET /api/v1/audit admin

Catalogues

Method Path Scope
GET /api/v1/loaders read
GET /api/v1/loaders/{loader}/versions read
GET /api/v1/loaders/{loader}/versions/{version}/builds read
GET /api/v1/java read
POST /api/v1/java/{major} admin
DELETE /api/v1/java/{major} admin
GET /api/v1/properties/schema read
GET /api/v1/content/sources read
GET /api/v1/content/search read
GET /api/v1/content/{source}/{project} read
GET /api/v1/content/{source}/{project}/versions read

API tokens

Method Path Scope
GET /api/v1/tokens admin
POST /api/v1/tokens admin
DELETE /api/v1/tokens/{token_id} admin

Servers

Method Path Scope
GET /api/v1/servers read
POST /api/v1/servers admin

Server operations

Method Path Scope
GET /api/v1/servers/{sid} read
PATCH /api/v1/servers/{sid} admin
DELETE /api/v1/servers/{sid} admin
POST /api/v1/servers/{sid}/start control
POST /api/v1/servers/{sid}/stop control
POST /api/v1/servers/{sid}/restart control
POST /api/v1/servers/{sid}/kill control
POST /api/v1/servers/{sid}/command console
POST /api/v1/servers/{sid}/install admin
POST /api/v1/servers/{sid}/eula control
GET /api/v1/servers/{sid}/console console
GET /api/v1/servers/{sid}/console/ws console
GET /api/v1/servers/{sid}/status read
GET /api/v1/servers/{sid}/metrics read
GET /api/v1/servers/{sid}/properties read
PUT /api/v1/servers/{sid}/properties control
GET /api/v1/servers/{sid}/access admin
PUT /api/v1/servers/{sid}/access admin
GET /api/v1/servers/{sid}/notifications admin
PUT /api/v1/servers/{sid}/notifications admin
POST /api/v1/servers/{sid}/notifications/test admin
GET /api/v1/servers/{sid}/players read
POST /api/v1/servers/{sid}/players/{action} control
GET /api/v1/servers/{sid}/worlds read
POST /api/v1/servers/{sid}/worlds/activate control
POST /api/v1/servers/{sid}/worlds/reset control
POST /api/v1/servers/{sid}/worlds/import files
GET /api/v1/servers/{sid}/worlds/export files
DELETE /api/v1/servers/{sid}/worlds/{world} admin
GET /api/v1/servers/{sid}/files files
GET /api/v1/servers/{sid}/files/read files
GET /api/v1/servers/{sid}/files/download files
POST /api/v1/servers/{sid}/files/write files
POST /api/v1/servers/{sid}/files/upload files
POST /api/v1/servers/{sid}/files/mkdir files
POST /api/v1/servers/{sid}/files/rename files
POST /api/v1/servers/{sid}/files/move files
POST /api/v1/servers/{sid}/files/copy files
POST /api/v1/servers/{sid}/files/compress files
POST /api/v1/servers/{sid}/files/extract files
POST /api/v1/servers/{sid}/files/chmod files
DELETE /api/v1/servers/{sid}/files files
GET /api/v1/servers/{sid}/backups read
POST /api/v1/servers/{sid}/backups files
GET /api/v1/servers/{sid}/backups/{bid}/download files
POST /api/v1/servers/{sid}/backups/{bid}/restore admin
DELETE /api/v1/servers/{sid}/backups/{bid} files
GET /api/v1/servers/{sid}/schedules read
POST /api/v1/servers/{sid}/schedules admin
PATCH /api/v1/servers/{sid}/schedules/{schid} admin
DELETE /api/v1/servers/{sid}/schedules/{schid} admin
GET /api/v1/servers/{sid}/content read
POST /api/v1/servers/{sid}/content files
GET /api/v1/servers/{sid}/content/updates read
DELETE /api/v1/servers/{sid}/content/{cid} files

75 endpoints total.

Examples

Create a server and follow the install:

TOKEN=...   # from Settings -> REST API tokens
API=https://your-host:8720/api/v1

curl -s -X POST "$API/servers" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"Survival","loader":"paper","mc_version":"1.21.8",
       "memory_mb":4096,"sleep_enabled":true,"eula_accepted":true}'

curl -s "$API/servers/<id>/console?since=-1" -H "Authorization: Bearer $TOKEN"

Start it and wait for it to come up:

curl -s -X POST "$API/servers/<id>/start" -H "Authorization: Bearer $TOKEN"
until [ "$(curl -s "$API/servers/<id>" -H "Authorization: Bearer $TOKEN" \
          | python3 -c 'import json,sys;print(json.load(sys.stdin)["state"])')" = running ]; do
  sleep 5
done

Install a plugin from Modrinth:

curl -s -X POST "$API/servers/<id>/content" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"source":"modrinth","project":"chunky","kind":"plugin"}'

Upload a file (raw body, path in the query string):

curl -s -X POST "$API/servers/<id>/files/upload?path=plugins/config.yml" \
  -H "Authorization: Bearer $TOKEN" --data-binary @config.yml

Enabling the public listener

The daemon binds 127.0.0.1 only by default. To let external clients in, turn on Expose the REST API on a public port in the extension settings, choose a port, open it in the firewall, and restart plesk-minecraftd. Put it behind TLS — the daemon speaks plain HTTP and is designed to sit behind the panel or a reverse proxy.