Skip to main content

Bots

Per-bot REST routes. The :id segment maps to the dispatcher's id argument — same identifier shown in the dashboard's bot list (bot-1, bot-2, …).

MethodPathBody
GET/api/bots
GET/api/bots/{id}
POST/api/bots/{id}/connect
POST/api/bots/{id}/reconnect— — alias of connect
POST/api/bots/{id}/disconnect
POST/api/bots/{id}/warp{world}
POST/api/bots/{id}/leave
POST/api/bots/{id}/walk_to{x, y}
GET/api/bots/{id}/collectables
GET/api/bots/{id}/enemies
GET/api/bots/{id}/minimap
GET/api/bots/{id}/recent_worlds?timeout_ms (opt) — server reply with the bot's last visited worlds
GET/api/bots/{id}/active_worlds?timeout_ms (opt) — list of currently-populated worlds
GET/api/bots/{id}/world_info?world&timeout_ms — single-world player count + flags
POST/api/bots/{id}/tutorial

All endpoints require the bearer header. Responses share the {"error": "..."} envelope on failure.

GET /api/bots

List all spawned bots with a lite snapshot (no inventory contents, no full world tile grid) so the response stays under a few KB.

Response (200):

{
"bots": [
{
"id": "bot-1",
"status": "in_world",
"device_id": "ae7b7219cfb72594",
"current_host": "game-lava.pixelworlds.pw",
"current_port": 10001,
"current_world": "MINEWORLD",
"pending_world": null,
"username": "P71710199",
"user_id": "69fd4201a4fa2bc68c51dc27",
"player_position": { "map_x": 42.0, "map_y": 18.0,
"world_x": 13.44, "world_y": 5.76 },
"inventory_count": 18,
"gems": 1250,
"byte_coins": 180,
"xp_amount": 420,
"experience": 1200,
"xp_level": 3,
"slots": 32,
"tutorial_state": 7,
"tutorial_running": false,
"ping_ms": 47,
"proxy_name": null,
"proxy_kind": null,
"connected_since": 1778205616123,
"fishing_active": false,
"fishing_info": null,
"last_error": null
}
]
}

status is one of: connecting, authenticating, menu_ready, joining_world, loading_world, awaiting_ready, in_world, redirecting, reconnecting, disconnected, already_connected, banned, kicked, error.

GET /api/bots/{id}

Full snapshot for a single bot, including the inventory list and world tile counts.

Response (200): every field from the list snapshot above, plus:

{
"world": {
"world_name": "MINEWORLD",
"width": 100,
"height": 60,
"spawn_map_x": 50.0,
"spawn_map_y": 30.0,
"spawn_world_x": 16.0,
"spawn_world_y": 9.6,
"collectables_count": 12,
"world_items_count": 48,
"tile_counts": [
{ "tile_id": 8, "count": 412 },
{ "tile_id": 14, "count": 96 }
]
},
"inventory": [
{
"block_id": 1041,
"inventory_type": 49,
"amount": 1,
"name": "WeaponPickaxeBasic",
"category": "tool"
}
],
"tutorial_stage": null,
"sf_token": "<JWT>"
}

POST /api/bots/{id}/connect

Resume a previously-created bot. Re-runs the auth chain (PlayFab + sclfrst), then opens the TCP socket.

Response (200):

{ "ok": true }

Errors (200, body): if the auth fails Seraph still returns 200 but with the failure surfaced in the bot snapshot — poll GET /api/bots/{id} and read status + last_error. Truly fatal failures (bad credentials, license invalid) come back as 500 with the verbatim error string.

POST /api/bots/{id}/disconnect

Drop the TCP socket cleanly. Sends DD to the server first so the session ledger releases the slot.

Response (200): { "ok": true }

POST /api/bots/{id}/warp

Join the named world. Same wire burst the real client emits (MWliTTjWGw + ActionEvents + GSb + ST). OoIP redirects are followed automatically.

Body:

{ "world": "MINEWORLD" }

Response (200): { "ok": true } — the bot transitions through joining_worldloading_worldawaiting_readyin_world. Watch the event stream or poll the snapshot to know when it's settled.

POST /api/bots/{id}/leave

Send LW (LeaveWorld) and return to menu_ready status.

Response (200): { "ok": true }

POST /api/bots/{id}/walk_to

Plan a path through the current world's tile graph and walk to the target tile. Emits mp + mP movement bursts; waits for the server's position-update echo before returning.

Body:

{ "x": 42, "y": 18 }

Response (200): { "ok": true }

GET /api/bots/{id}/collectables

Live list of dropped items in the bot's render range.

Response (200):

{
"collectables": [
{
"id": 12,
"block_type": 1041,
"amount": 1,
"inventory_type": 49,
"pos_x": 13.44,
"pos_y": 5.76,
"is_gem": false
}
]
}

GET /api/bots/{id}/enemies

AI / mob entities visible to the bot.

Response (200):

{
"enemies": [
{
"ai_id": 17,
"x": 41,
"y": 28,
"ai_kind": "Spider",
"hp": 80,
"max_hp": 100
}
]
}

GET /api/bots/{id}/minimap

Compact representation of the world's foreground / background / water / wiring layers — every tile id as a flat array of length width * height. Useful for rendering an overlay or feeding a pathfinder.

Response (200):

{
"width": 100,
"height": 60,
"foreground_tiles": [0, 0, 8, 14, 0, ...],
"background_tiles": [0, 0, 0, 0, 12, ...],
"water_tiles": [0, 0, 0, ...],
"wiring_tiles": [0, 0, 0, ...],
"player_position": { "map_x": 42.0, "map_y": 18.0,
"world_x": 13.44, "world_y": 5.76 },
"other_players": [
{
"user_id": "69fd4201a4fa2bc68c51dc27",
"nick": "Devastres22",
"position": { "map_x": 50.0, "map_y": 30.0,
"world_x": 16.0, "world_y": 9.6 }
}
]
}

POST /api/bots/{id}/tutorial

Kick off the canonical Rust tutorial automation flow (TUTORIAL2 join → CharC → spawn pods → exit to PIXELSTATION). Use this on a freshly- minted account to land it in the post-tutorial world without writing any Lua glue.

Response (200): { "ok": true } — the bot's tutorial_running flag flips to true. Watch tutorial_stage on the snapshot for human-readable progress ("character creation", "spawn pod walk", …).