{
  "openapi": "3.1.0",
  "info": {
    "title": "Vulcani Aeolian Boat Rentals API",
    "version": "1.0.0",
    "summary": "Read-only data about boat tours and dinghy rentals in the Aeolian Islands.",
    "description": "Public, read-only, no authentication. Rate limit: 60 requests per minute per IP. Errors use application/problem+json (RFC 9457). Bookings happen on WhatsApp, not via the API.",
    "contact": {
      "name": "Vulcani Aeolian Boat Rentals",
      "url": "https://vulcaniboatrentals.com/contact/"
    }
  },
  "externalDocs": {
    "description": "Developer docs",
    "url": "https://vulcaniboatrentals.com/docs/"
  },
  "servers": [
    {
      "url": "https://vulcaniboatrentals.com"
    }
  ],
  "security": [],
  "paths": {
    "/api/v1/info": {
      "get": {
        "operationId": "getBusinessInfo",
        "summary": "Business information",
        "description": "Contacts, booking method, address and coordinates of the departure pier, hours, languages and islands served.",
        "tags": [
          "business"
        ],
        "responses": {
          "200": {
            "description": "Business information",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds until reset (t) for the current window.",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";r=59;t=42"
              },
              "RateLimit-Policy": {
                "description": "Quota (q) and window in seconds (w).",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";q=60;w=60"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessInfo"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds until reset (t) for the current window.",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";r=59;t=42"
              },
              "RateLimit-Policy": {
                "description": "Quota (q) and window in seconds (w).",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";q=60;w=60"
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/experiences": {
      "get": {
        "operationId": "listExperiences",
        "summary": "List boat experiences",
        "description": "The boat tours and licence-free dinghy rentals on offer.",
        "tags": [
          "catalog"
        ],
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Response language",
            "schema": {
              "type": "string",
              "enum": [
                "it",
                "en"
              ],
              "default": "it"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Experiences",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds until reset (t) for the current window.",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";r=59;t=42"
              },
              "RateLimit-Policy": {
                "description": "Quota (q) and window in seconds (w).",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";q=60;w=60"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExperienceList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds until reset (t) for the current window.",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";r=59;t=42"
              },
              "RateLimit-Policy": {
                "description": "Quota (q) and window in seconds (w).",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";q=60;w=60"
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/faq": {
      "get": {
        "operationId": "listFaq",
        "summary": "List frequently asked questions",
        "description": "Questions and answers about prices, licence, departure point, islands, weather, what to bring and languages.",
        "tags": [
          "catalog"
        ],
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "Response language",
            "schema": {
              "type": "string",
              "enum": [
                "it",
                "en"
              ],
              "default": "it"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "FAQ",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds until reset (t) for the current window.",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";r=59;t=42"
              },
              "RateLimit-Policy": {
                "description": "Quota (q) and window in seconds (w).",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";q=60;w=60"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FaqList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "RateLimit": {
                "description": "Remaining requests (r) and seconds until reset (t) for the current window.",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";r=59;t=42"
              },
              "RateLimit-Policy": {
                "description": "Quota (q) and window in seconds (w).",
                "schema": {
                  "type": "string"
                },
                "example": "\"per-ip\";q=60;w=60"
              },
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid_parameter",
              "not_found",
              "method_not_allowed",
              "rate_limited"
            ]
          },
          "resolution": {
            "type": "string"
          }
        }
      },
      "BusinessInfo": {
        "type": "object",
        "required": [
          "name",
          "url",
          "description",
          "booking",
          "contacts",
          "address",
          "geo"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "alternateName": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "description": {
            "type": "object",
            "properties": {
              "it": {
                "type": "string"
              },
              "en": {
                "type": "string"
              }
            }
          },
          "founder": {
            "type": "string"
          },
          "services": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "licenceRequired": {
            "type": "boolean",
            "description": "Whether a boat licence is needed for self-drive rental"
          },
          "booking": {
            "type": "object",
            "properties": {
              "method": {
                "type": "string"
              },
              "whatsapp": {
                "type": "string",
                "format": "uri"
              },
              "onlineCheckout": {
                "type": "boolean"
              },
              "note": {
                "type": "string"
              }
            }
          },
          "contacts": {
            "type": "object",
            "properties": {
              "phone": {
                "type": "string"
              },
              "whatsapp": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "phoneAntonio": {
                "type": "string"
              },
              "instagram": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "address": {
            "type": "object",
            "properties": {
              "streetAddress": {
                "type": "string"
              },
              "postalCode": {
                "type": "string"
              },
              "locality": {
                "type": "string"
              },
              "province": {
                "type": "string"
              },
              "region": {
                "type": "string"
              },
              "country": {
                "type": "string"
              }
            }
          },
          "geo": {
            "type": "object",
            "properties": {
              "latitude": {
                "type": "number"
              },
              "longitude": {
                "type": "number"
              }
            }
          },
          "map": {
            "type": "string",
            "format": "uri"
          },
          "hours": {
            "type": "string"
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "islands": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                }
              }
            }
          },
          "weatherPolicy": {
            "type": "string"
          }
        }
      },
      "Experience": {
        "type": "object",
        "required": [
          "id",
          "title",
          "description"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "image": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "ExperienceList": {
        "type": "object",
        "required": [
          "lang",
          "items"
        ],
        "properties": {
          "lang": {
            "type": "string",
            "enum": [
              "it",
              "en"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Experience"
            }
          }
        }
      },
      "FaqList": {
        "type": "object",
        "required": [
          "lang",
          "items"
        ],
        "properties": {
          "lang": {
            "type": "string",
            "enum": [
              "it",
              "en"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "question",
                "answer"
              ],
              "properties": {
                "question": {
                  "type": "string"
                },
                "answer": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}