Skip to main content

Introspection

Discover every dispatch command the running binary exposes. Useful for external tooling that wants to enumerate the surface without a code-walk through api_dispatch.rs.

GET /api/commands

Auth: bearer.

Response (200):

{
"commands": [
"account_creator_accounts",
"bot_accept_friend",
"bot_active_worlds",
"bot_add_friend",
"bot_chat",
"bot_drop",
"bot_walk_to",
"catalog_block_types",
"catalog_item_database",
"catalog_pack_pool",
"connect_bot",
"disconnect_bot",
"join_world",
"leave_world",
"list_bots",
"seraph_execute",
"spawn_bot_email",
"..."
]
}

The list is alphabetical and reflects the exact set of names that POST /invoke accepts as cmd. Adding a feature mid-release rotates this list automatically — the introspection endpoint reads s.handlers.keys() directly, no manifest to keep in sync.

Calling a discovered command

Every name returned here is reachable via the universal dispatch endpoint:

curl -s -X POST http://localhost:8090/invoke \
-H 'authorization: Bearer <token>' \
-H 'content-type: application/json' \
-d '{"cmd":"<name>","args":<args>}'

<args> is whatever shape the corresponding handler expects. For zero-arg handlers, send null or {}. For per-bot commands the common shape is {"id":"bot-1"}. The full argument schema lives in src-tauri/src/api_dispatch.rs — open the matching register0 / register1 line and the struct after register1::<...>.

REST sugar vs /invoke

The REST sugar routes (/api/bots/{id}/*, /api/scripts/*, etc.) are thin wrappers that forward to the dispatcher. Anything they do, /invoke can do too. If you want to drive every bot from one generic client, point at /invoke and skip the sugar entirely.