{
  "openapi": "3.1.0",
  "info": {
    "title": "Sandlot world builder",
    "version": "0.1.0",
    "description": "Build multiplayer 3D browser games in Sandlot. Each tool edits a shared world that players see live. Read the full guide at https://sandlot.foxhollow.games/api/docs before building."
  },
  "servers": [
    {
      "url": "https://sandlot.foxhollow.games"
    }
  ],
  "paths": {
    "/api/worlds": {
      "get": {
        "operationId": "list_worlds",
        "summary": "List worlds",
        "description": "List the worlds on this server (id and title).",
        "responses": {
          "200": {
            "description": "Worlds",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "worlds": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "security": []
      },
      "post": {
        "operationId": "create_world",
        "summary": "Create world",
        "description": "Create a new empty world. Returns its id, edit key, play URL (share with players) and MCP URL.",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "World title."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "key": {
                      "type": "string",
                      "description": "Edit key; send as X-Sandlot-Key to change this world."
                    },
                    "playUrl": {
                      "type": "string"
                    },
                    "mcpUrl": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/worlds/{worldId}/tools/get_world_overview": {
      "post": {
        "operationId": "get_world_overview",
        "summary": "World overview",
        "description": "Summarize the world: title, rules, jump limits, entity counts, bounds, groups, spawns, checkpoints, finish, and the numbered route from spawn to finish with a playability status. Call this first; use the route numbers to resolve \"the third platform\".",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/worlds/{worldId}/tools/find_entities": {
      "post": {
        "operationId": "find_entities",
        "summary": "Find entities",
        "description": "Search entities by role, name/id substring, group, exact ids, and/or distance from a point; returns one line per entity (id, name, role, shape, position, size, color/material, group, order/value/power, behaviors). Filters combine; results near a point are sorted nearest first.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "description": "Only entities with this role.",
                    "type": "string",
                    "enum": [
                      "solid",
                      "spawn",
                      "checkpoint",
                      "finish",
                      "coin",
                      "treasure",
                      "hazard",
                      "bounce",
                      "speed",
                      "decor"
                    ]
                  },
                  "name": {
                    "description": "Case-insensitive substring of the name or id.",
                    "type": "string"
                  },
                  "group": {
                    "description": "Only parts of this structure group.",
                    "type": "string"
                  },
                  "near": {
                    "minItems": 3,
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "type": "number"
                    },
                    "description": "Search center as [x, y, z] in meters (Y is up, the course runs toward -Z)."
                  },
                  "radius": {
                    "description": "Radius in meters around `near` (default 10).",
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "ids": {
                    "description": "Exact entity ids or group ids.",
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "limit": {
                    "description": "Max results (default 40).",
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/worlds/{worldId}/tools/get_player_context": {
      "post": {
        "operationId": "get_player_context",
        "summary": "Players and selections",
        "description": "List the players in the world with their positions and the entities they currently have selected (with details). Use it to resolve \"this\", \"that\" and \"here\" when a player asks for a change.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/worlds/{worldId}/tools/check_playability": {
      "post": {
        "operationId": "check_playability",
        "summary": "Check playability",
        "description": "Simulate whether the course can be completed with the current jump physics: spawn, then each checkpoint in order, then the finish. Reports impossible gaps and ledges naming the exact entities, plus unreachable coins. Run after building and fix every ERROR.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/worlds/{worldId}/tools/get_builder_guide": {
      "post": {
        "operationId": "get_builder_guide",
        "summary": "Builder guide",
        "description": "Get the full builder guide: coordinates, jump limits for this world, roles, behaviors, rules, every structure kind with its params, and the recommended workflow. Read it before building if you have not.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/worlds/{worldId}/tools/add_entities": {
      "post": {
        "operationId": "add_entities",
        "summary": "Add entities",
        "description": "Add one or more primitive entities (platforms, coins, hazards, decor, spawns, checkpoints...). position is the shape CENTER: a 1m-thick platform whose top is at y=T has position y=T-0.5. Role defaults fill in size, color and material. Returns the new ids.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "entities": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "description": "Optional readable id; one is generated if omitted or already taken.",
                          "type": "string"
                        },
                        "position": {
                          "minItems": 3,
                          "maxItems": 3,
                          "type": "array",
                          "items": {
                            "type": "number"
                          },
                          "description": "Center of the shape as [x, y, z] in meters (Y is up, the course runs toward -Z)."
                        },
                        "name": {
                          "description": "Short descriptive label, e.g. \"moat platform 2\".",
                          "type": "string"
                        },
                        "shape": {
                          "description": "box (default) | cylinder | sphere | wedge (ramp rising toward -Z).",
                          "type": "string",
                          "enum": [
                            "box",
                            "cylinder",
                            "sphere",
                            "wedge"
                          ]
                        },
                        "role": {
                          "description": "What it means to the game: solid (default), spawn, checkpoint, finish, coin, treasure, hazard (kills), bounce, speed, decor (no collision).",
                          "type": "string",
                          "enum": [
                            "solid",
                            "spawn",
                            "checkpoint",
                            "finish",
                            "coin",
                            "treasure",
                            "hazard",
                            "bounce",
                            "speed",
                            "decor"
                          ]
                        },
                        "rotation": {
                          "description": "Euler XYZ degrees; rotation[1] is yaw.",
                          "minItems": 3,
                          "maxItems": 3,
                          "type": "array",
                          "items": {
                            "type": "number"
                          }
                        },
                        "size": {
                          "description": "Full extents [x, y, z] in meters. Cylinder: [diameter, height, diameter]. Defaults depend on role.",
                          "minItems": 3,
                          "maxItems": 3,
                          "type": "array",
                          "items": {
                            "type": "number"
                          }
                        },
                        "color": {
                          "description": "Hex color like \"#ff7043\".",
                          "type": "string"
                        },
                        "material": {
                          "description": "plastic | neon | wood | stone | metal | grass | ice | lava | glass.",
                          "type": "string",
                          "enum": [
                            "plastic",
                            "neon",
                            "wood",
                            "stone",
                            "metal",
                            "grass",
                            "ice",
                            "lava",
                            "glass"
                          ]
                        },
                        "behaviors": {
                          "description": "Motion. In an update this REPLACES the whole list; [] stops all motion.",
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "move",
                                  "rotate",
                                  "blink"
                                ],
                                "description": "move = slide to position+offset and back; rotate = spin; blink = appear/disappear."
                              },
                              "offset": {
                                "description": "move: [dx, dy, dz] meters from the base position at the far end of travel.",
                                "minItems": 3,
                                "maxItems": 3,
                                "type": "array",
                                "items": {
                                  "type": "number"
                                }
                              },
                              "period": {
                                "description": "move: seconds for a full there-and-back cycle (default 4).",
                                "type": "number",
                                "exclusiveMinimum": 0
                              },
                              "phase": {
                                "description": "move/blink: 0..1 cycle offset so neighbours are out of sync (default 0).",
                                "type": "number",
                                "minimum": 0,
                                "maximum": 1
                              },
                              "axis": {
                                "description": "rotate: spin axis (default \"y\").",
                                "type": "string",
                                "enum": [
                                  "x",
                                  "y",
                                  "z"
                                ]
                              },
                              "speed": {
                                "description": "rotate: degrees per second; negative spins the other way (default 90).",
                                "type": "number"
                              },
                              "on": {
                                "description": "blink: seconds present and solid (default 2).",
                                "type": "number",
                                "exclusiveMinimum": 0
                              },
                              "off": {
                                "description": "blink: seconds gone (default 1).",
                                "type": "number",
                                "exclusiveMinimum": 0
                              }
                            },
                            "required": [
                              "type"
                            ],
                            "description": "A motion behavior. Fields that do not apply to the chosen type are ignored."
                          }
                        },
                        "group": {
                          "description": "Structure group id to attach this entity to.",
                          "type": "string"
                        },
                        "order": {
                          "description": "Checkpoint number (1, 2, 3...) increasing along the course.",
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        "value": {
                          "description": "Coin/treasure value.",
                          "type": "number"
                        },
                        "power": {
                          "description": "Bounce: launch speed m/s (18 reaches ~6.5m high). Speed pad: speed multiplier (e.g. 1.8).",
                          "type": "number"
                        }
                      },
                      "required": [
                        "position"
                      ]
                    },
                    "description": "Entities to add; batch many in one call."
                  }
                },
                "required": [
                  "entities"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/update_entities": {
      "post": {
        "operationId": "update_entities",
        "summary": "Update entities",
        "description": "Change fields on existing entities: role, color, size, material, behaviors (motion), power, value, order, name, position, rotation. Applies the same patch to every listed id (a group id patches every part). behaviors replaces the whole list.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Entity ids, or structure group ids (a group id stands for every part of that structure)."
                  },
                  "patch": {
                    "type": "object",
                    "properties": {
                      "position": {
                        "minItems": 3,
                        "maxItems": 3,
                        "type": "array",
                        "items": {
                          "type": "number"
                        },
                        "description": "New center as [x, y, z] in meters (Y is up, the course runs toward -Z)."
                      },
                      "name": {
                        "description": "Short descriptive label, e.g. \"moat platform 2\".",
                        "type": "string"
                      },
                      "shape": {
                        "description": "box (default) | cylinder | sphere | wedge (ramp rising toward -Z).",
                        "type": "string",
                        "enum": [
                          "box",
                          "cylinder",
                          "sphere",
                          "wedge"
                        ]
                      },
                      "role": {
                        "description": "What it means to the game: solid (default), spawn, checkpoint, finish, coin, treasure, hazard (kills), bounce, speed, decor (no collision).",
                        "type": "string",
                        "enum": [
                          "solid",
                          "spawn",
                          "checkpoint",
                          "finish",
                          "coin",
                          "treasure",
                          "hazard",
                          "bounce",
                          "speed",
                          "decor"
                        ]
                      },
                      "rotation": {
                        "description": "Euler XYZ degrees; rotation[1] is yaw.",
                        "minItems": 3,
                        "maxItems": 3,
                        "type": "array",
                        "items": {
                          "type": "number"
                        }
                      },
                      "size": {
                        "description": "Full extents [x, y, z] in meters. Cylinder: [diameter, height, diameter]. Defaults depend on role.",
                        "minItems": 3,
                        "maxItems": 3,
                        "type": "array",
                        "items": {
                          "type": "number"
                        }
                      },
                      "color": {
                        "description": "Hex color like \"#ff7043\".",
                        "type": "string"
                      },
                      "material": {
                        "description": "plastic | neon | wood | stone | metal | grass | ice | lava | glass.",
                        "type": "string",
                        "enum": [
                          "plastic",
                          "neon",
                          "wood",
                          "stone",
                          "metal",
                          "grass",
                          "ice",
                          "lava",
                          "glass"
                        ]
                      },
                      "behaviors": {
                        "description": "Motion. In an update this REPLACES the whole list; [] stops all motion.",
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "move",
                                "rotate",
                                "blink"
                              ],
                              "description": "move = slide to position+offset and back; rotate = spin; blink = appear/disappear."
                            },
                            "offset": {
                              "description": "move: [dx, dy, dz] meters from the base position at the far end of travel.",
                              "minItems": 3,
                              "maxItems": 3,
                              "type": "array",
                              "items": {
                                "type": "number"
                              }
                            },
                            "period": {
                              "description": "move: seconds for a full there-and-back cycle (default 4).",
                              "type": "number",
                              "exclusiveMinimum": 0
                            },
                            "phase": {
                              "description": "move/blink: 0..1 cycle offset so neighbours are out of sync (default 0).",
                              "type": "number",
                              "minimum": 0,
                              "maximum": 1
                            },
                            "axis": {
                              "description": "rotate: spin axis (default \"y\").",
                              "type": "string",
                              "enum": [
                                "x",
                                "y",
                                "z"
                              ]
                            },
                            "speed": {
                              "description": "rotate: degrees per second; negative spins the other way (default 90).",
                              "type": "number"
                            },
                            "on": {
                              "description": "blink: seconds present and solid (default 2).",
                              "type": "number",
                              "exclusiveMinimum": 0
                            },
                            "off": {
                              "description": "blink: seconds gone (default 1).",
                              "type": "number",
                              "exclusiveMinimum": 0
                            }
                          },
                          "required": [
                            "type"
                          ],
                          "description": "A motion behavior. Fields that do not apply to the chosen type are ignored."
                        }
                      },
                      "group": {
                        "description": "Structure group id to attach this entity to.",
                        "type": "string"
                      },
                      "order": {
                        "description": "Checkpoint number (1, 2, 3...) increasing along the course.",
                        "type": "integer",
                        "minimum": -9007199254740991,
                        "maximum": 9007199254740991
                      },
                      "value": {
                        "description": "Coin/treasure value.",
                        "type": "number"
                      },
                      "power": {
                        "description": "Bounce: launch speed m/s (18 reaches ~6.5m high). Speed pad: speed multiplier (e.g. 1.8).",
                        "type": "number"
                      }
                    },
                    "description": "Fields to change; omitted fields stay as they are."
                  }
                },
                "required": [
                  "ids",
                  "patch"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/move_entities": {
      "post": {
        "operationId": "move_entities",
        "summary": "Move entities",
        "description": "Shift entities (or whole structures by group id) by a delta [dx, dy, dz]. The course runs toward -Z, so moving a platform \"closer\" to the one before it is usually +Z.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Entity ids, or structure group ids (a group id stands for every part of that structure)."
                  },
                  "delta": {
                    "minItems": 3,
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "type": "number"
                    },
                    "description": "Offset to add to each position as [x, y, z] in meters (Y is up, the course runs toward -Z)."
                  }
                },
                "required": [
                  "ids",
                  "delta"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/scale_entities": {
      "post": {
        "operationId": "scale_entities",
        "summary": "Scale entities",
        "description": "Multiply entity sizes by factor [fx, fy, fz] (e.g. [1.5, 1, 1.5] makes platforms wider). With aroundCenter=true positions also spread from the selection center, to grow a whole structure while keeping its base on the ground.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Entity ids, or structure group ids (a group id stands for every part of that structure)."
                  },
                  "factor": {
                    "minItems": 3,
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "type": "number",
                      "exclusiveMinimum": 0
                    },
                    "description": "Size multipliers [fx, fy, fz]."
                  },
                  "aroundCenter": {
                    "description": "Also scale positions away from the group center (default false).",
                    "type": "boolean"
                  }
                },
                "required": [
                  "ids",
                  "factor"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/remove_entities": {
      "post": {
        "operationId": "remove_entities",
        "summary": "Remove entities",
        "description": "Delete entities, or whole structures by group id. Do not remove the last spawn or finish unless replacing them.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Entity ids, or structure group ids (a group id stands for every part of that structure)."
                  }
                },
                "required": [
                  "ids"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/duplicate_entities": {
      "post": {
        "operationId": "duplicate_entities",
        "summary": "Duplicate entities",
        "description": "Copy entities (or whole structures by group id) shifted by an offset; copies get new ids, and grouped copies get a new group id. Handy for repeating a section further down the course.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Entity ids, or structure group ids (a group id stands for every part of that structure)."
                  },
                  "offset": {
                    "minItems": 3,
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "type": "number"
                    },
                    "description": "Offset of the copies from the originals as [x, y, z] in meters (Y is up, the course runs toward -Z)."
                  }
                },
                "required": [
                  "ids",
                  "offset"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/build_structure": {
      "post": {
        "operationId": "build_structure",
        "summary": "Build structure",
        "description": "Build a ready-made multi-part structure as one group, e.g. a whole themed course (full_course), a castle, tower, bridge, moving platforms or checkpoint gate. The result gives the group id and an exit point where the course continues; see get_builder_guide for every kind's params.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "staircase",
                      "tower",
                      "castle",
                      "bridge",
                      "platform_path",
                      "spinner",
                      "wall_with_door",
                      "moat",
                      "stepping_stones",
                      "zigzag",
                      "moving_platforms",
                      "ring_of_coins",
                      "coin_line",
                      "lava_floor",
                      "checkpoint_gate",
                      "finish_arch",
                      "obstacle_course_section",
                      "full_course"
                    ],
                    "description": "Structure type."
                  },
                  "position": {
                    "minItems": 3,
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "type": "number"
                    },
                    "description": "Origin: for course pieces, where the player stands before the piece (at that walking height); for buildings, the base center/front as [x, y, z] in meters (Y is up, the course runs toward -Z)."
                  },
                  "rotationY": {
                    "description": "Yaw in degrees around the origin (default 0 = extends toward -Z; 90 = toward -X).",
                    "type": "number"
                  },
                  "params": {
                    "description": "Kind-specific parameters, e.g. {\"count\": 5, \"gap\": 3}. All optional; see get_builder_guide.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "name": {
                    "description": "Readable base for the group id, e.g. \"lava castle\".",
                    "type": "string"
                  }
                },
                "required": [
                  "kind",
                  "position"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/set_rules": {
      "post": {
        "operationId": "set_rules",
        "summary": "Set game rules",
        "description": "Change game mechanics: lives, time limit, scoring (finishPoints, coinPoints), physics (gravity, jumpVelocity, walkSpeed), killY, ground plane, sky/fog/ground colors. Pass the fields directly, e.g. {\"lives\": 3, \"timeLimit\": 90} (wrapping them in \"patch\" also works).",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lives": {
                    "description": "Lives per race; null = unlimited.",
                    "anyOf": [
                      {
                        "type": "integer",
                        "exclusiveMinimum": 0,
                        "maximum": 9007199254740991
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "timeLimit": {
                    "description": "Race time limit in seconds; null = none.",
                    "anyOf": [
                      {
                        "type": "number",
                        "exclusiveMinimum": 0
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "finishPoints": {
                    "description": "Points for 1st, 2nd, 3rd... finisher; later finishers get the last value.",
                    "type": "array",
                    "items": {
                      "type": "number"
                    }
                  },
                  "coinPoints": {
                    "description": "Score points per coin collected.",
                    "type": "number"
                  },
                  "killY": {
                    "description": "Falling below this height counts as a death.",
                    "type": "number"
                  },
                  "gravity": {
                    "description": "Gravity in m/s^2, negative (default -25). Weaker gravity = higher, longer jumps.",
                    "type": "number"
                  },
                  "walkSpeed": {
                    "description": "Run speed m/s (default 8).",
                    "type": "number"
                  },
                  "jumpVelocity": {
                    "description": "Jump launch speed m/s (default 10).",
                    "type": "number"
                  },
                  "skyColor": {
                    "description": "Hex sky color.",
                    "type": "string"
                  },
                  "fogColor": {
                    "description": "Hex fog color.",
                    "type": "string"
                  },
                  "groundY": {
                    "description": "Height of an infinite ground plane; null = no ground (the void).",
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "groundColor": {
                    "description": "Hex ground color.",
                    "type": "string"
                  },
                  "patch": {
                    "description": "Alternative: the same rule fields wrapped in an object.",
                    "type": "object",
                    "properties": {
                      "lives": {
                        "description": "Lives per race; null = unlimited.",
                        "anyOf": [
                          {
                            "type": "integer",
                            "exclusiveMinimum": 0,
                            "maximum": 9007199254740991
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "timeLimit": {
                        "description": "Race time limit in seconds; null = none.",
                        "anyOf": [
                          {
                            "type": "number",
                            "exclusiveMinimum": 0
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "finishPoints": {
                        "description": "Points for 1st, 2nd, 3rd... finisher; later finishers get the last value.",
                        "type": "array",
                        "items": {
                          "type": "number"
                        }
                      },
                      "coinPoints": {
                        "description": "Score points per coin collected.",
                        "type": "number"
                      },
                      "killY": {
                        "description": "Falling below this height counts as a death.",
                        "type": "number"
                      },
                      "gravity": {
                        "description": "Gravity in m/s^2, negative (default -25). Weaker gravity = higher, longer jumps.",
                        "type": "number"
                      },
                      "walkSpeed": {
                        "description": "Run speed m/s (default 8).",
                        "type": "number"
                      },
                      "jumpVelocity": {
                        "description": "Jump launch speed m/s (default 10).",
                        "type": "number"
                      },
                      "skyColor": {
                        "description": "Hex sky color.",
                        "type": "string"
                      },
                      "fogColor": {
                        "description": "Hex fog color.",
                        "type": "string"
                      },
                      "groundY": {
                        "description": "Height of an infinite ground plane; null = no ground (the void).",
                        "type": [
                          "number",
                          "null"
                        ]
                      },
                      "groundColor": {
                        "description": "Hex ground color.",
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/set_info": {
      "post": {
        "operationId": "set_info",
        "summary": "Set title and description",
        "description": "Set the world's title and/or description, shown to players in the lobby and HUD.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "description": "World title, e.g. \"Lava Castle Dash\".",
                    "type": "string",
                    "maxLength": 80
                  },
                  "description": {
                    "description": "One or two sentences describing the game.",
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/clear_world": {
      "post": {
        "operationId": "clear_world",
        "summary": "Clear world",
        "description": "Remove EVERY entity, leaving an empty world (rules and title stay). Only use when the person clearly wants to start over, then rebuild a spawn, course and finish (build_structure full_course is the quickest).",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/style_avatar": {
      "post": {
        "operationId": "style_avatar",
        "summary": "Style a player avatar",
        "description": "Dress up a player's avatar: costume presets (pirate, astronaut, knight, wizard, princess, ninja, robot, superhero...), hats, hair, face, clothes with colors and patterns, wings/capes, held items and pets. Use it when someone asks to change how they (or a friend) look, e.g.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "player": {
                    "description": "Name or id of the player to style. Omit to style the player who asked (built-in builder); external agents must name the player (see get_player_context).",
                    "type": "string"
                  },
                  "preset": {
                    "description": "Start from a ready-made costume, then apply hat/outfit on top: pirate, astronaut, knight, wizard, princess, ninja, robot, superhero, fairy, vampire, chef, cowpoke. Presets keep the player's skin tone.",
                    "type": "string",
                    "enum": [
                      "pirate",
                      "astronaut",
                      "knight",
                      "wizard",
                      "princess",
                      "ninja",
                      "robot",
                      "superhero",
                      "fairy",
                      "vampire",
                      "chef",
                      "cowpoke"
                    ]
                  },
                  "reset": {
                    "description": "Start from the plain default outfit instead of the player's current look (default false: only the fields you pass change).",
                    "type": "boolean"
                  },
                  "hat": {
                    "description": "Hat or headwear (\"none\" removes it).",
                    "type": "string",
                    "enum": [
                      "none",
                      "cap",
                      "crown",
                      "cone",
                      "tophat",
                      "horns",
                      "halo",
                      "beanie",
                      "cowboy",
                      "pirate",
                      "wizard",
                      "knight",
                      "astronaut",
                      "tiara",
                      "bow",
                      "cat_ears",
                      "bunny_ears",
                      "flower",
                      "chef",
                      "propeller",
                      "viking",
                      "ninja",
                      "antenna",
                      "headphones"
                    ]
                  },
                  "outfit": {
                    "description": "Outfit fields to change; omitted fields keep their current value.",
                    "type": "object",
                    "properties": {
                      "height": {
                        "description": "Visual height scale, 0.88-1.12 (1 = normal).",
                        "type": "number",
                        "minimum": 0.88,
                        "maximum": 1.12
                      },
                      "shape": {
                        "description": "Body proportions; \"chibi\" is a small body with a big head.",
                        "type": "string",
                        "enum": [
                          "classic",
                          "slim",
                          "sturdy",
                          "chibi"
                        ]
                      },
                      "eyes": {
                        "description": "Eye style.",
                        "type": "string",
                        "enum": [
                          "round",
                          "happy",
                          "sparkle",
                          "sleepy",
                          "wink",
                          "star",
                          "heart",
                          "dot",
                          "angry",
                          "cool"
                        ]
                      },
                      "mouth": {
                        "description": "Mouth/expression.",
                        "type": "string",
                        "enum": [
                          "smile",
                          "grin",
                          "laugh",
                          "tongue",
                          "cat",
                          "oh",
                          "smirk",
                          "fangs",
                          "flat"
                        ]
                      },
                      "brows": {
                        "description": "Eyebrow style.",
                        "type": "string",
                        "enum": [
                          "none",
                          "soft",
                          "raised",
                          "angry",
                          "worried",
                          "bushy"
                        ]
                      },
                      "cheeks": {
                        "description": "Cheek details.",
                        "type": "string",
                        "enum": [
                          "none",
                          "blush",
                          "freckles",
                          "both",
                          "whiskers",
                          "hearts"
                        ]
                      },
                      "glasses": {
                        "description": "Eyewear or mask (eyepatch for pirates, mask for heroes and ninjas).",
                        "type": "string",
                        "enum": [
                          "none",
                          "round",
                          "square",
                          "shades",
                          "star",
                          "heart",
                          "goggles",
                          "monocle",
                          "eyepatch",
                          "mask"
                        ]
                      },
                      "hair": {
                        "description": "Hairstyle (\"none\" = bald).",
                        "type": "string",
                        "enum": [
                          "none",
                          "short",
                          "swoop",
                          "spiky",
                          "long",
                          "bob",
                          "ponytail",
                          "pigtails",
                          "bun",
                          "curly",
                          "mohawk"
                        ]
                      },
                      "top": {
                        "description": "Top garment. dress and robe also cover the legs.",
                        "type": "string",
                        "enum": [
                          "tshirt",
                          "tank",
                          "longsleeve",
                          "hoodie",
                          "jacket",
                          "dress",
                          "robe",
                          "armor",
                          "spacesuit",
                          "tuxedo"
                        ]
                      },
                      "topPattern": {
                        "description": "Pattern printed on the top.",
                        "type": "string",
                        "enum": [
                          "solid",
                          "stripes",
                          "dots",
                          "stars",
                          "checker",
                          "hearts",
                          "zigzag"
                        ]
                      },
                      "bottom": {
                        "description": "Bottoms.",
                        "type": "string",
                        "enum": [
                          "pants",
                          "shorts",
                          "skirt",
                          "tutu"
                        ]
                      },
                      "bottomPattern": {
                        "description": "Pattern printed on the bottoms.",
                        "type": "string",
                        "enum": [
                          "solid",
                          "stripes",
                          "dots",
                          "stars",
                          "checker",
                          "hearts",
                          "zigzag"
                        ]
                      },
                      "shoes": {
                        "description": "Footwear.",
                        "type": "string",
                        "enum": [
                          "sneakers",
                          "boots",
                          "fancy",
                          "bare"
                        ]
                      },
                      "back": {
                        "description": "Item worn on the back.",
                        "type": "string",
                        "enum": [
                          "none",
                          "backpack",
                          "cape",
                          "angel_wings",
                          "bat_wings",
                          "fairy_wings",
                          "jetpack"
                        ]
                      },
                      "neck": {
                        "description": "Neckwear.",
                        "type": "string",
                        "enum": [
                          "none",
                          "scarf",
                          "necklace",
                          "bowtie",
                          "medal",
                          "bandana"
                        ]
                      },
                      "held": {
                        "description": "Item held in the hand (shield goes on the other arm).",
                        "type": "string",
                        "enum": [
                          "none",
                          "sword",
                          "wand",
                          "balloon",
                          "shield",
                          "icecream",
                          "lollipop",
                          "flower"
                        ]
                      },
                      "pet": {
                        "description": "A pet that follows the player around (the parrot sits on their shoulder).",
                        "type": "string",
                        "enum": [
                          "none",
                          "cat",
                          "dog",
                          "bunny",
                          "parrot",
                          "slime",
                          "dragon",
                          "robot",
                          "chick"
                        ]
                      },
                      "skin": {
                        "description": "Skin tone. Change it only if the person asks (e.g. \"make me green like an alien\"). Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "eyeColor": {
                        "description": "Iris color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "hairColor": {
                        "description": "Hair color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "topColor": {
                        "description": "Top color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "topPatternColor": {
                        "description": "Top pattern color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "bottomColor": {
                        "description": "Bottoms color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "bottomPatternColor": {
                        "description": "Bottoms pattern color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "shoeColor": {
                        "description": "Shoe color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "hatColor": {
                        "description": "Hat color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "backColor": {
                        "description": "Back item color (cape, wings, backpack, jetpack). Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "neckColor": {
                        "description": "Neckwear color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "heldColor": {
                        "description": "Held item color (balloon, shield face, ice cream, lollipop, flower). Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      },
                      "petColor": {
                        "description": "Pet color. Hex \"#rrggbb\".",
                        "type": "string",
                        "pattern": "^#[0-9a-fA-F]{6}$"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/undo": {
      "post": {
        "operationId": "undo",
        "summary": "Undo",
        "description": "Undo the most recent change to the world (by anyone: players, you, or other agents). Call again to step further back.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/redo": {
      "post": {
        "operationId": "redo",
        "summary": "Redo",
        "description": "Redo the most recently undone change.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/worlds/{worldId}/tools/get_history": {
      "post": {
        "operationId": "get_history",
        "summary": "Get change history",
        "description": "List recent changes to the world, newest first: time, who made it (player or agent name) and a summary. Use it to see what others changed since you last looked.",
        "parameters": [
          {
            "name": "worldId",
            "in": "path",
            "required": true,
            "description": "World id (from the game URL ?world=...).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "limit": {
                    "default": 30,
                    "description": "How many recent changes to list (newest first).",
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 200
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tool result (check ok)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid arguments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or wrong edit key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          },
          "404": {
            "description": "Unknown world",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                }
              }
            }
          }
        },
        "security": []
      }
    }
  },
  "components": {
    "schemas": {
      "ToolResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "description": "False if the call failed; text explains how to fix it."
          },
          "text": {
            "type": "string",
            "description": "Result for the model to read."
          },
          "data": {
            "description": "Optional structured result."
          },
          "world": {
            "type": "string",
            "description": "The world id this call acted on; check it is the world you meant."
          },
          "actor": {
            "type": "string",
            "description": "The name players see next to your changes."
          }
        },
        "required": [
          "ok",
          "text"
        ]
      }
    },
    "securitySchemes": {
      "editKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Sandlot-Key"
      }
    }
  },
  "security": [
    {
      "editKey": []
    }
  ]
}