{
  "openapi": "3.1.0",
  "info": {
    "title": "Hedonist Collaroy booking API",
    "version": "1.1.0",
    "description": "Public API for AI agents (the same back end as our AI host): restaurant info, live table availability, instant bookings (two steps: summary + confirmation_token, then confirm with guest_confirmed=true) and booking requests for the team to confirm. No auth; rate-limited per IP. Times are Sydney time. Guide: https://book.hedonistcollaroy.com.au/agents"
  },
  "servers": [
    {
      "url": "https://book.hedonistcollaroy.com.au"
    }
  ],
  "paths": {
    "/api/info": {
      "get": {
        "operationId": "getRestaurantInfo",
        "summary": "Restaurant facts, hours, specials, booking options",
        "responses": {
          "200": {
            "description": "Info"
          }
        }
      }
    },
    "/api/availability": {
      "get": {
        "operationId": "checkAvailability",
        "summary": "Live open times for a date/time/party size",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "YYYY-MM-DD (Sydney date)"
            }
          },
          {
            "name": "time",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "24-hour HH:MM, Sydney time"
            }
          },
          {
            "name": "party_size",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Availability"
          },
          "400": {
            "description": "Error: {ok:false, error, message, errors?}"
          },
          "429": {
            "description": "Error: {ok:false, error, message, errors?}"
          }
        }
      }
    },
    "/api/bookings": {
      "post": {
        "operationId": "makeBooking",
        "summary": "Book a table (call twice: without confirmation_token for a summary, then with it and guest_confirmed=true)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Diner's first and last name"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Diner's mobile, e.g. 0412 345 678"
                  },
                  "email": {
                    "type": "string",
                    "description": "Diner's email (confirmation is sent here)"
                  },
                  "date": {
                    "type": "string",
                    "description": "YYYY-MM-DD (Sydney date)"
                  },
                  "time": {
                    "type": "string",
                    "description": "24-hour HH:MM, Sydney time"
                  },
                  "party_size": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 8
                  },
                  "allergies": {
                    "type": "string"
                  },
                  "occasion": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "test": {
                    "type": "boolean",
                    "description": "true = try the flow without booking anything"
                  },
                  "confirmation_token": {
                    "type": "string",
                    "description": "From the first make_booking call. Omit on the first call."
                  },
                  "guest_confirmed": {
                    "type": "boolean",
                    "description": "true only after the guest said yes to the summary"
                  }
                },
                "required": [
                  "name",
                  "phone",
                  "email",
                  "date",
                  "time",
                  "party_size"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "status=confirm_with_guest (summary + token) | confirmed (booked=true) | sent_to_team (not confirmed) | test_ok"
          },
          "400": {
            "description": "Error: {ok:false, error, message, errors?}"
          },
          "409": {
            "description": "time_not_available | details_changed | token_expired | in_progress"
          },
          "422": {
            "description": "use_booking_request (large group)"
          },
          "429": {
            "description": "Error: {ok:false, error, message, errors?}"
          },
          "503": {
            "description": "live_unavailable: use requestBooking"
          }
        }
      }
    },
    "/api/booking-request": {
      "post": {
        "operationId": "requestBooking",
        "summary": "Booking request for the team to confirm with the guest",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Diner's first and last name"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Diner's mobile, e.g. 0412 345 678"
                  },
                  "email": {
                    "type": "string"
                  },
                  "date": {
                    "type": "string",
                    "description": "YYYY-MM-DD (Sydney date)"
                  },
                  "time": {
                    "type": "string",
                    "description": "24-hour HH:MM, Sydney time"
                  },
                  "party_size": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20
                  },
                  "allergies": {
                    "type": "string"
                  },
                  "occasion": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "test": {
                    "type": "boolean",
                    "description": "true = try the flow without booking anything"
                  }
                },
                "required": [
                  "name",
                  "phone",
                  "date",
                  "time",
                  "party_size"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "status=sent_to_team (submitted=true), or test"
          },
          "400": {
            "description": "Error: {ok:false, error, message, errors?}"
          },
          "429": {
            "description": "Error: {ok:false, error, message, errors?}"
          }
        }
      }
    }
  }
}