Repository navigation
WebSocket
The live feed: subscribe once, get a snapshot of the current state, then every change. It's one endpoint, /api/v1/ws.
Connect to wss://<your-domain>/worldapi/api/v1/ws, or ws://localhost:8110/api/v1/ws on the server itself. Send the token in the Authorization header, or as the first message if your client can't set headers. Never put it in the URL. Visitors without a token may subscribe to the topics in websocket.anonymousTopics.
{ "op": "auth", "token": "…" }
{ "op": "subscribe", "topics": ["player.join", "player.death", "world.time"], "filter": { "player": "Steve" } }
{ "op": "unsubscribe", "topics": ["world.time"] }
{ "op": "ping" }The server answers with hello (the heartbeat interval, your permissions, and the topics you may use), authenticated, subscribed, then a snapshot of the current state for topics that have one, then event messages as things happen. heartbeat arrives every 20 seconds.
{ "op": "event", "topic": "player.death", "event": {
"type": "player.death", "at": "2026-10-11T15:46:27Z", "atMillis": 1791733587000,
"player": { "uuid": "…", "name": "Steve" }, "world": "world",
"data": { "message": "Steve was slain by Zombie", "cause": "minecraft:mob_attack", "level": 12 } } }In the browser:
const ws = new WebSocket("wss://mc.example.com/worldapi/api/v1/ws");
ws.onopen = () => ws.send(JSON.stringify({ op: "subscribe", topics: ["player.join", "player.death"] }));
ws.onmessage = (message) => {
const data = JSON.parse(message.data);
if (data.op === "event") console.log(data.topic, data.event.player?.name, data.event.data);
};| Topic | When |
|---|---|
player.join, player.leave, player.kick
|
Someone joins, leaves, or gets kicked. Snapshot: who's online |
player.death, player.respawn
|
Deaths with the message, cause, and killer; respawns with the bed or anchor |
player.advancement |
An advancement with its title and frame (task, goal, challenge) |
player.chat |
Chat messages, only when events.chat is on; chat:read only |
player.command |
Commands players run; logs:read only |
player.move |
Positions, at most once a second per player, only when they moved. Hidden from visitors by default |
player.health, player.damage
|
Health with its maximum, food, absorption, active effects, and whether the player is frozen, when any of them change; damage with its cause, at most four a second |
player.inventory |
The full inventory when it changes |
player.gamemode, player.level_up, player.sleep, player.world_change, player.portal
|
What the names say |
player.kill, player.fish, player.enchant, player.trade, player.craft
|
Mob kills, catches, enchanting, villager trades, and crafting (added up over a few seconds) |
world.time |
The clock once a second, with ticks until night, whether beds work, and jumped: true after a skipped night or a /time command |
world.weather, world.lightning, world.night_skipped
|
Weather changes, strikes, and nights everyone slept through |
world.load, world.unload
|
Worlds coming and going |
entity.boss_killed |
The dragon, the wither, elder guardians, and wardens, with who was there |
entity.death, entity.explode
|
Mob deaths per type over a few seconds; explosions with their size |
raid.start, raid.finish
|
Raids, with the winners |
block.break, block.place
|
Blocks per player and type, added up over websocket.blockWindowSeconds
|
server.performance |
TPS, tick times, memory, and CPU every five seconds |
server.status, server.plugin
|
Start, stop, saves; plugins enabled and disabled |
server.console |
Console lines as they're printed, colors stripped and tokens blanked; logs:read only |
script.log |
Lines Java scripts log; code only |
ext.<namespace>.<event> |
Other plugins' events (see Extensions) |
Joins, leaves, kicks, deaths, advancements, chat, skipped nights, boss kills, raids, and server status also go to the history behind GET /events.
Events about a vanished player, and their state in snapshots, reach clients with players:moderate only. Counts inside events (online in player.join, player.leave, and server.status; sleepers in player.sleep and world.night_skipped; players per world in server.performance) leave vanished players out for everyone.
Each client has its own queue. State topics (time, weather, positions, health, inventories, performance) keep only the newest value per player or world, so a slow client catches up instead of lagging behind. Other events queue up to websocket.queueSize; past that, the oldest are dropped and the client gets { "op": "dropped", "count": n }. A slow client never holds up the server or anyone else.
Next: Extensions.