{
  "openapi": "3.1.0",
  "info": {
    "title": "Marais public booking API",
    "version": "1.0.0",
    "description": "Public, unauthenticated API for AI agents and integrators: blocked-date calendars, live quotes, and request-to-book for the Marais collection of private New Orleans homes (groups of 6 to 10). No API key. Booking is request-to-book: POST /api/request-booking files a real inquiry, takes no payment, and the team confirms by email with a secure payment link. Only submit a booking with the traveler's explicit consent and real contact details; never submit test requests. Home slugs and listing IDs: https://staymarais.com/agents and https://staymarais.com/llms.txt",
    "contact": { "email": "hello@staymarais.com", "url": "https://staymarais.com/agents" },
    "termsOfService": "https://staymarais.com/terms"
  },
  "servers": [{ "url": "https://staymarais.com" }],
  "paths": {
    "/api/quote": {
      "get": {
        "operationId": "getQuote",
        "summary": "Live quote for one home and one date span (JSON)",
        "description": "Same numbers as checkout: nightly rate, one cleaning fee, occupancy taxes, no per-guest fees. Minimum stay is typically 2 to 3 nights (per-home minimums listed on /agents).",
        "parameters": [
          { "name": "home", "in": "query", "required": true, "schema": { "type": "string", "enum": ["bird-of-paradise", "bienvenue", "spoonbill", "modern-swamp", "uptown", "canopy", "nest", "satsuma", "zen-paradise", "water-wildlife", "second-line", "afrofuture", "jungle", "traditional"] }, "description": "Home slug; the full slug-to-home table is on /agents" },
          { "name": "checkin", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } },
          { "name": "checkout", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } },
          { "name": "guests", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 10 } }
        ],
        "responses": {
          "200": { "description": "Quote in USD. available is true/false, or null when availability could not be checked.", "content": { "application/json": { "schema": { "type": "object", "properties": { "ok": { "type": "boolean" }, "available": { "type": ["boolean", "null"] }, "nights": { "type": "integer" }, "currency": { "type": "string" }, "nightly": { "type": "number" }, "accommodation": { "type": "number" }, "cleaningFee": { "type": "number" }, "fees": { "type": "number" }, "taxes": { "type": "number" }, "total": { "type": "number" } } } } } },
          "404": { "description": "Unknown home slug" }
        }
      }
    },
    "/api/calendar": {
      "get": {
        "operationId": "getBlockedDates",
        "summary": "Blocked dates for one home (dates not listed are open)",
        "parameters": [
          { "name": "listingId", "in": "query", "required": true, "schema": { "type": "string" }, "description": "The home's Guesty listing ID; the slug-to-listingId table is on /agents and in /llms.txt" },
          { "name": "from", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } },
          { "name": "to", "in": "query", "required": true, "schema": { "type": "string", "format": "date" } }
        ],
        "responses": {
          "200": { "description": "Blocked dates in the window.", "content": { "application/json": { "schema": { "type": "object", "properties": { "ok": { "type": "boolean" }, "blocked": { "type": "array", "items": { "type": "string", "format": "date" } } } } } } }
        }
      }
    },
    "/api/request-booking": {
      "post": {
        "operationId": "requestBooking",
        "summary": "File a real booking request (request-to-book, no payment taken)",
        "description": "Creates a real inquiry the team acts on: they reply to the guest's email with a secure payment link. Requirements for agents: get the traveler's explicit consent after showing them the quoted total and the terms (https://staymarais.com/terms), use their real name and email, state in notes that an agent is submitting and for whom, and never send test or placeholder requests.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["listingId", "checkIn", "checkOut", "guest"],
                "properties": {
                  "listingId": { "type": "string", "description": "The home's Guesty listing ID (table on /agents)" },
                  "checkIn": { "type": "string", "format": "date" },
                  "checkOut": { "type": "string", "format": "date" },
                  "guestsCount": { "type": "integer", "minimum": 1, "maximum": 16 },
                  "guest": { "type": "object", "required": ["name", "email"], "properties": { "name": { "type": "string", "description": "Traveler's full name" }, "email": { "type": "string", "format": "email", "description": "Traveler's real email; confirmation and the payment link go here" }, "phone": { "type": "string" } } },
                  "occasion": { "type": "string" },
                  "notes": { "type": "string", "description": "Include your agent name and that you are booking on the guest's behalf" },
                  "quoted": { "type": "string", "description": "The total you quoted the guest, e.g. \"$3,240\"" }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Request filed; the team follows up by email.", "content": { "application/json": { "schema": { "type": "object", "properties": { "ok": { "type": "boolean" }, "reservationId": { "type": ["string", "null"] }, "held": { "type": "boolean" } } } } } },
          "400": { "description": "Validation failure ({ ok: false, reason })" },
          "429": { "description": "Rate limited; slow down" }
        }
      }
    }
  }
}
