{
  "openapi": "3.1.0",
  "info": {
    "title": "Great Movers booking API",
    "version": "1.0.0",
    "summary": "Instant binding long distance moving estimates from Florida to any other US state, and booking on behalf of a customer.",
    "description": "Great Movers (USDOT 3034432) moves households from Florida to every other US state. Prices are binding, calculated from the volume of the customer's inventory under the carrier's published tariff (HIC 2025), with no fuel surcharge. No salespeople and no in-home visit.\n\nHow to book for a customer: (1) find exact item names with search_items or catalog, or send custom items with dimensions in inches; (2) call quote to get the binding price, valuation options and earliest move date; (3) with the customer's permission, call reserve with their contact details. The customer is emailed a private link to review and sign personally. Agents never sign. The booking is complete when the customer signs the estimate and accepts the bill of lading. A 35% deposit is due at booking; once the customer has signed, the status response includes a secure Stripe payment link for it.\n\nScope: origin must be in Florida and destination in another US state. Moves inside Florida are not quoted.",
    "contact": { "name": "Great Movers", "email": "quotes@greatmovers.pro", "url": "https://greatmovers.pro/" },
    "x-agent-instructions": "Always confirm the full inventory, both street addresses and the move date with the customer before calling reserve. Tell the customer the price is binding only for the items listed and that they must sign the emailed link themselves."
  },
  "servers": [{ "url": "https://greatmovers.pro" }],
  "paths": {
    "/api.php": {
      "get": {
        "operationId": "getInfoCatalogOrStatus",
        "summary": "API info, inventory catalog, item search, or booking status",
        "description": "Without action: returns API info and the earliest bookable move date. action=catalog: all inventory items with cubic feet. action=search_items&q=...: find exact item names. action=status&id=...&key=...: booking status (use status_url returned by reserve).",
        "parameters": [
          { "name": "action", "in": "query", "schema": { "type": "string", "enum": ["catalog", "search_items", "status"] } },
          { "name": "q", "in": "query", "description": "Words to search item names for (search_items).", "schema": { "type": "string" } },
          { "name": "id", "in": "query", "description": "Booking id (status).", "schema": { "type": "string", "pattern": "^GM-\\d{6}-[A-F0-9]{6}$" } },
          { "name": "key", "in": "query", "description": "Status key from reserve (status).", "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "JSON result", "content": { "application/json": { "schema": { "type": "object" } } } } }
      },
      "post": {
        "operationId": "quoteOrReserve",
        "summary": "Get a binding price (quote) or reserve it for the customer to sign (reserve)",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MoveRequest" },
            "examples": {
              "quote": { "value": { "action": "quote", "from_zip": "33431", "to_zip": "30301", "items": { "Sofa, 3 Cushions": 1, "Mattress & Box Spring, Queen": 1, "Medium Box": 20 }, "custom": [{ "name": "Peloton bike", "l": 59, "w": 23, "h": 47, "qty": 1 }], "pack": "none", "access": { "oS": 2, "dE": 1 } } },
              "reserve": { "value": { "action": "reserve", "customer_consent": true, "agent_name": "Example Assistant", "from_zip": "33431", "to_zip": "30301", "move_date": "2026-11-20", "items": { "Sofa, 3 Cushions": 1, "Medium Box": 20 }, "pack": "none", "first_name": "Jane", "last_name": "Doe", "phone": "5615551234", "email": "jane@example.com", "from_addr": "100 Main St", "to_addr": "200 Peachtree St" } }
            } } }
        },
        "responses": {
          "200": { "description": "ok=true with price details, or ok=false with error and a plain-English message", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Result" } } } },
          "429": { "description": "Too many requests" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "MoveRequest": {
        "type": "object",
        "required": ["action", "from_zip", "to_zip"],
        "properties": {
          "action": { "type": "string", "enum": ["quote", "reserve"] },
          "from_zip": { "type": "string", "pattern": "^\\d{5}$", "description": "Origin ZIP, must be in Florida" },
          "to_zip": { "type": "string", "pattern": "^\\d{5}$", "description": "Destination ZIP, outside Florida" },
          "move_date": { "type": "string", "format": "date", "description": "Requested pickup date (YYYY-MM-DD). Required for reserve. Must be on or after earliest_move_date." },
          "items": { "type": "object", "additionalProperties": { "type": "integer", "minimum": 1 }, "description": "Exact catalog item name -> quantity. Unknown names are ignored." },
          "custom": { "type": "array", "description": "Items not in the catalog, sized in inches (each side up to 240).", "items": { "type": "object", "required": ["name", "l", "w", "h"], "properties": { "name": { "type": "string" }, "l": { "type": "number" }, "w": { "type": "number" }, "h": { "type": "number" }, "qty": { "type": "integer", "minimum": 1, "default": 1 } } } },
          "pack": { "type": "string", "enum": ["none", "full"], "default": "none", "description": "none: customer packs boxes. full: we pack all boxes listed." },
          "access": { "type": "object", "description": "oS/dS: flights of stairs at origin/destination (first is free). oE/dE: 1 if elevator. oL/dL: true if carry over 100 ft.", "properties": { "oS": { "type": "integer" }, "dS": { "type": "integer" }, "oE": { "type": "integer" }, "dE": { "type": "integer" }, "oL": { "type": "boolean" }, "dL": { "type": "boolean" } } },
          "customer_consent": { "type": "boolean", "description": "reserve only: true confirms the customer asked for this estimate and agrees to be contacted about it." },
          "agent_name": { "type": "string", "description": "reserve only: your name, shown to the customer." },
          "first_name": { "type": "string" }, "last_name": { "type": "string" },
          "phone": { "type": "string", "description": "10 digit US phone" }, "email": { "type": "string", "format": "email" },
          "from_addr": { "type": "string", "description": "Origin street address (city, state and ZIP come from from_zip)" },
          "to_addr": { "type": "string", "description": "Destination street address" }
        }
      },
      "Result": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" }, "error": { "type": "string" }, "message": { "type": "string" },
          "price": { "type": "number", "description": "Binding price in USD with released value protection" },
          "consultant_price": { "type": "number" }, "savings": { "type": "number" }, "deposit_due_at_booking": { "type": "number" },
          "earliest_move_date": { "type": "string", "format": "date" },
          "valuation_options": { "type": "array", "items": { "type": "object" } },
          "id": { "type": "string" }, "status": { "type": "string", "enum": ["awaiting_customer_signature", "estimate_signed_awaiting_bill_of_lading", "booked"] },
          "status_url": { "type": "string" },
          "deposit": { "type": "object", "description": "Returned by status: percent, amount, paid, and pay_url (a Stripe payment page for the 35% deposit, available once the customer has signed and online payment is enabled)." }
        }
      }
    }
  }
}
