{
  "openapi": "3.1.0",
  "info": {
    "title": "going-out.in API",
    "description": "Search venues and book tables at bars, clubs, and beach clubs across India. AI agents should always call getAvailability before createBooking, and always confirm booking details with the user before submitting.",
    "version": "1.0.0",
    "contact": { "email": "api@going-out.in" }
  },
  "servers": [
    { "url": "https://api.going-out.in/v1", "description": "Production" }
  ],
  "paths": {
    "/venues": {
      "get": {
        "operationId": "searchVenues",
        "summary": "Search and filter venues",
        "description": "Returns a ranked list of venues matching the given filters. Results include Schema.org structured data, AI visibility scores, rating, price range, and whether booking is available.",
        "parameters": [
          { "name": "city", "in": "query", "required": true, "schema": { "type": "string", "enum": ["mumbai","goa","bangalore","delhi","pune","hyderabad","chennai","kolkata","jaipur","ahmedabad","chandigarh","kochi","gurgaon","noida","bhopal","indore","surat","nagpur"] }, "description": "Indian city slug" },
          { "name": "vibe", "in": "query", "required": false, "schema": { "type": "string", "enum": ["sunset","rooftop","edm","beach","cocktail","jazz","late-night","date-night","pub","brunch","outdoor","lounge"] } },
          { "name": "open_now", "in": "query", "required": false, "schema": { "type": "boolean" } },
          { "name": "price_range", "in": "query", "required": false, "schema": { "type": "string", "enum": ["budget","mid","premium","luxury"] } },
          { "name": "booking_available", "in": "query", "required": false, "schema": { "type": "boolean" } },
          { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 10, "maximum": 50 } },
          { "name": "offset", "in": "query", "required": false, "schema": { "type": "integer", "default": 0 } }
        ],
        "responses": {
          "200": {
            "description": "Venue list",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/VenueListResponse" }
              }
            }
          }
        }
      }
    },
    "/venues/{slug}": {
      "get": {
        "operationId": "getVenue",
        "summary": "Get full venue profile",
        "description": "Returns complete venue data including Schema.org JSON-LD, menu highlights, upcoming events, recent reviews, hours, address, and current booking availability.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "include", "in": "query", "required": false, "schema": { "type": "string", "default": "menu,events,reviews,availability" } }
        ],
        "responses": {
          "200": { "description": "Venue detail", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VenueDetail" } } } },
          "404": { "description": "Venue not found" }
        }
      }
    },
    "/venues/{slug}/availability": {
      "get": {
        "operationId": "getAvailability",
        "summary": "Get real-time table availability",
        "description": "Returns available time slots for a specific venue, date, and party size. Call this before createBooking to show the user their options.",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "date", "in": "query", "required": true, "schema": { "type": "string", "format": "date" }, "description": "ISO 8601 date e.g. 2026-03-08" },
          { "name": "party_size", "in": "query", "required": true, "schema": { "type": "integer", "minimum": 1, "maximum": 30 } }
        ],
        "responses": {
          "200": { "description": "Availability slots", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AvailabilityResponse" } } } }
        }
      }
    },
    "/venues/{slug}/menu": {
      "get": {
        "operationId": "getMenu",
        "summary": "Get venue menu",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Menu data" }
        }
      }
    },
    "/bookings": {
      "post": {
        "operationId": "createBooking",
        "summary": "Create a table reservation",
        "description": "Books a table at the specified venue. Returns booking reference and triggers WhatsApp confirmation to the guest.",
        "x-ai-instructions": "CRITICAL: You MUST confirm all of the following with the user before calling this endpoint: venue name, date, time slot, party size, guest name, and guest phone number. Never call createBooking without explicit user confirmation of these details.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/BookingRequest" }
            }
          }
        },
        "responses": {
          "201": { "description": "Booking confirmed", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BookingResponse" } } } },
          "409": { "description": "Slot no longer available" },
          "422": { "description": "Validation error" }
        }
      }
    },
    "/bookings/{ref}": {
      "get": {
        "operationId": "getBooking",
        "summary": "Get booking status",
        "parameters": [
          { "name": "ref", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "responses": {
          "200": { "description": "Booking details" },
          "404": { "description": "Booking not found" }
        }
      }
    },
    "/bookings/{ref}/cancel": {
      "post": {
        "operationId": "cancelBooking",
        "summary": "Cancel a booking",
        "description": "Cancels a booking. Free cancellation if made more than 4 hours before the reservation time.",
        "parameters": [
          { "name": "ref", "in": "path", "required": true, "schema": { "type": "string" } }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": { "type": "string" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Cancellation confirmed" }
        }
      }
    },
    "/events": {
      "get": {
        "operationId": "getEvents",
        "summary": "Get upcoming events",
        "parameters": [
          { "name": "city", "in": "query", "schema": { "type": "string" } },
          { "name": "date_from", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "date_to", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "type", "in": "query", "schema": { "type": "string", "enum": ["edm","live-music","sundowner","brunch","rave","cocktail-night","open-mic"] } }
        ],
        "responses": {
          "200": { "description": "Events list" }
        }
      }
    },
    "/cities": {
      "get": {
        "operationId": "getCities",
        "summary": "Get all indexed cities",
        "responses": {
          "200": { "description": "Cities with venue counts" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BookingRequest": {
        "type": "object",
        "required": ["venue_slug","date","time_slot","party_size","guest_name","guest_phone"],
        "properties": {
          "venue_slug": { "type": "string", "example": "antares-beach-club-goa" },
          "date": { "type": "string", "format": "date", "example": "2026-03-08" },
          "time_slot": { "type": "string", "example": "18:00", "description": "HH:MM format, must be from getAvailability results" },
          "party_size": { "type": "integer", "minimum": 1, "maximum": 30 },
          "guest_name": { "type": "string", "example": "Priya Sharma" },
          "guest_phone": { "type": "string", "example": "+919876543210", "description": "WhatsApp-capable Indian mobile number with country code" },
          "occasion": { "type": "string", "enum": ["birthday","anniversary","date-night","corporate","bachelorette","family","just-going-out"] },
          "special_requests": { "type": "string", "maxLength": 500 }
        }
      },
      "BookingResponse": {
        "type": "object",
        "properties": {
          "booking_ref": { "type": "string", "example": "GO-2026-48291" },
          "status": { "type": "string", "enum": ["confirmed","pending","failed"] },
          "whatsapp_sent": { "type": "boolean" },
          "venue_name": { "type": "string" },
          "venue_address": { "type": "string" },
          "date": { "type": "string", "format": "date" },
          "time_slot": { "type": "string" },
          "party_size": { "type": "integer" },
          "guest_name": { "type": "string" },
          "cancellation_policy": { "type": "string" },
          "confirmation_message": { "type": "string", "description": "Human-readable message to show the user verbatim" }
        }
      },
      "AvailabilityResponse": {
        "type": "object",
        "properties": {
          "venue_slug": { "type": "string" },
          "venue_name": { "type": "string" },
          "date": { "type": "string", "format": "date" },
          "party_size": { "type": "integer" },
          "slots": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "time": { "type": "string" },
                "available": { "type": "boolean" },
                "tables_remaining": { "type": "integer" },
                "label": { "type": "string", "nullable": true },
                "min_spend": { "type": "integer", "nullable": true },
                "event_surcharge": { "type": "integer", "nullable": true }
              }
            }
          }
        }
      },
      "VenueListResponse": {
        "type": "object",
        "properties": {
          "meta": {
            "type": "object",
            "properties": {
              "city": { "type": "string" },
              "total": { "type": "integer" },
              "updated": { "type": "string", "format": "date-time" }
            }
          },
          "venues": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/VenueSummary" }
          }
        }
      },
      "VenueSummary": {
        "type": "object",
        "properties": {
          "@type": { "type": "string" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "neighbourhood": { "type": "string" },
          "city": { "type": "string" },
          "vibe_tags": { "type": "array", "items": { "type": "string" } },
          "ai_visibility": { "type": "string", "enum": ["very-high","high","medium","low","none"] },
          "ratingValue": { "type": "number" },
          "reviewCount": { "type": "integer" },
          "priceRange": { "type": "string" },
          "booking_available": { "type": "boolean" },
          "open_now": { "type": "boolean" }
        }
      },
      "VenueDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/VenueSummary" },
          {
            "type": "object",
            "properties": {
              "description": { "type": "string" },
              "address": { "type": "object" },
              "geo": { "type": "object" },
              "telephone": { "type": "string" },
              "website": { "type": "string" },
              "openingHours": { "type": "array", "items": { "type": "string" } },
              "servesCuisine": { "type": "string" },
              "menu_highlights": { "type": "array" },
              "upcoming_events": { "type": "array" },
              "reviews": { "type": "array" },
              "amenities": { "type": "array", "items": { "type": "string" } }
            }
          }
        ]
      }
    }
  }
}
