{
  "openapi": "3.1.0",
  "info": {
    "title": "ABA VELA Croatian buoy mooring prices",
    "version": "1.0.0",
    "description": "Read-only access to the same maintained tariff functions and catalogue as the consolidated buoy article. No authentication, inventory fetch, reservations or live availability. Unknown parameters and nonscalar values are rejected. Missing numeric prices are null, not zero. Keep tariff years, check dates, VAT, required components, conditions and source types with every quotation."
  },
  "servers": [
    {
      "url": "https://abavela.com"
    }
  ],
  "externalDocs": {
    "description": "Usage and interpretation",
    "url": "https://abavela.com/api/buoy-prices.md"
  },
  "paths": {
    "/api/buoy-prices.php": {
      "get": {
        "operationId": "getCroatiaBuoyPrices",
        "summary": "Discover buoy sites or calculate published daily prices for explicit boat assumptions",
        "parameters": [
          {
            "name": "v",
            "in": "query",
            "required": false,
            "description": "Major API version.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ],
              "default": "1"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Hull type; boat names and model inventory are not accepted.",
            "schema": {
              "type": "string",
              "enum": [
                "monohull",
                "catamaran"
              ],
              "default": "monohull"
            }
          },
          {
            "name": "loa",
            "in": "query",
            "required": false,
            "description": "Measured overall length in metres, up to100. Supply with beam and period for a price.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,3}(?:\\.[0-9]{1,8})?$"
            }
          },
          {
            "name": "beam",
            "in": "query",
            "required": false,
            "description": "Measured beam in metres, up to30 and smaller than loa. Supply both dimensions.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,3}(?:\\.[0-9]{1,8})?$"
            }
          },
          {
            "name": "duration",
            "in": "query",
            "required": false,
            "description": "Only published daily buoy pricing is supported; no invented multi-day or annual products.",
            "schema": {
              "type": "string",
              "enum": [
                "daily"
              ],
              "default": "daily"
            }
          },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "description": "Recurring month-day MM-DD, required for boat-specific prices; no season assumed. Must be an actual valid day under the shared calculator calendar.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{2}-[0-9]{2}$",
              "example": "07-15"
            }
          },
          {
            "name": "region",
            "in": "query",
            "required": false,
            "description": "All researched regions or a maintained region. ASCII Sibenik accepted.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "Istria",
                "Kvarner",
                "Zadar",
                "Šibenik",
                "Sibenik",
                "Split",
                "Dubrovnik"
              ],
              "default": "all"
            }
          },
          {
            "name": "location",
            "in": "query",
            "required": false,
            "description": "Stable ID from catalogue; unknown IDs or filter conflicts return404.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]{1,100}$"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Bay/island/alias matching, up to100 characters; short names use whole-word matching.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Numerical price or name; missing prices follow priced entries.",
            "schema": {
              "type": "string",
              "enum": [
                "price",
                "name"
              ],
              "default": "price"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "UTF-8 JSON or CSV with lossless rule JSON columns.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Catalogue or calculated results. Successful responses cache for3600 seconds with ETag.",
            "headers": {
              "ETag": {
                "schema": {
                  "type": "string"
                }
              },
              "Link": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuoyResponse"
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                },
                "example": "location_id,name,region,island,mooring_kind,status,boat_type,loa_m,beam_m,duration,period,minimum_eur,maximum_eur,..."
              }
            }
          },
          "304": {
            "description": "ETag matches; response body empty."
          },
          "400": {
            "description": "Invalid parameters (400), location not found or outside filters (404), unsupported method (405), or temporarily unavailable tariffs (503). Errors are JSON even when format=csv.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "apiVersion",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "const": false
                    },
                    "apiVersion": {
                      "const": "1"
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Invalid parameters (400), location not found or outside filters (404), unsupported method (405), or temporarily unavailable tariffs (503). Errors are JSON even when format=csv.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "apiVersion",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "const": false
                    },
                    "apiVersion": {
                      "const": "1"
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "405": {
            "description": "Invalid parameters (400), location not found or outside filters (404), unsupported method (405), or temporarily unavailable tariffs (503). Errors are JSON even when format=csv.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "apiVersion",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "const": false
                    },
                    "apiVersion": {
                      "const": "1"
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Invalid parameters (400), location not found or outside filters (404), unsupported method (405), or temporarily unavailable tariffs (503). Errors are JSON even when format=csv.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "apiVersion",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "const": false
                    },
                    "apiVersion": {
                      "const": "1"
                    },
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "headCroatiaBuoyPrices",
        "summary": "Same validation, headers and status as GET, without a body",
        "parameters": [
          {
            "name": "v",
            "in": "query",
            "required": false,
            "description": "Major API version.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ],
              "default": "1"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Hull type; boat names and model inventory are not accepted.",
            "schema": {
              "type": "string",
              "enum": [
                "monohull",
                "catamaran"
              ],
              "default": "monohull"
            }
          },
          {
            "name": "loa",
            "in": "query",
            "required": false,
            "description": "Measured overall length in metres, up to100. Supply with beam and period for a price.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,3}(?:\\.[0-9]{1,8})?$"
            }
          },
          {
            "name": "beam",
            "in": "query",
            "required": false,
            "description": "Measured beam in metres, up to30 and smaller than loa. Supply both dimensions.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,3}(?:\\.[0-9]{1,8})?$"
            }
          },
          {
            "name": "duration",
            "in": "query",
            "required": false,
            "description": "Only published daily buoy pricing is supported; no invented multi-day or annual products.",
            "schema": {
              "type": "string",
              "enum": [
                "daily"
              ],
              "default": "daily"
            }
          },
          {
            "name": "period",
            "in": "query",
            "required": false,
            "description": "Recurring month-day MM-DD, required for boat-specific prices; no season assumed. Must be an actual valid day under the shared calculator calendar.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{2}-[0-9]{2}$",
              "example": "07-15"
            }
          },
          {
            "name": "region",
            "in": "query",
            "required": false,
            "description": "All researched regions or a maintained region. ASCII Sibenik accepted.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "Istria",
                "Kvarner",
                "Zadar",
                "Šibenik",
                "Sibenik",
                "Split",
                "Dubrovnik"
              ],
              "default": "all"
            }
          },
          {
            "name": "location",
            "in": "query",
            "required": false,
            "description": "Stable ID from catalogue; unknown IDs or filter conflicts return404.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9-]{1,100}$"
            }
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "description": "Bay/island/alias matching, up to100 characters; short names use whole-word matching.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Numerical price or name; missing prices follow priced entries.",
            "schema": {
              "type": "string",
              "enum": [
                "price",
                "name"
              ],
              "default": "price"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "UTF-8 JSON or CSV with lossless rule JSON columns.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Representation metadata, no body."
          },
          "304": {
            "description": "Unchanged, no body."
          },
          "400": {
            "description": "Invalid parameters, no body."
          },
          "404": {
            "description": "Location not found, no body."
          },
          "503": {
            "description": "Tariffs unavailable, no body."
          }
        }
      },
      "options": {
        "operationId": "optionsCroatiaBuoyPrices",
        "responses": {
          "204": {
            "description": "Allowed methods GET, HEAD and OPTIONS; no body."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BuoyResult": {
        "type": "object",
        "required": [
          "id",
          "name",
          "status",
          "price",
          "source",
          "tariffRules",
          "advertisedPrices",
          "parkAdmissionRules",
          "availability"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "island": {
            "type": "string"
          },
          "mooringKind": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "priced",
              "included",
              "quote-required",
              "unavailable",
              "selection-required"
            ]
          },
          "price": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "currency",
                  "unit",
                  "minimum",
                  "maximum",
                  "isStartingPrice",
                  "includesApplicableVat",
                  "vatTreatment"
                ],
                "properties": {
                  "currency": {
                    "const": "EUR"
                  },
                  "unit": {
                    "const": "day"
                  },
                  "minimum": {
                    "type": "number",
                    "minimum": 0
                  },
                  "maximum": {
                    "type": "number",
                    "minimum": 0
                  },
                  "isStartingPrice": {
                    "type": "boolean"
                  },
                  "includesApplicableVat": {
                    "const": true
                  },
                  "vatTreatment": {
                    "type": "string",
                    "enum": [
                      "included",
                      "exempt",
                      "component-specific"
                    ]
                  }
                }
              }
            ]
          },
          "dimensions": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "loa": {
                "type": "number"
              },
              "beam": {
                "type": "number"
              }
            }
          },
          "boatType": {
            "enum": [
              "monohull",
              "catamaran"
            ]
          },
          "duration": {
            "const": "daily"
          },
          "period": {
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "type": "object",
            "required": [
              "url",
              "type",
              "tariffYear",
              "checkedAt",
              "validFrom",
              "validTo"
            ],
            "properties": {
              "url": {
                "type": "string",
                "format": "uri"
              },
              "type": {
                "type": "string",
                "description": "Operator, park, port authority or third-party directory; directory evidence is not an official tariff."
              },
              "pricingUrl": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "tariffYear": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "checkedAt": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "validFrom": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "validTo": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "vatTreatment": {
            "enum": [
              "included",
              "exempt",
              "component-specific",
              "unconfirmed",
              "not-established"
            ]
          },
          "explanation": {
            "type": "string"
          },
          "priceNote": {
            "type": "string"
          },
          "priceLabel": {
            "type": [
              "string",
              "null"
            ]
          },
          "compulsoryCharges": {
            "type": "object",
            "description": "Explicit source components and multipliers applied by the shared tariff engine; not proof every invoice item is known."
          },
          "unpricedExtras": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "additionalSources": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "restrictions": {
            "type": "object",
            "description": "Separate physical mooring limit, tariff limit, rule source and confirmed multihull billing."
          },
          "publishedFlatRate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Original published per-boat amount, not necessarily a valid selected-boat quote."
          },
          "tariffRules": {
            "type": [
              "object",
              "null"
            ],
            "description": "Lossless maintained source rule; no duplicate tariff database."
          },
          "advertisedPrices": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Dated advertisements or guide references, not calculated payable totals."
          },
          "parkAdmission": {
            "type": [
              "object",
              "null"
            ],
            "description": "Separately verified park ticket price, never silently added to or substituted for buoy fees."
          },
          "parkAdmissionRules": {
            "type": [
              "object",
              "null"
            ]
          },
          "availability": {
            "const": "not-checked"
          }
        }
      },
      "BuoyResponse": {
        "type": "object",
        "required": [
          "ok",
          "apiVersion",
          "mode",
          "request",
          "catalogueCount",
          "resultCount",
          "pricedCount",
          "limitations",
          "results"
        ],
        "properties": {
          "ok": {
            "const": true
          },
          "apiVersion": {
            "const": "1"
          },
          "mode": {
            "enum": [
              "catalogue",
              "prices"
            ]
          },
          "request": {
            "type": "object"
          },
          "catalogueCount": {
            "type": "integer"
          },
          "resultCount": {
            "type": "integer"
          },
          "pricedCount": {
            "type": "integer"
          },
          "catalogueCheckedOn": {
            "type": "string",
            "format": "date"
          },
          "latestSourceCheck": {
            "type": [
              "string",
              "null"
            ]
          },
          "comparisonUrl": {
            "type": "string",
            "format": "uri"
          },
          "documentationUrl": {
            "type": "string",
            "format": "uri"
          },
          "openapiUrl": {
            "type": "string",
            "format": "uri"
          },
          "maintainedCatalogueUrl": {
            "type": "string",
            "format": "uri"
          },
          "options": {
            "type": "object"
          },
          "limitations": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BuoyResult"
            }
          }
        }
      }
    }
  }
}
