{
  "openapi": "3.1.0",
  "info": {
    "title": "Pre-entries public API",
    "version": "1.0.0",
    "description": "Read-only data about orienteering events entered on Pre-entries: dates, entry windows, fees, courses, classes, clubs and public start lists. No key is needed. Responses are cached for up to a minute. Each address may make 60 uncached requests a minute. Money is in pence.",
    "contact": {
      "url": "https://www.pre-entries.com/developers"
    }
  },
  "servers": [
    {
      "url": "https://www.pre-entries.com/api/v1"
    }
  ],
  "paths": {
    "/events": {
      "get": {
        "summary": "List events",
        "description": "Published events on the public list, in date order. Unlisted events are left out. Defaults to today onwards.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "description": "Events ending on or after this date (YYYY-MM-DD). Default today.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Events starting on or before this date (YYYY-MM-DD).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "club",
            "in": "query",
            "description": "Only this club’s events, by club slug (as in /c/{slug}).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "count"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EventSummary"
                      }
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "A date was not written YYYY-MM-DD.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No club has that slug.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address. Wait for Retry-After seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/events/{id}": {
      "get": {
        "summary": "Get an event",
        "description": "One event with its courses, classes, fees and location. A multi-day event lists its days, each with its own courses, classes and fees.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The event id (a UUID), as in the event page address /e/{id}.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            }
          },
          "404": {
            "description": "No published event has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address. Wait for Retry-After seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/events/{id}/start-list": {
      "get": {
        "summary": "Get an event’s start list",
        "description": "The public start list: the same names, clubs, age classes, SI cards and start details as the start list page. Cancelled entries are left out.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The event id (a UUID), as in the event page address /e/{id}.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartListResponse"
                }
              }
            }
          },
          "404": {
            "description": "No published event has that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address. Wait for Retry-After seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/clubs": {
      "get": {
        "summary": "List clubs",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "count"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Club"
                      }
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address. Wait for Retry-After seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/clubs/{slug}": {
      "get": {
        "summary": "Get a club",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "The club slug, as in /c/{slug}. The acronym also works.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Club"
                }
              }
            }
          },
          "404": {
            "description": "No club has that slug.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many requests from this address. Wait for Retry-After seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "status",
              "message"
            ],
            "properties": {
              "status": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "ClubRef": {
        "type": "object",
        "required": [
          "name",
          "acronym",
          "slug",
          "url"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "acronym": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Club": {
        "type": "object",
        "required": [
          "name",
          "acronym",
          "slug",
          "url",
          "logoUrl",
          "homepage",
          "links"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "acronym": {
            "type": "string"
          },
          "slug": {
            "type": [
              "string",
              "null"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "logoUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "homepage": {
            "type": [
              "string",
              "null"
            ]
          },
          "links": {
            "type": "object",
            "required": [
              "self",
              "events"
            ],
            "properties": {
              "self": {
                "type": "string"
              },
              "events": {
                "type": "string"
              }
            }
          }
        }
      },
      "EntryWindow": {
        "type": "object",
        "required": [
          "state",
          "feePeriod",
          "opensAt",
          "earlyClosesAt",
          "standardClosesAt",
          "closesAt",
          "entryOnTheDay",
          "codeRequired"
        ],
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "not_open",
              "open",
              "closed",
              "paused"
            ]
          },
          "feePeriod": {
            "type": "string",
            "enum": [
              "early",
              "standard",
              "late"
            ]
          },
          "opensAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "ISO 8601, UTC."
          },
          "earlyClosesAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "ISO 8601, UTC."
          },
          "standardClosesAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "ISO 8601, UTC."
          },
          "closesAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The final close. ISO 8601, UTC."
          },
          "entryOnTheDay": {
            "type": "boolean"
          },
          "codeRequired": {
            "type": "boolean"
          }
        }
      },
      "EventSummary": {
        "type": "object",
        "required": [
          "id",
          "name",
          "date",
          "endDate",
          "timeZone",
          "venue",
          "type",
          "multiDayKind",
          "format",
          "level",
          "disciplines",
          "club",
          "entries",
          "updatedAt",
          "links"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "YYYY-MM-DD."
          },
          "endDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "YYYY-MM-DD."
          },
          "timeZone": {
            "type": "string"
          },
          "venue": {
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "type": "string"
          },
          "multiDayKind": {
            "type": [
              "string",
              "null"
            ]
          },
          "format": {
            "type": "string",
            "enum": [
              "individual",
              "relay"
            ]
          },
          "level": {
            "type": [
              "string",
              "null"
            ]
          },
          "disciplines": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "club": {
            "$ref": "#/components/schemas/ClubRef"
          },
          "entries": {
            "$ref": "#/components/schemas/EntryWindow"
          },
          "updatedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "ISO 8601, UTC."
          },
          "links": {
            "type": "object",
            "required": [
              "self",
              "page",
              "enter",
              "startList",
              "apiStartList"
            ],
            "properties": {
              "self": {
                "type": "string"
              },
              "page": {
                "type": "string"
              },
              "enter": {
                "type": "string"
              },
              "startList": {
                "type": "string"
              },
              "apiStartList": {
                "type": "string"
              }
            }
          }
        }
      },
      "Course": {
        "type": "object",
        "required": [
          "id",
          "name",
          "lengthKm",
          "climbM",
          "difficulty",
          "colour",
          "note"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "lengthKm": {
            "type": [
              "number",
              "null"
            ]
          },
          "climbM": {
            "type": [
              "number",
              "null"
            ]
          },
          "difficulty": {
            "type": "string"
          },
          "colour": {
            "type": [
              "string",
              "null"
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "Class": {
        "type": "object",
        "required": [
          "id",
          "name",
          "courseId",
          "legs",
          "massStart"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "courseId": {
            "type": [
              "string",
              "null"
            ]
          },
          "legs": {
            "type": [
              "integer",
              "null"
            ]
          },
          "massStart": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "FeeBand": {
        "type": "object",
        "required": [
          "memberPence",
          "nonMemberPence"
        ],
        "properties": {
          "memberPence": {
            "type": "integer"
          },
          "nonMemberPence": {
            "type": "integer"
          }
        }
      },
      "FeeBands": {
        "type": "object",
        "required": [
          "senior",
          "junior",
          "student"
        ],
        "properties": {
          "senior": {
            "$ref": "#/components/schemas/FeeBand"
          },
          "junior": {
            "$ref": "#/components/schemas/FeeBand"
          },
          "student": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/FeeBand"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "FeeCategory": {
        "type": "object",
        "required": [
          "label",
          "amountPence"
        ],
        "properties": {
          "label": {
            "type": "string"
          },
          "amountPence": {
            "type": "integer"
          }
        }
      },
      "PeriodRule": {
        "description": "How a period differs from standard fees. Null when it does not.",
        "oneOf": [
          {
            "type": "null"
          },
          {
            "type": "object",
            "required": [
              "kind",
              "bands"
            ],
            "properties": {
              "kind": {
                "const": "fees"
              },
              "bands": {
                "$ref": "#/components/schemas/FeeBands"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "kind",
              "categories"
            ],
            "properties": {
              "kind": {
                "const": "fees"
              },
              "categories": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FeeCategory"
                }
              }
            }
          },
          {
            "type": "object",
            "required": [
              "kind",
              "amountPence"
            ],
            "properties": {
              "kind": {
                "enum": [
                  "discount",
                  "premium"
                ]
              },
              "amountPence": {
                "type": "integer"
              }
            }
          }
        ]
      },
      "Fees": {
        "type": "object",
        "description": "All money in pence. range prices every choice by the checkout rules, before extras and discount codes.",
        "required": [
          "currency",
          "per",
          "range",
          "mode",
          "seniorFromAge",
          "standard",
          "early",
          "late",
          "note"
        ],
        "properties": {
          "currency": {
            "const": "GBP"
          },
          "per": {
            "type": "string",
            "enum": [
              "entry",
              "team"
            ]
          },
          "range": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "period",
                  "minPence",
                  "maxPence"
                ],
                "properties": {
                  "period": {
                    "type": "string",
                    "enum": [
                      "early",
                      "standard",
                      "late"
                    ]
                  },
                  "minPence": {
                    "type": "integer"
                  },
                  "maxPence": {
                    "type": "integer"
                  }
                }
              }
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "age_and_membership",
              "categories"
            ]
          },
          "seniorFromAge": {
            "type": [
              "integer",
              "null"
            ]
          },
          "standard": {
            "oneOf": [
              {
                "type": "object",
                "required": [
                  "bands"
                ],
                "properties": {
                  "bands": {
                    "$ref": "#/components/schemas/FeeBands"
                  }
                }
              },
              {
                "type": "object",
                "required": [
                  "categories"
                ],
                "properties": {
                  "categories": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/FeeCategory"
                    }
                  }
                }
              }
            ]
          },
          "early": {
            "$ref": "#/components/schemas/PeriodRule"
          },
          "late": {
            "$ref": "#/components/schemas/PeriodRule"
          },
          "note": {
            "type": "string"
          }
        }
      },
      "Point": {
        "type": "object",
        "required": [
          "label",
          "lat",
          "lng"
        ],
        "properties": {
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "lat": {
            "type": "number"
          },
          "lng": {
            "type": "number"
          }
        }
      },
      "Location": {
        "type": "object",
        "required": [
          "gridRef",
          "gps",
          "assembly",
          "parking"
        ],
        "properties": {
          "gridRef": {
            "type": [
              "string",
              "null"
            ]
          },
          "gps": {
            "type": [
              "string",
              "null"
            ]
          },
          "assembly": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Point"
              },
              {
                "type": "null"
              }
            ]
          },
          "parking": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Point"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Starts": {
        "type": "object",
        "required": [
          "first",
          "last",
          "mode"
        ],
        "properties": {
          "first": {
            "type": [
              "string",
              "null"
            ]
          },
          "last": {
            "type": [
              "string",
              "null"
            ]
          },
          "mode": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "EventDay": {
        "type": "object",
        "required": [
          "id",
          "heading",
          "date",
          "venue",
          "location",
          "starts",
          "open",
          "courses",
          "classes",
          "fees"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "heading": {
            "type": "string"
          },
          "date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "YYYY-MM-DD."
          },
          "venue": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "$ref": "#/components/schemas/Location"
          },
          "starts": {
            "$ref": "#/components/schemas/Starts"
          },
          "open": {
            "type": "boolean"
          },
          "courses": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Course"
            }
          },
          "classes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Class"
            }
          },
          "fees": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Fees"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Event": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EventSummary"
          },
          {
            "type": "object",
            "required": [
              "description",
              "location",
              "starts",
              "choice",
              "courses",
              "classes",
              "fees",
              "days"
            ],
            "properties": {
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "location": {
                "$ref": "#/components/schemas/Location"
              },
              "starts": {
                "$ref": "#/components/schemas/Starts"
              },
              "choice": {
                "type": "string",
                "enum": [
                  "course",
                  "class",
                  "none"
                ]
              },
              "courses": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Course"
                }
              },
              "classes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Class"
                }
              },
              "fees": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/Fees"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "days": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/EventDay"
                    }
                  }
                ]
              }
            }
          }
        ]
      },
      "Competitor": {
        "type": "object",
        "required": [
          "firstName",
          "lastName",
          "club",
          "ageClass",
          "siCard",
          "nonCompetitive"
        ],
        "properties": {
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "club": {
            "type": [
              "string",
              "null"
            ]
          },
          "ageClass": {
            "type": [
              "string",
              "null"
            ]
          },
          "siCard": {
            "type": [
              "string",
              "null"
            ]
          },
          "nonCompetitive": {
            "type": "boolean"
          }
        }
      },
      "IndividualStart": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Competitor"
          },
          {
            "type": "object",
            "required": [
              "course",
              "class",
              "startTime",
              "startBlock",
              "startPreference",
              "bib",
              "groupWith"
            ],
            "properties": {
              "course": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "class": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "startTime": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "startBlock": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "startPreference": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "bib": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "groupWith": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        ]
      },
      "RelayTeam": {
        "type": "object",
        "required": [
          "teamNumber",
          "teamName",
          "class",
          "massStart",
          "nonCompetitive",
          "legs"
        ],
        "properties": {
          "teamNumber": {
            "type": [
              "integer",
              "null"
            ]
          },
          "teamName": {
            "type": [
              "string",
              "null"
            ]
          },
          "class": {
            "type": [
              "string",
              "null"
            ]
          },
          "massStart": {
            "type": [
              "string",
              "null"
            ]
          },
          "nonCompetitive": {
            "type": "boolean"
          },
          "legs": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/Competitor"
                },
                {
                  "type": "object",
                  "required": [
                    "leg",
                    "doubleRunOfLeg"
                  ],
                  "properties": {
                    "leg": {
                      "type": "integer"
                    },
                    "doubleRunOfLeg": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "StartList": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "format",
              "count",
              "entries"
            ],
            "properties": {
              "format": {
                "const": "individual"
              },
              "count": {
                "type": "integer"
              },
              "entries": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/IndividualStart"
                }
              }
            }
          },
          {
            "type": "object",
            "required": [
              "format",
              "count",
              "teams"
            ],
            "properties": {
              "format": {
                "const": "relay"
              },
              "count": {
                "type": "integer"
              },
              "teams": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/RelayTeam"
                }
              }
            }
          }
        ]
      },
      "StartListResponse": {
        "description": "A single event: format individual or relay with days null. A multi-day event: format multi_day and one start list per day.",
        "oneOf": [
          {
            "allOf": [
              {
                "type": "object",
                "required": [
                  "event",
                  "days"
                ],
                "properties": {
                  "event": {
                    "type": "object",
                    "required": [
                      "id",
                      "name",
                      "date"
                    ],
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "date": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date",
                        "description": "YYYY-MM-DD."
                      }
                    }
                  },
                  "days": {
                    "type": "null"
                  }
                }
              },
              {
                "$ref": "#/components/schemas/StartList"
              }
            ]
          },
          {
            "type": "object",
            "required": [
              "event",
              "format",
              "count",
              "days"
            ],
            "properties": {
              "event": {
                "type": "object",
                "required": [
                  "id",
                  "name",
                  "date"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "date": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date",
                    "description": "YYYY-MM-DD."
                  }
                }
              },
              "format": {
                "const": "multi_day"
              },
              "count": {
                "type": "integer"
              },
              "days": {
                "type": "array",
                "items": {
                  "allOf": [
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "heading",
                        "date"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "heading": {
                          "type": "string"
                        },
                        "date": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date",
                          "description": "YYYY-MM-DD."
                        }
                      }
                    },
                    {
                      "$ref": "#/components/schemas/StartList"
                    }
                  ]
                }
              }
            }
          }
        ]
      }
    }
  }
}