{
  "openapi": "3.1.0",
  "info": {
    "title": "Open Road Motorcycle Tours API",
    "version": "1.0.0",
    "summary": "Read-only access to Open Road's guided and self-guided motorcycle tours in New Zealand and Europe.",
    "description": "Open Road Motorcycle Tours runs guided and self-guided motorcycle tours in New Zealand and Europe.\nThis API exposes the same tours, departure dates, motorcycle fleet and rider reviews that appear on openroad.nz, as JSON.\n\n**Authentication.** None. Every endpoint is public and read-only, and answers cross-origin requests from any host.\n\n**Caching and fair use.** Responses carry a `Cache-Control` header with a shared-cache lifetime between 15 minutes and 24 hours; honour it rather than polling. There is no hard rate limit, but sustained request rates above a few per second may be throttled at the CDN.\n\n**Errors.** Every failure returns JSON in the same envelope, with a stable `error.code`, a human-readable `error.message` and an actionable `error.hint`. Branch on the code, not the message.\n\n**Booking.** This API does not take bookings. Send riders to the `booking_url` on a tour, or to https://openroad.nz/contact.",
    "contact": {
      "name": "Open Road Motorcycle Tours",
      "email": "hello@openroad.nz",
      "url": "https://openroad.nz/developers"
    },
    "termsOfService": "https://openroad.nz/terms-and-conditions"
  },
  "security": [],
  "externalDocs": {
    "description": "Developer and agent documentation",
    "url": "https://openroad.nz/developers"
  },
  "servers": [
    {
      "url": "https://openroad.nz/api/v1",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Discovery",
      "description": "Finding your way around the API."
    },
    {
      "name": "Tours",
      "description": "Tours, their itineraries and their prices."
    },
    {
      "name": "Availability",
      "description": "Scheduled departures and what is left on them."
    },
    {
      "name": "Regions",
      "description": "The parts of the world tours run in."
    },
    {
      "name": "Bikes",
      "description": "The motorcycles available to ride."
    },
    {
      "name": "Reviews",
      "description": "What past riders said."
    }
  ],
  "paths": {
    "/": {
      "get": {
        "operationId": "getApiIndex",
        "summary": "List the available API endpoints",
        "description": "Returns a machine-readable index of every endpoint in this API, plus links to the OpenAPI document, the human developer documentation, and the llms.txt guidance file. Call this first if you are discovering the API without the spec.",
        "tags": [
          "Discovery"
        ],
        "responses": {
          "200": {
            "description": "List the available API endpoints. Cached for 86400 seconds by shared caches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A single-resource response.",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApiIndex"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "405": {
            "description": "The API is read-only; only GET and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be completed. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/tours": {
      "get": {
        "operationId": "listTours",
        "summary": "List bookable motorcycle tours",
        "description": "Returns every currently offered motorcycle tour, with its region, duration, starting price in New Zealand dollars, and the URL of its page on openroad.nz. Use this to answer questions about what tours exist, then call getTourBySlug for the full itinerary.",
        "tags": [
          "Tours"
        ],
        "parameters": [
          {
            "name": "region",
            "in": "query",
            "required": false,
            "description": "Restrict results to one region slug, as returned by listRegions (for example `new-zealand` or `europe`).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Restrict results to guided tours (a guide rides with the group) or self-guided tours (a planned route ridden independently).",
            "schema": {
              "type": "string",
              "enum": [
                "guided",
                "self-guided"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return, from 1 to 100. Omit to return every item.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List bookable motorcycle tours. Cached for 3600 seconds by shared caches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A list response.",
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The items returned.",
                      "items": {
                        "$ref": "#/components/schemas/TourSummary"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "description": "Details about the list itself.",
                      "properties": {
                        "count": {
                          "type": "integer",
                          "description": "How many items are in `data`."
                        }
                      },
                      "required": [
                        "count"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was missing, malformed or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The API is read-only; only GET and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be completed. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/tours/{slug}": {
      "get": {
        "operationId": "getTourBySlug",
        "summary": "Get one tour with its full day-by-day itinerary",
        "description": "Returns the complete detail for a single tour: description, highlights, what is and is not included, all prices in New Zealand dollars, images, a booking URL, and the day-by-day itinerary with each riding leg's start and end points and meals included.",
        "tags": [
          "Tours"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "URL slug of the tour, as returned in the `slug` field of `listTours` (for example `southern-alps-explorer`).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get one tour with its full day-by-day itinerary. Cached for 3600 seconds by shared caches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A single-resource response.",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Tour"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was missing, malformed or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No resource matches the identifier in the path or query.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The API is read-only; only GET and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be completed. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/tours/{slug}/dates": {
      "get": {
        "operationId": "listTourDates",
        "summary": "List upcoming departure dates and per-bike pricing for a tour",
        "description": "Returns the future departures for one tour with their booking status, plus the price and remaining availability of each motorcycle on that departure. This is the endpoint to call when someone asks whether a tour runs on particular dates or what a specific bike costs.",
        "tags": [
          "Tours",
          "Availability"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "URL slug of the tour, as returned in the `slug` field of `listTours` (for example `southern-alps-explorer`).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List upcoming departure dates and per-bike pricing for a tour. Cached for 900 seconds by shared caches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A list response.",
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The items returned.",
                      "items": {
                        "$ref": "#/components/schemas/TourDate"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "description": "Details about the list itself.",
                      "properties": {
                        "count": {
                          "type": "integer",
                          "description": "How many items are in `data`."
                        }
                      },
                      "required": [
                        "count"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was missing, malformed or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No resource matches the identifier in the path or query.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The API is read-only; only GET and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be completed. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/regions": {
      "get": {
        "operationId": "listRegions",
        "summary": "List the regions tours are offered in",
        "description": "Returns every region Open Road runs tours in, with a description and the URL of its landing page. Use the `slug` values to filter listTours by region.",
        "tags": [
          "Regions"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return, from 1 to 100. Omit to return every item.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the regions tours are offered in. Cached for 86400 seconds by shared caches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A list response.",
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The items returned.",
                      "items": {
                        "$ref": "#/components/schemas/Region"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "description": "Details about the list itself.",
                      "properties": {
                        "count": {
                          "type": "integer",
                          "description": "How many items are in `data`."
                        }
                      },
                      "required": [
                        "count"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was missing, malformed or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The API is read-only; only GET and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be completed. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/bikes": {
      "get": {
        "operationId": "listBikes",
        "summary": "List the motorcycles available on tour",
        "description": "Returns the motorcycle fleet with engine capacity, power, torque, weight, seat height, fuel capacity, luggage and wind-protection details. Use this to compare bikes on specification before checking their price on a departure via listTourDates.",
        "tags": [
          "Bikes"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return, from 1 to 100. Omit to return every item.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List the motorcycles available on tour. Cached for 86400 seconds by shared caches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A list response.",
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The items returned.",
                      "items": {
                        "$ref": "#/components/schemas/Bike"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "description": "Details about the list itself.",
                      "properties": {
                        "count": {
                          "type": "integer",
                          "description": "How many items are in `data`."
                        }
                      },
                      "required": [
                        "count"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was missing, malformed or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The API is read-only; only GET and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be completed. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/bikes/{slug}": {
      "get": {
        "operationId": "getBikeBySlug",
        "summary": "Get one motorcycle by slug",
        "description": "Returns the full specification and images for a single motorcycle in the fleet.",
        "tags": [
          "Bikes"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "URL slug of the motorcycle, as returned in the `slug` field of `listBikes` (for example `bmw-r1250gs`).",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get one motorcycle by slug. Cached for 86400 seconds by shared caches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A single-resource response.",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Bike"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was missing, malformed or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No resource matches the identifier in the path or query.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The API is read-only; only GET and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be completed. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/reviews": {
      "get": {
        "operationId": "listReviews",
        "summary": "List customer reviews",
        "description": "Returns published rider reviews with their rating out of five, the author's country, the review date, and the tour reviewed where one was recorded. Use the `tour` parameter to quote reviews for a specific tour.",
        "tags": [
          "Reviews"
        ],
        "parameters": [
          {
            "name": "tour",
            "in": "query",
            "required": false,
            "description": "Restrict results to reviews of one tour, given its slug as returned by listTours.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of items to return, from 1 to 100. Omit to return every item.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List customer reviews. Cached for 3600 seconds by shared caches.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "A list response.",
                  "properties": {
                    "data": {
                      "type": "array",
                      "description": "The items returned.",
                      "items": {
                        "$ref": "#/components/schemas/Review"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "description": "Details about the list itself.",
                      "properties": {
                        "count": {
                          "type": "integer",
                          "description": "How many items are in `data`."
                        }
                      },
                      "required": [
                        "count"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was missing, malformed or out of range.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No resource matches the identifier in the path or query.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The API is read-only; only GET and OPTIONS are accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The request could not be completed. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "description": "The error envelope returned by every failing request. The body is always JSON, never HTML.",
        "properties": {
          "error": {
            "type": "object",
            "description": "Details of what went wrong and how to recover.",
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error code. Branch on this rather than on the message.",
                "enum": [
                  "invalid_query",
                  "not_found",
                  "method_not_allowed",
                  "internal_error",
                  "upstream_unavailable"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable description of what went wrong."
              },
              "hint": {
                "type": "string",
                "description": "Concrete next step that would resolve the error."
              },
              "documentation_url": {
                "type": "string",
                "description": "URL of the developer documentation.",
                "format": "uri"
              }
            },
            "required": [
              "code",
              "message",
              "hint",
              "documentation_url"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ApiIndex": {
        "type": "object",
        "description": "A machine-readable index of the API and its related resources.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the API."
          },
          "description": {
            "type": "string",
            "description": "What the API provides and whether authentication is required."
          },
          "base_url": {
            "type": "string",
            "description": "Base URL every endpoint path is relative to.",
            "format": "uri"
          },
          "openapi_url": {
            "type": "string",
            "description": "URL of this OpenAPI document.",
            "format": "uri"
          },
          "documentation_url": {
            "type": "string",
            "description": "URL of the human-readable developer documentation.",
            "format": "uri"
          },
          "llms_txt_url": {
            "type": "string",
            "description": "URL of the llms.txt guidance file for agents.",
            "format": "uri"
          },
          "agent_card_url": {
            "type": "string",
            "description": "URL of the A2A agent card.",
            "format": "uri"
          },
          "endpoints": {
            "type": "array",
            "description": "Every operation this API exposes.",
            "items": {
              "type": "object",
              "description": "One operation.",
              "properties": {
                "operation_id": {
                  "type": "string",
                  "description": "The operationId used in this OpenAPI document."
                },
                "method": {
                  "type": "string",
                  "description": "HTTP method for the operation."
                },
                "url": {
                  "type": "string",
                  "description": "Absolute URL of the operation.",
                  "format": "uri"
                },
                "summary": {
                  "type": "string",
                  "description": "One-line description of what the operation returns."
                }
              },
              "required": [
                "operation_id",
                "method",
                "url",
                "summary"
              ]
            }
          }
        },
        "required": [
          "name",
          "base_url",
          "openapi_url",
          "documentation_url",
          "endpoints"
        ]
      },
      "TourSummary": {
        "type": "object",
        "description": "A motorcycle tour as it appears in a list, without the itinerary.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier for the tour. Use this when linking to the booking form."
          },
          "slug": {
            "type": "string",
            "description": "URL slug for the tour. Pass this to getTourBySlug and listTourDates."
          },
          "name": {
            "type": "string",
            "description": "Display name of the tour, for example \"Southern Alps Explorer\"."
          },
          "url": {
            "type": "string",
            "description": "Absolute URL of the tour's page on openroad.nz.",
            "format": "uri"
          },
          "region_slug": {
            "type": "string",
            "description": "Slug of the region the tour runs in, as returned by listRegions."
          },
          "tour_types": {
            "type": "array",
            "description": "How the tour can be ridden. `guided` means a guide rides with the group; `self-guided` means the route is ridden independently. A tour may be offered both ways.",
            "items": {
              "type": "string",
              "enum": [
                "guided",
                "self-guided"
              ]
            }
          },
          "summary": {
            "type": "string",
            "description": "One-line plain-text summary of the tour."
          },
          "number_of_days": {
            "type": "integer",
            "description": "Total length of the tour in days, including rest days."
          },
          "number_of_days_riding": {
            "type": "integer",
            "description": "Number of days of the tour spent riding."
          },
          "price_from_nzd": {
            "type": "number",
            "description": "Lowest per-rider price for the tour, in New Zealand dollars."
          },
          "is_popular": {
            "type": "boolean",
            "description": "Whether Open Road features this tour as a popular choice."
          },
          "on_sale": {
            "type": "boolean",
            "description": "Whether the tour is currently discounted."
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Absolute URL of the tour's lead image, or null if it has none."
          }
        },
        "required": [
          "id",
          "slug",
          "name",
          "url",
          "region_slug",
          "tour_types",
          "number_of_days",
          "price_from_nzd"
        ]
      },
      "Tour": {
        "type": "object",
        "description": "A motorcycle tour with its full description, pricing, images and day-by-day itinerary.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier for the tour. Use this when linking to the booking form."
          },
          "slug": {
            "type": "string",
            "description": "URL slug for the tour. Pass this to getTourBySlug and listTourDates."
          },
          "name": {
            "type": "string",
            "description": "Display name of the tour, for example \"Southern Alps Explorer\"."
          },
          "url": {
            "type": "string",
            "description": "Absolute URL of the tour's page on openroad.nz.",
            "format": "uri"
          },
          "region_slug": {
            "type": "string",
            "description": "Slug of the region the tour runs in, as returned by listRegions."
          },
          "tour_types": {
            "type": "array",
            "description": "How the tour can be ridden. `guided` means a guide rides with the group; `self-guided` means the route is ridden independently. A tour may be offered both ways.",
            "items": {
              "type": "string",
              "enum": [
                "guided",
                "self-guided"
              ]
            }
          },
          "summary": {
            "type": "string",
            "description": "One-line plain-text summary of the tour."
          },
          "number_of_days": {
            "type": "integer",
            "description": "Total length of the tour in days, including rest days."
          },
          "number_of_days_riding": {
            "type": "integer",
            "description": "Number of days of the tour spent riding."
          },
          "price_from_nzd": {
            "type": "number",
            "description": "Lowest per-rider price for the tour, in New Zealand dollars."
          },
          "is_popular": {
            "type": "boolean",
            "description": "Whether Open Road features this tour as a popular choice."
          },
          "on_sale": {
            "type": "boolean",
            "description": "Whether the tour is currently discounted."
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Absolute URL of the tour's lead image, or null if it has none."
          },
          "description": {
            "type": "string",
            "description": "Full plain-text description of the tour."
          },
          "highlights": {
            "type": "array",
            "description": "Notable places or experiences on the tour.",
            "items": {
              "type": "string"
            }
          },
          "includes": {
            "type": "array",
            "description": "What the tour price covers.",
            "items": {
              "type": "string"
            }
          },
          "excludes": {
            "type": "array",
            "description": "What the tour price does not cover.",
            "items": {
              "type": "string"
            }
          },
          "pillion_price_from_nzd": {
            "type": "number",
            "description": "Lowest price for a pillion passenger, in New Zealand dollars."
          },
          "single_room_price_from_nzd": {
            "type": "number",
            "description": "Lowest single-room supplement, in New Zealand dollars."
          },
          "image_urls": {
            "type": "array",
            "description": "Absolute URLs of every image for the tour.",
            "items": {
              "type": "string"
            }
          },
          "booking_url": {
            "type": "string",
            "description": "Absolute URL of the booking form, pre-filled with this tour.",
            "format": "uri"
          },
          "itinerary": {
            "type": "array",
            "description": "The tour day by day, ordered from day one.",
            "items": {
              "$ref": "#/components/schemas/TourLeg"
            }
          }
        },
        "required": [
          "id",
          "slug",
          "name",
          "url",
          "region_slug",
          "tour_types",
          "description",
          "number_of_days",
          "price_from_nzd",
          "booking_url",
          "itinerary"
        ]
      },
      "TourLeg": {
        "type": "object",
        "description": "One day of a tour's itinerary.",
        "properties": {
          "day": {
            "type": "integer",
            "description": "Day number within the tour, starting at 1."
          },
          "name": {
            "type": "string",
            "description": "Title of the day, usually its start and end points."
          },
          "description": {
            "type": "string",
            "description": "Plain-text description of the day."
          },
          "type": {
            "type": "string",
            "description": "Whether the day is spent riding or resting.",
            "enum": [
              "riding_day",
              "rest_day"
            ]
          },
          "route": {
            "type": [
              "object",
              "null"
            ],
            "description": "The route ridden on this day, or null on a rest day or where no route is recorded.",
            "properties": {
              "name": {
                "type": "string",
                "description": "Name of the route."
              },
              "from": {
                "type": "string",
                "description": "Where the day's ride starts."
              },
              "to": {
                "type": "string",
                "description": "Where the day's ride ends."
              },
              "description": {
                "type": "string",
                "description": "Plain-text description of the route."
              },
              "meals_included": {
                "type": "object",
                "description": "Which meals the tour price covers on this day.",
                "properties": {
                  "breakfast": {
                    "type": "boolean",
                    "description": "Whether breakfast is included."
                  },
                  "lunch": {
                    "type": "boolean",
                    "description": "Whether lunch is included."
                  },
                  "dinner": {
                    "type": "boolean",
                    "description": "Whether dinner is included."
                  }
                },
                "required": [
                  "breakfast",
                  "lunch",
                  "dinner"
                ]
              }
            },
            "required": [
              "name",
              "from",
              "to",
              "meals_included"
            ]
          }
        },
        "required": [
          "day",
          "name",
          "type"
        ]
      },
      "TourDate": {
        "type": "object",
        "description": "A scheduled departure of a tour, with the price and availability of each motorcycle on it.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier for the departure."
          },
          "start": {
            "type": "string",
            "description": "First day of the departure, as an ISO 8601 date.",
            "format": "date"
          },
          "finish": {
            "type": "string",
            "description": "Last day of the departure, as an ISO 8601 date.",
            "format": "date"
          },
          "status": {
            "type": "string",
            "description": "Booking status of the departure. `active` is open, `limited_spaces` is nearly full, `full` takes no more riders, `cancelled` will not run.",
            "enum": [
              "active",
              "full",
              "limited_spaces",
              "cancelled"
            ]
          },
          "pillion_amount_nzd": {
            "type": "number",
            "description": "Price for a pillion passenger on this departure, in New Zealand dollars."
          },
          "single_room_amount_nzd": {
            "type": "number",
            "description": "Single-room supplement for this departure, in New Zealand dollars."
          },
          "bikes": {
            "type": "array",
            "description": "Price and remaining availability of each motorcycle on this departure.",
            "items": {
              "$ref": "#/components/schemas/BikePrice"
            }
          }
        },
        "required": [
          "id",
          "start",
          "finish",
          "status",
          "bikes"
        ]
      },
      "Region": {
        "type": "object",
        "description": "A part of the world Open Road runs tours in.",
        "properties": {
          "slug": {
            "type": "string",
            "description": "URL slug for the region. Pass this as the `region` filter on listTours."
          },
          "name": {
            "type": "string",
            "description": "Display name of the region."
          },
          "description": {
            "type": "string",
            "description": "Plain-text description of riding in the region."
          },
          "url": {
            "type": "string",
            "description": "Absolute URL of the region's page on openroad.nz.",
            "format": "uri"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Absolute URL of the region's lead image, or null."
          }
        },
        "required": [
          "slug",
          "name",
          "url"
        ]
      },
      "Bike": {
        "type": "object",
        "description": "A motorcycle available to ride on tour.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier for the motorcycle."
          },
          "slug": {
            "type": "string",
            "description": "URL slug for the motorcycle. Pass this to getBikeBySlug."
          },
          "name": {
            "type": "string",
            "description": "Manufacturer and model, for example \"BMW R 1250 GS\"."
          },
          "url": {
            "type": "string",
            "description": "Absolute URL of the motorcycle's page on openroad.nz.",
            "format": "uri"
          },
          "summary": {
            "type": "string",
            "description": "One-line plain-text summary of the motorcycle."
          },
          "description": {
            "type": "string",
            "description": "Full plain-text description of the motorcycle."
          },
          "engine_capacity_cc": {
            "type": "number",
            "description": "Engine displacement in cubic centimetres."
          },
          "power": {
            "type": "number",
            "description": "Manufacturer-quoted peak power, as published by Open Road."
          },
          "torque_nm": {
            "type": "number",
            "description": "Peak torque in newton metres."
          },
          "torque_revs": {
            "type": "number",
            "description": "Engine speed in rpm at which peak torque is produced."
          },
          "weight_kg": {
            "type": "number",
            "description": "Kerb weight in kilograms."
          },
          "seat_height_mm": {
            "type": "number",
            "description": "Seat height in millimetres."
          },
          "fuel_capacity_litres": {
            "type": "number",
            "description": "Usable fuel capacity in litres."
          },
          "engine_configuration": {
            "type": "string",
            "description": "Engine layout, for example \"Boxer twin\"."
          },
          "final_drive": {
            "type": "string",
            "description": "Final drive type, for example \"Shaft\" or \"Chain\"."
          },
          "luggage_system": {
            "type": "string",
            "description": "Luggage fitted to the motorcycle on tour."
          },
          "wind_protection": {
            "type": "string",
            "description": "Wind protection fitted to the motorcycle."
          },
          "other_features": {
            "type": "string",
            "description": "Any further equipment fitted to the motorcycle."
          },
          "image_urls": {
            "type": "array",
            "description": "Absolute URLs of every image for the motorcycle.",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "slug",
          "name",
          "url",
          "engine_capacity_cc"
        ]
      },
      "Review": {
        "type": "object",
        "description": "A published review left by a rider.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable identifier for the review."
          },
          "author": {
            "type": "string",
            "description": "Name the reviewer gave."
          },
          "country": {
            "type": "string",
            "description": "Country the reviewer travelled from."
          },
          "date": {
            "type": "string",
            "description": "Date the review was left, as an ISO 8601 date.",
            "format": "date"
          },
          "rating": {
            "type": "integer",
            "description": "Rating out of five.",
            "minimum": 1,
            "maximum": 5
          },
          "text": {
            "type": "string",
            "description": "The review text as written."
          },
          "tour": {
            "type": [
              "object",
              "null"
            ],
            "description": "The tour reviewed, or null where the review was not recorded against a specific tour.",
            "properties": {
              "slug": {
                "type": "string",
                "description": "URL slug of the reviewed tour."
              },
              "name": {
                "type": "string",
                "description": "Name of the reviewed tour."
              },
              "url": {
                "type": "string",
                "description": "Absolute URL of the reviewed tour.",
                "format": "uri"
              }
            },
            "required": [
              "slug",
              "name",
              "url"
            ]
          }
        },
        "required": [
          "id",
          "author",
          "date",
          "rating",
          "text"
        ]
      },
      "BikePrice": {
        "type": "object",
        "description": "What one motorcycle costs on a given departure, and how many are left.",
        "properties": {
          "bike_slug": {
            "type": "string",
            "description": "URL slug of the motorcycle, as returned by listBikes."
          },
          "bike_name": {
            "type": "string",
            "description": "Manufacturer and model of the motorcycle."
          },
          "amount_nzd": {
            "type": "number",
            "description": "Price of the tour on this motorcycle, in New Zealand dollars."
          },
          "bikes_available": {
            "type": "integer",
            "description": "How many of this motorcycle remain unbooked on this departure."
          }
        },
        "required": [
          "bike_slug",
          "bike_name",
          "amount_nzd",
          "bikes_available"
        ]
      }
    }
  }
}