{
  "openapi": "3.1.0",
  "info": {
    "title": "Forage public booking API",
    "version": "1.0.0",
    "description": "Search venues live on Forage, check real availability and book a table direct. No commission. Read endpoints need no key. Bookings are rate limited per client."
  },
  "servers": [{ "url": "https://eltasuwllihnsqketgdv.supabase.co/functions/v1/forage-public-api" }],
  "paths": {
    "/venues": {
      "get": {
        "operationId": "searchVenues",
        "summary": "Venues live on Forage",
        "parameters": [
          { "name": "city", "in": "query", "schema": { "type": "string" }, "description": "Exact city name, case insensitive" },
          { "name": "cuisine", "in": "query", "schema": { "type": "string" }, "description": "Substring match on cuisine" },
          { "name": "q", "in": "query", "schema": { "type": "string" }, "description": "Free text over name, cuisine, area and vibes" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20, "maximum": 100 } }
        ],
        "responses": { "200": { "description": "List of venues", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VenueList" } } } } }
      }
    },
    "/venues/{slug}": {
      "get": {
        "operationId": "getVenue",
        "summary": "One venue by slug",
        "parameters": [{ "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": {
          "200": { "description": "Venue", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Venue" } } } },
          "404": { "description": "Not on Forage" }
        }
      }
    },
    "/availability": {
      "get": {
        "operationId": "checkAvailability",
        "summary": "Live times for a venue, date and party size",
        "parameters": [
          { "name": "venue", "in": "query", "required": true, "schema": { "type": "string" }, "description": "Venue id (uuid) or slug" },
          { "name": "date", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } },
          { "name": "covers", "in": "query", "required": true, "schema": { "type": "integer", "minimum": 1, "maximum": 20 } }
        ],
        "responses": { "200": { "description": "Slots", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Availability" } } } } }
      }
    },
    "/bookings": {
      "post": {
        "operationId": "createBooking",
        "summary": "Book a table for a named guest",
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BookingRequest" } } } },
        "responses": {
          "200": { "description": "Booking created", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BookingResult" } } } },
          "400": { "description": "Validation error" },
          "409": { "description": "Slot no longer available" },
          "429": { "description": "Rate limited" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "OpeningHours": {
        "type": "object",
        "properties": {
          "day_of_week": { "type": "integer", "description": "0 = Sunday" },
          "open": { "type": ["string", "null"] },
          "close": { "type": ["string", "null"] },
          "is_closed": { "type": "boolean" }
        }
      },
      "Venue": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "slug": { "type": "string" },
          "name": { "type": "string" },
          "blurb": { "type": ["string", "null"] },
          "cuisine": { "type": ["string", "null"] },
          "price_range": { "type": ["string", "null"] },
          "area": { "type": ["string", "null"] },
          "city": { "type": ["string", "null"] },
          "address": { "type": ["string", "null"] },
          "phone": { "type": ["string", "null"] },
          "vibes": { "type": "array", "items": { "type": "string" } },
          "latitude": { "type": ["number", "null"] },
          "longitude": { "type": ["number", "null"] },
          "opening_hours": { "type": "array", "items": { "$ref": "#/components/schemas/OpeningHours" } },
          "review_rating": { "type": ["number", "null"] },
          "review_count": { "type": "integer" },
          "url": { "type": "string", "format": "uri", "description": "The listing on forage.vip" },
          "booking_url": { "type": "string", "format": "uri", "description": "Opens the booking dialog" }
        }
      },
      "VenueList": {
        "type": "object",
        "properties": { "venues": { "type": "array", "items": { "$ref": "#/components/schemas/Venue" } }, "count": { "type": "integer" } }
      },
      "Availability": {
        "type": "object",
        "properties": {
          "venue_id": { "type": "string" },
          "date": { "type": "string" },
          "covers": { "type": "integer" },
          "venue_closed": { "type": "boolean" },
          "slots": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "time": { "type": "string", "example": "19:30" },
                "available": { "type": "boolean" },
                "is_request": { "type": "boolean", "description": "Large party; the venue confirms by hand" }
              }
            }
          }
        }
      },
      "BookingRequest": {
        "type": "object",
        "required": ["venue_id", "booking_date", "time", "covers", "name"],
        "properties": {
          "venue_id": { "type": "string", "description": "Venue id (uuid) or slug" },
          "booking_date": { "type": "string", "format": "date" },
          "time": { "type": "string", "example": "19:30" },
          "covers": { "type": "integer", "minimum": 1, "maximum": 20 },
          "name": { "type": "string" },
          "email": { "type": "string", "format": "email" },
          "phone": { "type": "string" },
          "notes": { "type": "string" },
          "occasion": { "type": "string" },
          "dietary": { "type": "array", "items": { "type": "string" }, "maxItems": 20 },
          "referral_source": { "type": "string", "description": "Your product name, so the venue sees where the booking came from" }
        }
      },
      "BookingResult": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "ref": { "type": "string", "description": "Booking reference the guest quotes" },
          "status": { "type": "string" },
          "awaiting_deposit": { "type": "boolean" },
          "checkout_url": { "type": ["string", "null"], "description": "When a deposit is due: a Stripe page for the guest to pay on" },
          "manage_url": { "type": "string", "format": "uri", "description": "Guest self service for changes and cancellation" }
        }
      }
    }
  }
}
