Compatibility
Minecraft: Java Edition
Platforms
Tags
Creators
Details
DevelopmentAPI
A Paper plugin that exposes a small HTTP/JSON API so you can drive your
Minecraft server from external tooling: inspect the server, manage
online players, tail the log, and read/write config files in a
sandboxed folder. Ships with a web console at /.
Setup
-
Drop
DevelopmentAPI-1.0.0.jarinto your server'splugins/folder and start the server. -
Open
plugins/DevelopmentAPI/config.yml. On first launch a random bearer token is generated and written into it — copy that value. -
Every HTTP request must include the header:
Authorization: Bearer <token>
Configuration
plugins/DevelopmentAPI/config.yml:
server:
host: "127.0.0.1" # bind address; 0.0.0.0 to expose externally
port: 8080
token: "" # leave blank on first launch — one is generated
security:
target-plugin-folder: "Development"
allowed-extensions:
- yml
- yaml
- json
- txt
commands:
reload: "develop reload"
Reload the config from in-game with /devapi reload.
In-game commands
| Command | Description |
|---|---|
/devapi status |
Show listener state |
/devapi reload |
Reload config.yml and restart listener |
/devapi token |
Print current bearer token (op-only) |
HTTP endpoints
All endpoints require Authorization: Bearer <token>.
| Method | Path | Description |
|---|---|---|
| GET | /api/health |
Liveness probe |
| GET | /api/info |
Plugin version, target folder, action list |
| POST | /api/action |
Dispatch a JSON action (see below) |
| GET | / |
Web console UI |
POST /api/action takes a JSON object with an "action" field. All
responses are JSON with "ok": true|false and either the action-
specific payload or an "error" string.
File actions
Paths are relative to the configured target-plugin-folder (default
plugins/Development/). Path traversal is rejected; readable/writable
files must match allowed-extensions.
| Action | Body |
|---|---|
read_file |
{ "path": "foo.yml" } |
write_file |
{ "path": "foo.yml", "content": "...", "reload": false } |
list_files |
{ "path": "subdir" } (path optional) |
delete_file |
{ "path": "foo.yml" } |
mkdir |
{ "path": "new/subdir" } |
move_file |
{ "from": "a.yml", "to": "b.yml", "overwrite": false } |
stat_file |
{ "path": "foo.yml", "hash": true } (hash optional) |
Command actions
| Action | Body |
|---|---|
run_command |
{ "command": "say hello" } |
run_commands |
{ "commands": ["save-all", "tps"] } |
reload |
{} — dispatches the configured reload command |
Server introspection
| Action | Returns |
|---|---|
server_info |
version, MOTD, TPS, view/sim distance, memory, port/ip |
players |
online players with UUID, gamemode, health, food, level, ping, world, location |
plugins |
installed plugins with version, enabled state, authors |
worlds |
per-world time, weather, difficulty, PVP, seed, spawn, chunks |
Player actions
| Action | Body |
|---|---|
broadcast |
{ "message": "server restarting in 5m" } |
message |
{ "player": "Notch", "message": "hi" } |
kick |
{ "player": "Notch", "reason": "afk" } (reason optional) |
teleport |
{ "player": "Notch", "x": 0, "y": 100, "z": 0, "world": "world" } (world/yaw/pitch optional) |
Log
| Action | Body |
|---|---|
tail_log |
{ "lines": 200 } — reads server/logs/latest.log (max 2000 lines) |
Examples
TOKEN="paste-from-config.yml"
# Server metadata
curl -s http://127.0.0.1:8080/api/info \
-H "Authorization: Bearer $TOKEN" | jq
# Live TPS, memory, MOTD, view distance…
curl -s -X POST http://127.0.0.1:8080/api/action \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"server_info"}' | jq
# Broadcast a message
curl -s -X POST http://127.0.0.1:8080/api/action \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"broadcast","message":"hello from curl"}'
# Teleport a player
curl -s -X POST http://127.0.0.1:8080/api/action \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"teleport","player":"Notch","x":0,"y":100,"z":0}'
# Tail the last 50 log lines
curl -s -X POST http://127.0.0.1:8080/api/action \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"tail_log","lines":50}' | jq
Web console
Visit http://<host>:<port>/ in a browser. Paste the bearer token to
unlock. The console has a command panel with quick presets and a file
browser/editor scoped to the target plugin folder.
Security notes
- Bind to
127.0.0.1unless you know what you're doing. If you expose the listener externally, put it behind a reverse proxy with TLS. - The bearer token is the only auth. Rotate it in
config.ymland run/devapi reload. - File operations are sandboxed to the configured target folder and an
extension allowlist.
tail_logis the one exception — it reads the server'slogs/latest.logand only that. - Commands are dispatched as the console sender, so they run with full permissions. Treat the token like a root credential.


