{
  "openapi": "3.1.1",
  "info": {
    "title": "Tournament Bracket Maker API",
    "version": "1.0.0",
    "summary": "Single or double elimination or round robin: seeded brackets, byes, results and downloads.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://tournamentbracketmaker.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Single or double elimination or round robin: seeded brackets, byes, results and downloads.",
        "description": "Paste the entrants (in seed order, or let a seeded random draw decide) and pick single elimination, double elimination or round robin. Get a bracket with standard seeding and byes for the top seeds, a match list, and — as you enter results — winners advancing, standings and the champion. Download the bracket as JSON or CSV to share it.\n\nMethodology:\n- Elimination brackets are padded to the next power of two. Seeds are placed in the standard order (1 v 8, 4 v 5, 2 v 7, 3 v 6 for eight), so the top seeds can only meet late and the byes go to the highest seeds.\n- Double elimination: losers of winners-round 1 meet in losers-round 1; afterwards losers-bracket rounds alternate between taking in the losers of the next winners round (in reversed order on alternate rounds to reduce early rematches) and pairing up survivors. The winners-bracket champion meets the losers-bracket champion in the grand final; if the losers-bracket player wins it, an optional reset match decides.\n- Round robin uses the circle method (Berger tables): with an odd number of players one player rests each round. Standings: 3 points for a win, 1 for a draw, then wins, then name.\n- Results advance the winner (and, in double elimination, drop the loser into the losers bracket). Results naming someone who is not in that match, or for matches whose players are not known yet, are ignored with a warning.\n- A random draw shuffles the entrants with a seeded generator, so the same seed always gives the same bracket. To share a bracket, download the JSON (it contains the input, so it can be re-run via the API) or the CSV match list.",
        "tags": [
          "fun"
        ],
        "x-mcp-tool": "tournament_bracket_maker",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TournamentBracketMakerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Six players, single elimination, two rounds played",
                  "value": {
                    "title": "Office ping-pong",
                    "entrants": [
                      "Ana",
                      "Ben",
                      "Chloe",
                      "Dev",
                      "Emil",
                      "Fatima"
                    ],
                    "format": "single",
                    "seeding": "listed",
                    "thirdPlace": true,
                    "results": [
                      {
                        "match": "W1-2",
                        "winner": "Dev",
                        "score": "11–8"
                      },
                      {
                        "match": "W1-4",
                        "winner": "Fatima",
                        "score": "11–9"
                      },
                      {
                        "match": "W2-1",
                        "winner": "Ana",
                        "score": "2–1"
                      }
                    ]
                  }
                },
                "example2": {
                  "summary": "Double elimination for 8 teams",
                  "value": {
                    "title": "Pub quiz cup",
                    "entrants": [
                      "Quizzly Bears",
                      "Smarty Pints",
                      "Les Quizerables",
                      "Agatha Quiztie",
                      "The Know-Its",
                      "Trivia Newton-John",
                      "Universally Challenged",
                      "Brainy Bunch"
                    ],
                    "format": "double",
                    "seeding": "listed",
                    "results": [
                      {
                        "match": "W1-1",
                        "winner": "Quizzly Bears"
                      },
                      {
                        "match": "W1-2",
                        "winner": "The Know-Its"
                      }
                    ]
                  }
                },
                "example3": {
                  "summary": "Round robin for five",
                  "value": {
                    "title": "Chess club",
                    "entrants": [
                      "Ivy",
                      "Jon",
                      "Kai",
                      "Lea",
                      "Mo"
                    ],
                    "format": "round-robin",
                    "seeding": "random",
                    "seed": "autumn",
                    "results": [
                      {
                        "match": "R1-1",
                        "winner": "draw"
                      },
                      {
                        "match": "R1-2",
                        "winner": "Kai"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TournamentBracketMakerResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "TournamentBracketMakerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "title": "Tournament name",
            "type": "string",
            "maxLength": 80,
            "default": "Tournament"
          },
          "entrants": {
            "title": "Entrants (one per line, best seed first)",
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 64
          },
          "format": {
            "title": "Format",
            "type": "string",
            "enum": [
              "single",
              "double",
              "round-robin"
            ],
            "default": "single"
          },
          "seeding": {
            "title": "Seeding",
            "type": "string",
            "enum": [
              "listed",
              "random"
            ],
            "default": "listed"
          },
          "thirdPlace": {
            "title": "Third-place match (single elimination)",
            "type": "boolean",
            "default": false
          },
          "grandFinalReset": {
            "title": "Grand-final reset if the losers-bracket player wins (double elimination)",
            "type": "boolean",
            "default": true
          },
          "results": {
            "title": "Results",
            "description": "Match id from the match list (e.g. W1-2, L1-1, GF-1, R3-2) and the winner’s name. Round robin: write “draw” for a draw.",
            "type": "array",
            "maxItems": 200,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "match": {
                  "title": "Match",
                  "type": "string",
                  "maxLength": 10
                },
                "winner": {
                  "title": "Winner",
                  "type": "string",
                  "maxLength": 40
                },
                "score": {
                  "title": "Score (optional)",
                  "type": "string",
                  "maxLength": 20
                }
              },
              "required": [
                "match",
                "winner"
              ]
            }
          },
          "seed": {
            "title": "Random draw seed (optional)",
            "description": "Only for a random draw. Empty = derived from the entrant list.",
            "type": "string",
            "maxLength": 60
          }
        },
        "required": [
          "entrants"
        ]
      },
      "TournamentBracketMakerResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "title",
              "format",
              "seed",
              "entrants",
              "bracketSize",
              "byes",
              "matches",
              "nextMatches",
              "champion",
              "standings",
              "completed"
            ],
            "properties": {
              "title": {
                "type": "string"
              },
              "format": {
                "type": "string",
                "enum": [
                  "single",
                  "double",
                  "round-robin"
                ]
              },
              "seed": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "entrants": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "seed",
                    "name"
                  ],
                  "properties": {
                    "seed": {
                      "type": "integer"
                    },
                    "name": {
                      "type": "string"
                    }
                  }
                }
              },
              "bracketSize": {
                "type": "integer"
              },
              "byes": {
                "type": "integer"
              },
              "matches": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "id",
                    "bracket",
                    "round",
                    "roundName",
                    "a",
                    "b",
                    "aFrom",
                    "bFrom",
                    "winner",
                    "loser",
                    "score",
                    "status"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "bracket": {
                      "type": "string",
                      "enum": [
                        "W",
                        "L",
                        "GF",
                        "3P",
                        "RR"
                      ]
                    },
                    "round": {
                      "type": "integer"
                    },
                    "roundName": {
                      "type": "string"
                    },
                    "a": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "b": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "aFrom": {
                      "type": "string"
                    },
                    "bFrom": {
                      "type": "string"
                    },
                    "winner": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "loser": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "score": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "ready",
                        "done",
                        "bye",
                        "not-needed",
                        "draw"
                      ]
                    }
                  }
                }
              },
              "nextMatches": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Ids of matches whose players are known but that have no result yet."
              },
              "champion": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "standings": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "rank",
                    "name",
                    "played",
                    "won",
                    "drawn",
                    "lost",
                    "points"
                  ],
                  "properties": {
                    "rank": {
                      "type": "integer"
                    },
                    "name": {
                      "type": "string"
                    },
                    "played": {
                      "type": "integer"
                    },
                    "won": {
                      "type": "integer"
                    },
                    "drawn": {
                      "type": "integer"
                    },
                    "lost": {
                      "type": "integer"
                    },
                    "points": {
                      "type": "integer"
                    }
                  }
                }
              },
              "completed": {
                "type": "integer"
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}