{
    "openapi": "3.1.0",
    "info": {
        "title": "FlipSight Bot API",
        "version": "1.0.0"
    },
    "servers": [
        {
            "url": "https://othelloclub.com"
        }
    ],
    "components": {
        "securitySchemes": {
            "BotToken": {
                "type": "http",
                "scheme": "bearer"
            }
        },
        "schemas": {
            "Bot": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "name": {
                        "type": "string"
                    },
                    "supported_games": {
                        "type": "array",
                        "minItems": 1,
                        "items": {
                            "type": "string",
                            "enum": [
                                "std",
                                "anti",
                                "octagon",
                                "grand",
                                "reversi"
                            ]
                        }
                    },
                    "auto_match": {
                        "type": "boolean"
                    },
                    "owner_id": {
                        "type": "string"
                    },
                    "owner_name": {
                        "type": "string"
                    },
                    "is_builtin": {
                        "type": "boolean"
                    },
                    "online": {
                        "type": "boolean"
                    },
                    "disabled": {
                        "type": "boolean"
                    },
                    "deleted": {
                        "type": "boolean"
                    },
                    "engine_level": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "rating": {
                        "type": "object"
                    },
                    "environment": {
                        "oneOf": [
                            {
                                "type": "object",
                                "properties": {
                                    "cpu": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "engine": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "os": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "practice": {
                                        "type": "boolean"
                                    }
                                }
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "photo": {
                        "type": "string"
                    },
                    "bio": {
                        "type": "string"
                    },
                    "registered_at": {
                        "type": "string"
                    },
                    "registered_at_ts": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    }
                }
            },
            "Match": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "kind": {
                        "type": "string",
                        "enum": [
                            "human"
                        ]
                    },
                    "room_id": {
                        "type": "integer"
                    },
                    "round_no": {
                        "type": "integer"
                    },
                    "room_created_at": {
                        "type": "string"
                    },
                    "bot_a": {
                        "type": "integer"
                    },
                    "bot_b": {
                        "type": "integer"
                    },
                    "game_mode": {
                        "type": "string"
                    },
                    "time_limit_sec": {
                        "type": "integer"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "running",
                            "finished",
                            "aborted",
                            "rejected",
                            "expired"
                        ]
                    },
                    "state": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/State"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "auto": {
                        "type": "boolean"
                    },
                    "expires_ms": {
                        "type": "integer"
                    },
                    "ranked": {
                        "type": "boolean"
                    },
                    "rating_applied": {
                        "type": "boolean"
                    },
                    "rating_before": {
                        "type": "array",
                        "items": {
                            "type": [
                                "number",
                                "string",
                                "null"
                            ]
                        }
                    },
                    "rating_after": {
                        "type": "array",
                        "items": {
                            "type": [
                                "number",
                                "string",
                                "null"
                            ]
                        }
                    },
                    "created_at": {
                        "type": "string"
                    }
                }
            },
            "State": {
                "type": "object",
                "properties": {
                    "version": {
                        "type": "integer",
                        "const": 1
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "active",
                            "finished",
                            "aborted"
                        ]
                    },
                    "game_mode": {
                        "type": "string",
                        "enum": [
                            "std",
                            "anti",
                            "octagon",
                            "grand",
                            "reversi"
                        ]
                    },
                    "board_size": {
                        "type": "integer",
                        "enum": [
                            8,
                            10
                        ]
                    },
                    "blocked_squares": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "time_limit_sec": {
                        "type": "integer"
                    },
                    "revision": {
                        "type": "integer"
                    },
                    "legs": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 2,
                        "items": {
                            "$ref": "#/components/schemas/Leg"
                        }
                    },
                    "totals": {
                        "type": "array",
                        "minItems": 2,
                        "maxItems": 2,
                        "items": {
                            "type": "integer"
                        }
                    },
                    "winner": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "enum": [
                            0,
                            1,
                            null
                        ]
                    },
                    "opening_moves": {
                        "type": "array",
                        "items": {
                            "type": "integer"
                        }
                    },
                    "opening_history": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/HistoryMove"
                        }
                    },
                    "started_ms": {
                        "type": "integer"
                    },
                    "finished_ms": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "finish_reason": {
                        "type": [
                            "string",
                            "null"
                        ]
                    }
                }
            },
            "Leg": {
                "type": "object",
                "properties": {
                    "board": {
                        "oneOf": [
                            {
                                "type": "array",
                                "minItems": 64,
                                "maxItems": 64,
                                "items": {
                                    "type": "integer",
                                    "enum": [
                                        0,
                                        1,
                                        2
                                    ]
                                }
                            },
                            {
                                "type": "array",
                                "minItems": 100,
                                "maxItems": 100,
                                "items": {
                                    "type": "integer",
                                    "enum": [
                                        0,
                                        1,
                                        2
                                    ]
                                }
                            }
                        ]
                    },
                    "legal_moves": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 99
                        }
                    },
                    "placed": {
                        "type": "object"
                    },
                    "turn": {
                        "type": "integer",
                        "enum": [
                            1,
                            2
                        ]
                    },
                    "black_participant": {
                        "type": "integer",
                        "enum": [
                            0,
                            1
                        ]
                    },
                    "clocks_ms": {
                        "type": "array",
                        "minItems": 2,
                        "maxItems": 2,
                        "items": {
                            "type": "number"
                        }
                    },
                    "turn_started_ms": {
                        "type": "integer"
                    },
                    "revision": {
                        "type": "integer",
                        "minimum": 0
                    },
                    "history": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/HistoryMove"
                        }
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "active",
                            "finished",
                            "timeout",
                            "stopped"
                        ]
                    },
                    "result_discs": {
                        "type": "array",
                        "minItems": 2,
                        "maxItems": 2,
                        "items": {
                            "type": "integer"
                        },
                        "description": "Optional timeout adjudicated scores in black/white order. When present, use instead of discs for totals; discs and board retain the actual position."
                    },
                    "discs": {
                        "type": "array",
                        "minItems": 2,
                        "maxItems": 2,
                        "items": {
                            "type": "integer"
                        }
                    },
                    "finished_ms": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    }
                }
            },
            "HistoryMove": {
                "type": "object",
                "properties": {
                    "color": {
                        "type": "integer",
                        "enum": [
                            1,
                            2
                        ]
                    },
                    "move": {
                        "type": "integer",
                        "minimum": -1,
                        "maximum": 99
                    },
                    "at_ms": {
                        "type": "integer"
                    }
                }
            }
        }
    },
    "paths": {
        "/flipsight/bot_match_api.php": {
            "post": {
                "tags": [
                    "Bot"
                ],
                "operationId": "botAction",
                "security": [
                    {
                        "BotToken": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "oneOf": [
                                    {
                                        "type": "object",
                                        "required": [
                                            "action"
                                        ],
                                        "properties": {
                                            "action": {
                                                "type": "string",
                                                "const": "agent_poll"
                                            },
                                            "environment": {
                                                "type": "object",
                                                "properties": {
                                                    "cpu": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "maxLength": 120
                                                    },
                                                    "engine": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "maxLength": 120
                                                    },
                                                    "os": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "maxLength": 120
                                                    },
                                                    "practice": {
                                                        "type": "boolean"
                                                    }
                                                },
                                                "additionalProperties": false
                                            }
                                        }
                                    },
                                    {
                                        "type": "object",
                                        "required": [
                                            "action"
                                        ],
                                        "properties": {
                                            "action": {
                                                "type": "string",
                                                "const": "agent_challenge"
                                            },
                                            "target_id": {
                                                "type": "integer",
                                                "minimum": 1
                                            },
                                            "target_name": {
                                                "type": "string",
                                                "minLength": 2,
                                                "maxLength": 24
                                            },
                                            "game_mode": {
                                                "type": "string",
                                                "enum": [
                                                    "std",
                                                    "anti",
                                                    "octagon",
                                                    "grand",
                                                    "reversi"
                                                ],
                                                "default": "std"
                                            }
                                        },
                                        "anyOf": [
                                            {
                                                "required": [
                                                    "target_id"
                                                ]
                                            },
                                            {
                                                "required": [
                                                    "target_name"
                                                ]
                                            }
                                        ]
                                    },
                                    {
                                        "type": "object",
                                        "required": [
                                            "action",
                                            "match_id"
                                        ],
                                        "properties": {
                                            "action": {
                                                "type": "string",
                                                "const": "agent_accept"
                                            },
                                            "match_id": {
                                                "type": "integer",
                                                "minimum": 1
                                            }
                                        }
                                    },
                                    {
                                        "type": "object",
                                        "required": [
                                            "action",
                                            "match_id"
                                        ],
                                        "properties": {
                                            "action": {
                                                "type": "string",
                                                "const": "agent_reject"
                                            },
                                            "match_id": {
                                                "type": "integer",
                                                "minimum": 1
                                            }
                                        }
                                    },
                                    {
                                        "type": "object",
                                        "required": [
                                            "action",
                                            "match_id",
                                            "leg",
                                            "revision",
                                            "move"
                                        ],
                                        "properties": {
                                            "action": {
                                                "type": "string",
                                                "const": "agent_move"
                                            },
                                            "match_id": {
                                                "type": "integer",
                                                "not": {
                                                    "const": 0
                                                }
                                            },
                                            "round_no": {
                                                "type": "integer",
                                                "minimum": 0
                                            },
                                            "room_created_at": {
                                                "type": "string"
                                            },
                                            "leg": {
                                                "type": "integer",
                                                "enum": [
                                                    0,
                                                    1
                                                ]
                                            },
                                            "revision": {
                                                "type": "integer",
                                                "minimum": 0
                                            },
                                            "move": {
                                                "oneOf": [
                                                    {
                                                        "type": "integer",
                                                        "minimum": -1,
                                                        "maximum": 99
                                                    },
                                                    {
                                                        "type": "string",
                                                        "pattern": "^(?:[a-jA-J](?:10|[0-9])|[pP][aA](?:[sS][sS])?|[pP][sS]|--)$"
                                                    }
                                                ]
                                            }
                                        },
                                        "allOf": [
                                            {
                                                "if": {
                                                    "properties": {
                                                        "match_id": {
                                                            "maximum": -1
                                                        }
                                                    }
                                                },
                                                "then": {
                                                    "required": [
                                                        "round_no",
                                                        "room_created_at"
                                                    ],
                                                    "properties": {
                                                        "leg": {
                                                            "const": 0
                                                        },
                                                        "move": {
                                                            "oneOf": [
                                                                {
                                                                    "type": "integer",
                                                                    "minimum": 0,
                                                                    "maximum": 99
                                                                },
                                                                {
                                                                    "type": "string",
                                                                    "pattern": "^[a-jA-J](?:10|[0-9])$"
                                                                }
                                                            ]
                                                        }
                                                    }
                                                }
                                            }
                                        ]
                                    }
                                ]
                            },
                            "examples": {
                                "agent_poll": {
                                    "value": {
                                        "action": "agent_poll",
                                        "environment": {
                                            "cpu": "Apple M4",
                                            "engine": "MyEngine",
                                            "os": "Darwin"
                                        }
                                    }
                                },
                                "agent_challenge": {
                                    "value": {
                                        "action": "agent_challenge",
                                        "target_id": 2,
                                        "game_mode": "anti"
                                    }
                                },
                                "agent_accept": {
                                    "value": {
                                        "action": "agent_accept",
                                        "match_id": 123
                                    }
                                },
                                "agent_reject": {
                                    "value": {
                                        "action": "agent_reject",
                                        "match_id": 123
                                    }
                                },
                                "agent_move": {
                                    "value": {
                                        "action": "agent_move",
                                        "match_id": 123,
                                        "leg": 1,
                                        "revision": 0,
                                        "move": 2
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": true
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        },
                                        "bot": {
                                            "$ref": "#/components/schemas/Bot"
                                        },
                                        "bots": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Bot"
                                            }
                                        },
                                        "record_bots": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Bot"
                                            }
                                        },
                                        "matches": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Match"
                                            }
                                        },
                                        "match_id": {
                                            "type": "integer"
                                        },
                                        "match": {
                                            "$ref": "#/components/schemas/Match"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "400",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "error",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": false
                                        },
                                        "error": {
                                            "type": "string"
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "401",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "error",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": false
                                        },
                                        "error": {
                                            "type": "string"
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "403",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "error",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": false
                                        },
                                        "error": {
                                            "type": "string"
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "405": {
                        "description": "405",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "error",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": false
                                        },
                                        "error": {
                                            "type": "string"
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "409",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "error",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": false
                                        },
                                        "error": {
                                            "type": "string"
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "413": {
                        "description": "413",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "error",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": false
                                        },
                                        "error": {
                                            "type": "string"
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "429",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "error",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": false
                                        },
                                        "error": {
                                            "type": "string"
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "503",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "error",
                                        "server_now_ms"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "const": false
                                        },
                                        "error": {
                                            "type": "string"
                                        },
                                        "server_now_ms": {
                                            "type": "integer"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}