MMoriDocs
API Reference

HTTP API

REST endpoints for managing Mori setup

HTTP API

All endpoints return application/json.

Most endpoints are protected by authentication except for the frontend static files and /auth/* endpoints. Protected API endpoints require an Authorization: Bearer <token> header. The application is meant for a single user. Credentials are saved locally to user.json.


GET /auth/status

Check whether the master password has been configured yet.

Response

{ "registered": true }

POST /auth/setup

Registers the master password for the application. This can only be done once.

Request Body

{ "password": "your_secure_password" }

Response

StatusMeaning
204Setup successful
409Already registered

POST /auth/login

Returns a session token valid until the server restarts or the user logs out.

Request Body

{ "password": "your_secure_password" }

Response

{ "token": "uuid-v4-token" }

POST /auth/logout

Invalidates the current session token.

Response

StatusMeaning
204Logged out

GET /

Serves the HTML dashboard.


GET /bots

Returns a summary list of all running bots.

Response

[
  {
    "id": 1,
    "username": "string",
    "status": "in_game",
    "world": "string",
    "pos_x": 0.0,
    "pos_y": 0.0,
    "gems": 0,
    "ping_ms": 0
  }
]

POST /bots

Spawns a new bot.

Request Body

{
  "username": "string",
  "password": "string",
  "proxy_host": "string",
  "proxy_port": 1080,
  "proxy_username": "string",
  "proxy_password": "string"
}

proxy_host and proxy_port are required together to enable SOCKS5 proxy. Username/password are optional.

Response

{ "id": 1 }

POST /bots/ltoken

Spawns a new bot using a pre-existing ltoken instead of username/password. The token is validated immediately — if it fails the bot stops without retrying.

Request Body

{
  "ltoken": "token|rid|mac|wk",
  "proxy_host": "string",
  "proxy_port": 1080,
  "proxy_username": "string",
  "proxy_password": "string"
}

ltoken is a |-separated string of four fields: the refresh token, a 32-char hex RID, a MAC address (XX:XX:XX:XX:XX:XX), and a 32-char hex WK.

proxy_host and proxy_port are required together to enable SOCKS5 proxy. Username/password are optional.

Response

{ "id": 1 }

DELETE /bots/{id}

Stops and removes a bot.

StatusMeaning
204Stopped successfully
404Bot not found

GET /bots/{id}/state

Returns the full state of a bot.

Response

{
  "status": "in_game",
  "world_name": "string",
  "pos_x": 0.0,
  "pos_y": 0.0,
  "world_width": 100,
  "world_height": 60,
  "tiles": [
    {
      "fg_item_id": 0,
      "bg_item_id": 0,
      "flags": 0,
      "tile_type": { "type": "Basic" }
    }
  ],
  "players": [
    {
      "net_id": 0,
      "name": "string",
      "pos_x": 0.0,
      "pos_y": 0.0,
      "country": "us"
    }
  ],
  "objects": [
    {
      "uid": 0,
      "item_id": 0,
      "x": 0.0,
      "y": 0.0,
      "count": 1
    }
  ],
  "inventory": [
    {
      "item_id": 0,
      "amount": 0,
      "is_active": false,
      "action_type": 0
    }
  ],
  "inventory_size": 18,
  "gems": 0,
  "console": ["string"],
  "ping_ms": 0,
  "delays": {
    "place_ms": 500,
    "walk_ms": 500,
    "twofa_secs": 120,
    "server_overload_secs": 30,
    "too_many_logins_secs": 5,
    "maintenance_secs": 600
  },
  "track_info": {
    "level": 0,
    "grow_id": 0,
    "install_date": 0,
    "global_playtime": 0,
    "awesomeness": 0
  },
  "auto_collect": true,
  "auto_reconnect": true
}

track_info is null until the server sends account data after login.

StatusMeaning
200OK
404Bot not found

POST /bots/{id}/cmd

Sends a command to a bot.

StatusMeaning
204Command sent
404Bot not found

All commands use a tagged union with a "type" field.

move

Move the bot to a pixel position.

{ "type": "move", "x": 0.0, "y": 0.0 }

walk_to

Pathfind to a tile position.

{ "type": "walk_to", "x": 0, "y": 0 }

run_script

Run a Lua script on the bot.

{ "type": "run_script", "content": "string" }

stop_script

Stop the currently running script.

{ "type": "stop_script" }

wear

Equip an item.

{ "type": "wear", "item_id": 0 }

unwear

Unequip an item.

{ "type": "unwear", "item_id": 0 }

drop

Drop items into the world.

{ "type": "drop", "item_id": 0, "count": 1 }

trash

Permanently delete items.

{ "type": "trash", "item_id": 0, "count": 1 }

set_delays

Configure action delays. place_ms and walk_ms are in milliseconds; the *_secs fields control how long the bot waits before reconnecting after each login failure type.

{
  "type": "set_delays",
  "place_ms": 500,
  "walk_ms": 500,
  "twofa_secs": 120,
  "server_overload_secs": 30,
  "too_many_logins_secs": 5,
  "maintenance_secs": 600
}

set_auto_collect

Enable or disable automatic collection of nearby dropped items.

{ "type": "set_auto_collect", "enabled": true }

set_auto_reconnect

Enable or disable automatic reconnection after a disconnect.

{ "type": "set_auto_reconnect", "enabled": true }

disconnect

Disconnect the bot from the current server. If auto-reconnect is enabled, the bot will reconnect automatically.

{ "type": "disconnect" }

reconnect

Force a reconnect. If the bot is currently connected, it disconnects first and reconnects via the normal disconnect handler. If already disconnected, reconnects immediately.

{ "type": "reconnect" }

accept_access

Accept a world lock access request from the nearest player. Wrenches the player and confirms both dialogs in sequence.

{ "type": "accept_access" }

warp

Warp the bot to a world by name. id is the door ID to enter through and defaults to an empty string (main door).

{ "type": "warp", "name": "START", "id": "" }

GET /growtopia-cdn/{*path}

Proxies a request to https://growserver-cache.netlify.app/{path} and returns the response body with the original content-type header.

Example

GET /growtopia-cdn/growtopia/game/fire.rttex
→ proxied to https://growserver-cache.netlify.app/growtopia/game/fire.rttex
StatusMeaning
200Response from upstream
502Upstream request failed or body could not be read

POST /proxy/test

Tests a SOCKS5 proxy against three checks and returns the result of each.

All checks use the same proxy credentials. Each check is independent — a failed earlier check does not block later ones, except check 3 which requires a server address from check 2.

Request Body

{
  "proxy_host": "103.160.95.181",
  "proxy_port": 1080,
  "proxy_username": "string",
  "proxy_password": "string"
}

proxy_username and proxy_password are optional.

Response

{
  "socks5": {
    "ok": true,
    "error": null,
    "detail": null
  },
  "server_data": {
    "ok": true,
    "error": null,
    "detail": "1.2.3.4:17091"
  },
  "enet": {
    "ok": true,
    "error": null,
    "detail": null
  }
}

Each check object has:

FieldTypeDescription
okboolWhether the check passed
errorstring | nullError message if ok is false
detailstring | nullExtra info on success (check 2 returns the resolved server:port)

Checks

#NameWhat it does
1socks5TCP connect to the proxy + auth negotiation + UDP ASSOCIATE. Times out after 10 seconds.
2server_dataHTTP POST through the proxy to growtopia1.com/growtopia/server_data.php, falling back to growtopia2.com if the first fails.
3enetOpens a second SOCKS5 UDP socket and attempts an ENet connect to the game server address obtained from check 2. Waits up to 10 seconds for a Connect event. Skipped if check 2 failed.

GET /items/colors

Returns a flat map of all item IDs to their minimap color as 0xRRGGBB. Colors are derived from the base_color field in items.dat, which is stored as BGRA and converted server-side.

Response

{
  "0": 0,
  "2": 1588250666,
  "8": 2303786022
}

Keys are item IDs as strings. No query parameters.


GET /items/names

Returns a flat map of all item IDs to their names. Useful for quick lookups without pagination.

Response

{
  "0": "x",
  "2": "y",
  "8": "z"
}

Keys are item IDs as strings (standard JSON object key behaviour). No query parameters.


GET /items

Paginated search through the item database, or bulk fetch by ID.

Query Parameters

ParamTypeDefaultDescription
pageinteger1Page number (1-indexed)
qstring""Search by item ID (exact) or name (substring, case-insensitive)
get-itemsstringComma-separated item IDs to fetch. When present, returns an array directly (bypasses pagination).

Paginated response (default)

{
  "items": [
    {
      "id": 0,
      "name": "string",
      "flags": 0,
      "action_type": 0,
      "material": 0,
      "texture_file_name": "string",
      "texture_hash": 0,
      "visual_effect": 0,
      "collision_type": 0,
      "rarity": 0,
      "max_item": 0,
      "grow_time": 0,
      "base_color": 0,
      "overlay_color": 0,
      "clothing_type": 0
    }
  ],
  "total": 0,
  "page": 1,
  "page_size": 50
}

50 items per page.

Bulk fetch response (?get-items=2,4,6,8)

Returns a flat array containing only the items whose IDs were requested. Items not found in the database are silently omitted.

[
  {
    "id": 2,
    "name": "string",
    "flags": 0,
    "action_type": 0,
    "material": 0,
    "texture_file_name": "string",
    "texture_hash": 0,
    "visual_effect": 0,
    "collision_type": 0,
    "rarity": 0,
    "max_item": 0,
    "grow_time": 0,
    "base_color": 0,
    "overlay_color": 0,
    "clothing_type": 0
  }
]

On this page