{
  "openapi": "3.1.0",
  "info": {
    "title": "Chaloupka Jamný – availability, prices and booking enquiries",
    "version": "1.0.0",
    "summary": "Public API for AI assistants and booking agents.",
    "description": "Check free dates, get the price of a stay (current price list; the invoice is binding) and send a booking enquiry for the whole farmstead Chaloupka Jamný (Czech Republic) on behalf of a guest. No authentication. An enquiry is not a confirmed booking: the host replies to the guest by e-mail within 24 hours with a confirmation and an invoice; the booking is binding once paid. The same capabilities are available as an MCP server at https://chaloupkajamny.cz/mcp. Facts and rules for LLMs: https://chaloupkajamny.cz/llms.txt.",
    "contact": {
      "name": "Chaloupka Jamný",
      "email": "rezervace@chaloupkajamny.cz",
      "url": "https://chaloupkajamny.cz"
    }
  },
  "servers": [
    {
      "url": "https://chaloupkajamny.cz"
    }
  ],
  "security": [],
  "externalDocs": {
    "description": "LLM-friendly description of the property, prices and rules",
    "url": "https://chaloupkajamny.cz/llms-full.txt"
  },
  "paths": {
    "/api/availability": {
      "get": {
        "operationId": "listAvailability",
        "summary": "Booked ranges and free periods",
        "description": "Booked ranges end on the departure day (free for the next guests). `free` lists free periods between `from` and `to` (default: the next 120 days, at most 400 days); `from` of a free period = first possible arrival, `until` = last possible departure. When `calendarVerified` is false the calendar could not be checked and free periods carry `confirmed: false`; `free` is null when no calendar is configured.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2027-05-14"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2027-05-14"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Availability",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Availability"
                }
              }
            }
          }
        }
      }
    },
    "/api/quote": {
      "get": {
        "operationId": "getQuote",
        "summary": "Check a stay and get its price",
        "description": "Validates the dates against the live calendar and every booking rule (minimum stay, holiday packages, capacity, sales horizon) and returns the price breakdown in CZK per the current price list (whole property, VAT included, cleaning added once; the host's invoice is binding) and a prefilled booking link. Invalid numbers or flags are reported as `invalid_param` problems, never guessed.",
        "parameters": [
          {
            "name": "arrival",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2027-05-14"
            }
          },
          {
            "name": "departure",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2027-05-16"
            }
          },
          {
            "name": "adults",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 2
            }
          },
          {
            "name": "children",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "pets",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "lang",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "cs",
                "en",
                "uk"
              ],
              "default": "en"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Evaluation (check `bookable` and `problems`)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StayEvaluation"
                }
              }
            }
          },
          "400": {
            "description": "Invalid dates (arrival/departure are echoed as given)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StayEvaluation"
                }
              }
            }
          }
        }
      }
    },
    "/api/agent/enquiry": {
      "post": {
        "operationId": "createBookingEnquiry",
        "summary": "Send a booking enquiry for a guest",
        "description": "Sends a no-obligation booking enquiry to the host on behalf of the guest. The guest receives a summary e-mail; the host confirms the dates and sends an invoice within 24 hours. It is NOT a confirmed booking until the invoice is paid. Call with dry_run=true first to validate. Requires the guest's real name, e-mail and phone, and consent=true given by the guest. A retry with the same e-mail and dates within 15 minutes returns the original reference.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "arrival": {
                    "type": "string",
                    "format": "date",
                    "description": "YYYY-MM-DD"
                  },
                  "departure": {
                    "type": "string",
                    "format": "date",
                    "description": "YYYY-MM-DD"
                  },
                  "adults": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "children": {
                    "type": "integer",
                    "minimum": 0,
                    "default": 0
                  },
                  "pets": {
                    "type": "boolean",
                    "default": false
                  },
                  "guest_name": {
                    "type": "string",
                    "description": "Guest's full name."
                  },
                  "guest_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Guest's e-mail – the host replies there."
                  },
                  "guest_phone": {
                    "type": "string",
                    "description": "Guest's phone, international format (e.g. +420 …)."
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 1500,
                    "description": "Arrival time, occasion, special requests (optional)."
                  },
                  "lang": {
                    "type": "string",
                    "enum": [
                      "cs",
                      "en",
                      "uk"
                    ],
                    "description": "Language of the e-mails the guest receives and of the booking link (default en)."
                  },
                  "consent": {
                    "type": "boolean",
                    "description": "true only after the guest agreed to the processing of their personal data and read the booking terms."
                  },
                  "agent_name": {
                    "type": "string",
                    "description": "Name of the assistant or service sending the enquiry (shown to the host)."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "default": false,
                    "description": "Validate only, send nothing."
                  }
                },
                "required": [
                  "arrival",
                  "departure",
                  "adults",
                  "guest_name",
                  "guest_email",
                  "guest_phone",
                  "consent"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "dry_run: valid, nothing sent – or `duplicate: true`: the same enquiry was already received in the last 15 minutes (nothing new sent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnquiryResult"
                }
              }
            }
          },
          "201": {
            "description": "Enquiry received (not a confirmed booking)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnquiryResult"
                }
              }
            }
          },
          "400": {
            "description": "Body is not one JSON object",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnquiryResult"
                }
              }
            }
          },
          "403": {
            "description": "Sent from another website's page (Origin header of a foreign site)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnquiryResult"
                }
              }
            }
          },
          "409": {
            "description": "`not_bookable` (see problems) or `conflict_existing_enquiry` (an enquiry with different details for the same guest and dates was received in the last 15 minutes; see reference)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnquiryResult"
                }
              }
            }
          },
          "413": {
            "description": "Body larger than 64 kB"
          },
          "415": {
            "description": "Content-Type must be application/json"
          },
          "422": {
            "description": "Missing, unknown or invalid fields (see issues) – nothing was sent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnquiryResult"
                }
              }
            }
          },
          "429": {
            "description": "More than 5 enquiries for this guest e-mail or IP address in the last hour (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnquiryResult"
                }
              }
            }
          },
          "502": {
            "description": "Could not be delivered right now – nothing reached the host; retry later (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnquiryResult"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Availability": {
        "type": "object",
        "properties": {
          "configured": {
            "type": "boolean",
            "description": "false when no calendar source is configured"
          },
          "partial": {
            "type": "boolean",
            "description": "true when a calendar source failed – treat free dates as unconfirmed"
          },
          "calendarVerified": {
            "type": "boolean",
            "description": "configured and no source failed"
          },
          "busy": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "start": {
                  "type": "string",
                  "format": "date",
                  "example": "2027-05-14"
                },
                "end": {
                  "type": "string",
                  "format": "date",
                  "example": "2027-05-14"
                }
              }
            }
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "window": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "format": "date",
                "example": "2027-05-14"
              },
              "to": {
                "type": "string",
                "format": "date",
                "example": "2027-05-14"
              }
            }
          },
          "free": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "from": {
                  "type": "string",
                  "format": "date",
                  "example": "2027-05-14"
                },
                "until": {
                  "type": "string",
                  "format": "date",
                  "example": "2027-05-14"
                },
                "nights": {
                  "type": "integer"
                },
                "confirmed": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      },
      "Problem": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "invalid_date",
              "past",
              "order",
              "too_long",
              "too_far",
              "capacity",
              "unavailable",
              "min_nights",
              "package_block",
              "invalid_param"
            ]
          },
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "StayEvaluation": {
        "type": "object",
        "required": [
          "arrival",
          "departure",
          "nights",
          "available",
          "availabilityVerified",
          "bookable",
          "problems",
          "price",
          "bookingUrl",
          "nextStep"
        ],
        "properties": {
          "arrival": {
            "type": "string",
            "description": "YYYY-MM-DD (echoed as given)"
          },
          "departure": {
            "type": "string",
            "description": "YYYY-MM-DD (echoed as given)"
          },
          "nights": {
            "type": "integer"
          },
          "guests": {
            "type": "object",
            "properties": {
              "adults": {
                "type": "integer"
              },
              "children": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              },
              "pets": {
                "type": "boolean"
              }
            }
          },
          "available": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "null = calendar could not be verified right now"
          },
          "availabilityVerified": {
            "type": "boolean"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "const": "availability_unverified"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          },
          "bookable": {
            "type": "boolean"
          },
          "problems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Problem"
            }
          },
          "minNights": {
            "type": [
              "integer",
              "null"
            ]
          },
          "price": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "currency": {
                "const": "CZK"
              },
              "status": {
                "const": "indicative",
                "description": "current price list; the price in the host's confirmation and invoice is binding"
              },
              "total": {
                "type": "integer"
              },
              "accommodation": {
                "type": "integer"
              },
              "discount": {
                "type": "integer",
                "description": "negative amount (or 0)"
              },
              "cleaningFee": {
                "type": "integer"
              },
              "includesVat": {
                "const": true
              },
              "lines": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "description": {
                      "type": "string"
                    },
                    "nights": {
                      "type": "integer"
                    },
                    "unitPrice": {
                      "type": "integer"
                    },
                    "amount": {
                      "type": "integer"
                    }
                  }
                }
              },
              "prepayment": {
                "type": "object",
                "properties": {
                  "percent": {
                    "type": "integer"
                  },
                  "amount": {
                    "type": "integer"
                  },
                  "when": {
                    "type": "string"
                  }
                }
              },
              "securityDeposit": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "integer"
                  },
                  "refundable": {
                    "const": true
                  },
                  "when": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "checkIn": {
            "type": "string"
          },
          "checkOut": {
            "type": "string"
          },
          "bookingUrl": {
            "type": "string",
            "format": "uri"
          },
          "nextStep": {
            "type": "string"
          }
        }
      },
      "EnquiryResult": {
        "type": "object",
        "required": [
          "ok",
          "message"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "dry_run": {
            "type": "boolean"
          },
          "duplicate": {
            "type": "boolean"
          },
          "reference": {
            "type": "string",
            "example": "JA-2705-7Q4K"
          },
          "status": {
            "const": "enquiry"
          },
          "error": {
            "type": "string",
            "enum": [
              "validation",
              "not_bookable",
              "conflict_existing_enquiry",
              "rate_limited",
              "delivery",
              "forbidden"
            ]
          },
          "message": {
            "type": "string"
          },
          "issues": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string"
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          },
          "problems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Problem"
            }
          },
          "evaluation": {
            "$ref": "#/components/schemas/StayEvaluation"
          }
        }
      }
    }
  }
}