{
  "openapi": "3.1.0",
  "info": {
    "title": "Harz Escape AI Agent API",
    "description": "Offizielle REST-Schnittstelle für KI-Agenten und LLMs (Gemini, ChatGPT, Claude) zur Abfrage von Escape Rooms, Live-Terminverfügbarkeiten und automatisierten Buchungsdurchführung bei Harz Escape in Wernigerode.",
    "version": "1.0.0",
    "contact": {
      "name": "Harz Escape",
      "email": "info@harz-escape.de",
      "url": "https://www.harz-escape.de/"
    }
  },
  "servers": [
    {
      "url": "https://www.harz-escape.de/api/v1",
      "description": "Production API Server"
    },
    {
      "url": "http://localhost:18080/api/v1",
      "description": "Local Development Server"
    }
  ],
  "paths": {
    "/rooms.php": {
      "get": {
        "summary": "List active escape rooms and outdoor games",
        "description": "Returns all 7 active experiences with player limits, pricing matrix, address, supported languages, and age recommendations.",
        "operationId": "getRooms",
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "description": "Language for names and descriptions (de or en)",
            "schema": {
              "type": "string",
              "enum": ["de", "en"],
              "default": "de"
            }
          },
          {
            "name": "players",
            "in": "query",
            "description": "Filter rooms suitable for a specific group size",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20
            }
          },
          {
            "name": "category",
            "in": "query",
            "description": "Filter by experience category",
            "schema": {
              "type": "string",
              "enum": ["indoor_escape_room", "outdoor_city_game", "rental_table"]
            }
          },
          {
            "name": "id",
            "in": "query",
            "description": "Get a specific room by its calendar ID",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of matching rooms",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoomsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/availability.php": {
      "get": {
        "summary": "Check live slot availability",
        "description": "Queries date-specific time slots for rooms with statuses (available, on_request, booked, blocked, past). Supports group size and language filtering.",
        "operationId": "getAvailability",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "description": "Target date in YYYY-MM-DD format (default: today)",
            "schema": {
              "type": "string",
              "format": "date",
              "example": "2026-09-08"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "description": "Optional end date for a range query (max 7 days)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "room_id",
            "in": "query",
            "description": "Filter by specific room ID (1: Uhrmacherin, 2: Don Vito, 3: Zauberprüfung, 5: Goldenes Buch, 4: Post, 10: Fabelwesen, 9: Rätseltisch)",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "players",
            "in": "query",
            "description": "Filter by number of players in group",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "description": "Response language (de or en)",
            "schema": {
              "type": "string",
              "enum": ["de", "en"],
              "default": "de"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter slots by status (e.g. 'available' for immediately bookable slots)",
            "schema": {
              "type": "string",
              "enum": ["available", "on_request", "booked", "blocked"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Availability data per day and room",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailabilityResponse"
                }
              }
            }
          },
          "422": {
            "description": "Policy violation (e.g. group size > 18 requiring personal inquiry)"
          }
        }
      }
    },
    "/bookings.php": {
      "post": {
        "summary": "Quote calculation (dry_run) and automated booking execution",
        "description": "Validates booking details, checks availability, calculates prices (including voucher deductions with anti-brute-force protection), and creates the reservation. Includes arrival instructions and venue details.",
        "operationId": "createBooking",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BookingRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Quote preview (dry_run: true) or duplicate confirmation"
          },
          "201": {
            "description": "Booking successfully created and confirmation email dispatched (dry_run: false)"
          },
          "422": {
            "description": "Validation error or outside booking policy (e.g. player count out of bounds or slot on request)"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BookingRequest": {
        "type": "object",
        "required": [
          "calendar_id",
          "timepoint",
          "contact_name",
          "contact_email",
          "contact_phone",
          "contact_nop"
        ],
        "properties": {
          "calendar_id": {
            "type": "integer",
            "description": "Room ID to book (e.g. 2 for Don Vito)",
            "example": 2
          },
          "timepoint": {
            "type": "string",
            "description": "Start date and time (YYYY-MM-DD HH:MM)",
            "example": "2026-09-08 14:00"
          },
          "contact_name": {
            "type": "string",
            "description": "Full name of the customer",
            "example": "Max Mustermann"
          },
          "contact_email": {
            "type": "string",
            "format": "email",
            "description": "Customer email address for confirmation email",
            "example": "max@example.com"
          },
          "contact_phone": {
            "type": "string",
            "description": "Customer phone number for urgent queries",
            "example": "+49 170 1234567"
          },
          "contact_nop": {
            "type": "integer",
            "description": "Number of players",
            "example": 4
          },
          "contact_message": {
            "type": "string",
            "description": "Optional remarks or wishes",
            "example": "Gebucht über KI-Assistent"
          },
          "contact_lang": {
            "type": "string",
            "enum": ["de", "en"],
            "default": "de"
          },
          "voucher": {
            "type": "string",
            "description": "Optional gift voucher code",
            "example": "HE-2026-XXXX"
          },
          "dry_run": {
            "type": "boolean",
            "description": "If true, calculates price and returns quote without writing to DB or sending email",
            "default": false
          }
        }
      },
      "RoomsResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean" },
          "data": {
            "type": "array",
            "items": { "type": "object" }
          },
          "meta": { "type": "object" }
        }
      },
      "AvailabilityResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean" },
          "data": {
            "type": "array",
            "items": { "type": "object" }
          },
          "meta": { "type": "object" }
        }
      }
    }
  }
}
