{
  "openapi": "3.1.0",
  "info": {
    "title": "Find My Tris API",
    "version": "1.0.0",
    "summary": "Read-only data on official IRONMAN, IRONMAN 70.3 and 5150 triathlons.",
    "description": "Data compiled by Find My Tris from official IRONMAN pages; please cite findmytris.com. Always confirm details on the official race page. Data licensed CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/); attribution: Find My Tris (findmytris.com).",
    "contact": {
      "url": "https://findmytris.com"
    },
    "license": {
      "name": "CC BY 4.0",
      "identifier": "CC-BY-4.0"
    }
  },
  "servers": [
    {
      "url": "https://findmytris.com"
    }
  ],
  "paths": {
    "/api/events": {
      "get": {
        "operationId": "listEvents",
        "summary": "List races (all, including past, unless upcoming=1). Filters are case-insensitive; list filters accept comma-separated values (any of). Same semantics as the MCP search_races tool.",
        "parameters": [
          {
            "name": "race_type",
            "in": "query",
            "required": false,
            "description": "Race type (case-insensitive; comma-separate for several, e.g. IRONMAN,IRONMAN 70.3)",
            "schema": {
              "type": "string",
              "examples": [
                "IRONMAN",
                "IRONMAN 70.3",
                "5150"
              ]
            }
          },
          {
            "name": "continent",
            "in": "query",
            "required": false,
            "description": "Continent (case-insensitive; comma-separate for several, e.g. Europe,Africa)",
            "schema": {
              "type": "string",
              "examples": [
                "Africa",
                "Asia",
                "Europe",
                "North America",
                "Oceania",
                "South America"
              ]
            }
          },
          {
            "name": "swim_type",
            "in": "query",
            "required": false,
            "description": "Swim venue: Ocean, Sea, Bay, Harbor, Lake, River, Reservoir. Case-insensitive; comma-separate for several; Ocean and Sea are synonyms (either returns both); \"saltwater\" = Ocean,Sea,Bay,Harbor",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bike_course_type",
            "in": "query",
            "required": false,
            "description": "Bike profile (case-insensitive; comma-separate for several, e.g. Flat,Rolling)",
            "schema": {
              "type": "string",
              "examples": [
                "Flat",
                "Rolling",
                "Hilly"
              ]
            }
          },
          {
            "name": "run_course_type",
            "in": "query",
            "required": false,
            "description": "Run profile (case-insensitive; comma-separate for several, e.g. Flat,Rolling)",
            "schema": {
              "type": "string",
              "examples": [
                "Flat",
                "Rolling",
                "Hilly"
              ]
            }
          },
          {
            "name": "min_air_temp",
            "in": "query",
            "required": false,
            "description": "Minimum average air temperature, °F",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_water_temp",
            "in": "query",
            "required": false,
            "description": "Minimum average water temperature, °F",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "upcoming",
            "in": "query",
            "required": false,
            "description": "1 or true: drop races dated before today (UTC); TBD dates count as upcoming",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true",
                "0",
                "false"
              ]
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Country, e.g. Spain, United States (case-insensitive; comma-separate for several)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": false,
            "description": "Race month 1-12, or several comma-separated (e.g. 6,7,8). TBD-dated races are excluded when set.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "description": "Earliest race date, YYYY-MM-DD (TBD-dated races excluded)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "description": "Latest race date, YYYY-MM-DD (TBD-dated races excluded)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Words to match in race name, city, country or slug (all words must match)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "wetsuit",
            "in": "query",
            "required": false,
            "description": "1 or true: only races with typical water temperature ≤ 76°F (24°C)",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            }
          },
          {
            "name": "beginner",
            "in": "query",
            "required": false,
            "description": "1 or true: only 5150s and IRONMAN 70.3s with flat bike and flat run",
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Return at most this many races (default: all)",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Skip this many matches (use with limit)",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Races sorted by date (TBD last)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of races in this response"
                    },
                    "total": {
                      "type": "integer",
                      "description": "Total matches before limit/offset"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/events/{slug}": {
      "get": {
        "operationId": "getEvent",
        "summary": "Get one race by slug",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "im-lake-placid"
          }
        ],
        "responses": {
          "200": {
            "description": "The race",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "event": {
                      "$ref": "#/components/schemas/Event"
                    }
                  }
                }
              }
            }
          },
          "301": {
            "description": "Slug was merged into another race; follow Location"
          },
          "404": {
            "description": "Not found"
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "health",
        "summary": "Health check",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Event": {
        "type": "object",
        "required": [
          "slug",
          "event_name",
          "race_type",
          "event_date"
        ],
        "properties": {
          "event_name": {
            "type": "string",
            "description": "Official race name"
          },
          "event_country": {
            "type": "string",
            "description": "Country, or TBD"
          },
          "event_city": {
            "type": "string",
            "description": "City, or TBD"
          },
          "event_continent": {
            "type": "string",
            "description": "Continent, or TBD"
          },
          "event_date": {
            "type": "string",
            "description": "YYYY-MM-DD, or TBD"
          },
          "swim_type": {
            "type": "string",
            "description": "e.g. Ocean, Lake, River, Bay, Sea, Reservoir, Harbor, or TBD"
          },
          "bike_course_type": {
            "type": "string",
            "description": "Flat, Rolling, Hilly, or TBD"
          },
          "run_course_type": {
            "type": "string",
            "description": "Flat, Rolling, Hilly, or TBD"
          },
          "average_air_temperature": {
            "type": "string",
            "description": "e.g. 79F/26C, or TBD"
          },
          "average_water_temperature": {
            "type": "string",
            "description": "e.g. 68F/20C, or TBD"
          },
          "airport_information": {
            "type": "string",
            "description": "Nearest airport, or TBD"
          },
          "event_page_url": {
            "type": "string",
            "description": "Official ironman.com race page"
          },
          "slug": {
            "type": "string",
            "description": "Find My Tris slug; page at https://findmytris.com/events/{slug}"
          },
          "race_type": {
            "type": "string",
            "description": "IRONMAN, IRONMAN 70.3, or 5150"
          },
          "nextEdition": {
            "type": "string",
            "description": "Optional slug of the next edition"
          }
        }
      }
    }
  }
}
