{
  "openapi": "3.1.0",
  "info": {
    "title": "Pamm Properties API",
    "version": "1.0.0",
    "summary": "Read commercial lease listings and submit leasing inquiries for Pamm Properties.",
    "description": "The Pamm Properties API exposes the commercial real estate inventory of\nPAMM Family Properties LLC (Pamm Properties) in the Rio Grande Valley of South Texas:\nretail, restaurant, office, and beauty-suite space for lease in McAllen,\nMission, Pharr, and Edinburg.\n\nEvery endpoint is public. There is no API key, no OAuth flow, no registration,\nand no login. Send the request and read the JSON.\n\nRead operations are safe and idempotent. The single write operation,\nsubmitLeasingInquiry, delivers a real leasing inquiry to a human agent and\nshould only be called with a prospect's own contact details and consent.\n\nHuman-readable documentation lives at https://www.pammproperties.com/developers.\nAn agent-oriented site summary lives at https://www.pammproperties.com/llms.txt.",
    "termsOfService": "https://www.pammproperties.com/terms-of-service",
    "contact": {
      "name": "Pamm Properties leasing and developer support",
      "email": "jgonzalez@pammproperties.com",
      "url": "https://www.pammproperties.com/developers"
    },
    "license": {
      "name": "Pamm Properties Terms of Service",
      "url": "https://www.pammproperties.com/terms-of-service"
    }
  },
  "servers": [
    {
      "url": "https://www.pammproperties.com",
      "description": "Production"
    },
    {
      "url": "https://pammproperties.com",
      "description": "Apex domain, redirects to production"
    }
  ],
  "externalDocs": {
    "description": "Pamm Properties developer portal: quickstart, examples, and the CLI",
    "url": "https://www.pammproperties.com/developers"
  },
  "tags": [
    {
      "name": "Properties",
      "description": "The commercial property portfolio: address, size, space type, and listing status."
    },
    {
      "name": "Availability",
      "description": "Live suite-level availability with monthly rent, square footage, and features."
    },
    {
      "name": "Leasing",
      "description": "Submit a leasing inquiry to a human leasing agent."
    },
    {
      "name": "Service",
      "description": "Discovery and health endpoints for clients wiring up the API."
    }
  ],
  "security": [],
  "paths": {
    "/api": {
      "get": {
        "operationId": "listApiEndpoints",
        "summary": "List every public endpoint",
        "description": "Returns a machine-readable index of the API: the OpenAPI spec URL, the documentation URL, and one entry per operation. Call this first when discovering the API from a bare domain.",
        "tags": [
          "Service"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The endpoint index.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiIndex"
                }
              }
            }
          },
          "405": {
            "description": "The HTTP method is not supported on this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Retry once, then contact leasing by email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getApiHealth",
        "summary": "Check API availability",
        "description": "Returns the service status and the current API version. Use it as a sandbox call to confirm connectivity before wiring up real requests.",
        "tags": [
          "Service"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The service is reachable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "405": {
            "description": "The HTTP method is not supported on this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Retry once, then contact leasing by email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/properties": {
      "get": {
        "operationId": "listProperties",
        "summary": "List commercial properties for lease or sale",
        "description": "Returns every property in the Pamm Properties portfolio, optionally filtered. Use it to answer what commercial space exists in McAllen, Mission, Pharr, or Edinburg, Texas, and to find the property id that getPropertyById needs.",
        "tags": [
          "Properties"
        ],
        "security": [],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Filter to a single property category. Case-insensitive.",
            "schema": {
              "type": "string",
              "enum": [
                "Retail",
                "Restaurant",
                "Office",
                "Warehouse",
                "Industrial",
                "Land",
                "Mixed-Use"
              ]
            },
            "example": "Retail"
          },
          {
            "name": "listingType",
            "in": "query",
            "required": false,
            "description": "Filter by whether the property is offered for lease or for sale.",
            "schema": {
              "type": "string",
              "enum": [
                "FOR LEASE",
                "FOR SALE"
              ]
            },
            "example": "FOR LEASE"
          },
          {
            "name": "location",
            "in": "query",
            "required": false,
            "description": "Case-insensitive substring match against the city, state, and ZIP of the property, for example McAllen or 78501.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 80
            },
            "example": "McAllen"
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text search across the property title, street address, location, and space type.",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 120
            },
            "example": "Conway"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of properties to return. Omit for all of them.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            },
            "example": 10
          }
        ],
        "responses": {
          "200": {
            "description": "The matching properties, in portfolio order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PropertyList"
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was malformed, for example a non-numeric limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The HTTP method is not supported on this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Retry once, then contact leasing by email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/properties/{propertyId}": {
      "get": {
        "operationId": "getPropertyById",
        "summary": "Get one property by id",
        "description": "Returns a single property, including street address, square footage, space type, map link, and coordinates. Get the id from listProperties.",
        "tags": [
          "Properties"
        ],
        "security": [],
        "parameters": [
          {
            "name": "propertyId",
            "in": "path",
            "required": true,
            "description": "The numeric property id returned by listProperties.",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "The requested property.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Property"
                }
              }
            }
          },
          "400": {
            "description": "The property id was not an integer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No property exists with that id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The HTTP method is not supported on this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Retry once, then contact leasing by email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/spaces": {
      "get": {
        "operationId": "listAvailableSpaces",
        "summary": "List currently available suites with rent and size",
        "description": "Returns the live, published suite-level inventory: monthly rent in US dollars, square footage, included utilities, and special features. This is the endpoint for what can be rented right now and at what price.",
        "tags": [
          "Availability"
        ],
        "security": [],
        "parameters": [
          {
            "name": "maxRent",
            "in": "query",
            "required": false,
            "description": "Only return suites whose monthly rent is at or below this amount, in US dollars.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000000
            },
            "example": 3000
          },
          {
            "name": "minSqft",
            "in": "query",
            "required": false,
            "description": "Only return suites at or above this floor area, in square feet.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 1000000
            },
            "example": 1200
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of suites to return.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 100
            },
            "example": 25
          }
        ],
        "responses": {
          "200": {
            "description": "The matching available suites.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AvailableSpaceList"
                }
              }
            }
          },
          "400": {
            "description": "A query parameter was malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The HTTP method is not supported on this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Retry once, then contact leasing by email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "The availability database is temporarily unreachable. Retry, or read /available-spaces.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/contact": {
      "post": {
        "operationId": "submitLeasingInquiry",
        "summary": "Send a leasing inquiry to a leasing agent",
        "description": "Delivers a leasing inquiry to the Pamm Properties leasing team. Only call this for a real person who has supplied their own name, email, and message. Set smsConsent to true only when that person has explicitly agreed to receive text messages; leave it false otherwise. Do not call it to test connectivity; use getApiHealth for that.",
        "tags": [
          "Leasing"
        ],
        "security": [],
        "requestBody": {
          "required": true,
          "description": "The prospect's contact details and message.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeasingInquiry"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The inquiry was accepted and routed to the leasing team.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeasingInquiryAccepted"
                }
              }
            }
          },
          "400": {
            "description": "The body failed validation. The details array names each invalid field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "The HTTP method is not supported on this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request body was not application/json.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Retry once, then contact leasing by email.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Property": {
        "type": "object",
        "title": "Property",
        "description": "One commercial property in the Pamm Properties portfolio.",
        "required": [
          "id",
          "title",
          "location",
          "address",
          "spaceType",
          "type",
          "listingType",
          "url"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "Stable numeric identifier.",
            "example": 1
          },
          "title": {
            "type": "string",
            "description": "Display name of the property, usually its street address.",
            "example": "1006 N Conway Ave"
          },
          "location": {
            "type": "string",
            "description": "City, state, and ZIP.",
            "example": "Mission, TX 78572"
          },
          "address": {
            "type": "string",
            "description": "Street address and city.",
            "example": "1006 N Conway Ave, Mission"
          },
          "spaceSize": {
            "type": [
              "string",
              "null"
            ],
            "description": "Rentable area as published, in square feet.",
            "example": "3,350 SF"
          },
          "spaceType": {
            "type": "string",
            "description": "Marketing description of the space.",
            "example": "Retail Development"
          },
          "type": {
            "type": "string",
            "description": "Property category.",
            "enum": [
              "Retail",
              "Restaurant",
              "Office",
              "Warehouse",
              "Industrial",
              "Land",
              "Mixed-Use"
            ],
            "example": "Retail"
          },
          "listingType": {
            "type": "string",
            "description": "Whether the property is offered for lease or for sale.",
            "enum": [
              "FOR LEASE",
              "FOR SALE"
            ],
            "example": "FOR LEASE"
          },
          "image": {
            "type": "string",
            "description": "Site-relative path to the primary photograph.",
            "example": "/properties/1006 N Conway Ave/1006 N Conway-2(1).jpg"
          },
          "mapsLink": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Google Maps link for the property."
          },
          "coordinates": {
            "type": [
              "object",
              "null"
            ],
            "description": "WGS84 coordinates of the property.",
            "required": [
              "latitude",
              "longitude"
            ],
            "properties": {
              "latitude": {
                "type": "number",
                "format": "double",
                "example": 26.2159
              },
              "longitude": {
                "type": "number",
                "format": "double",
                "example": -98.3256
              }
            }
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Canonical human-readable page for this property.",
            "example": "https://www.pammproperties.com/properties/1"
          }
        }
      },
      "PropertyList": {
        "type": "object",
        "title": "PropertyList",
        "description": "The properties that matched, plus how many there were.",
        "required": [
          "count",
          "data"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of properties returned.",
            "example": 23
          },
          "data": {
            "type": "array",
            "description": "The properties.",
            "items": {
              "$ref": "#/components/schemas/Property"
            }
          }
        }
      },
      "AvailableSpace": {
        "type": "object",
        "title": "AvailableSpace",
        "description": "A single leasable suite with live rent and size.",
        "required": [
          "id",
          "title",
          "sqft",
          "rent",
          "utilities"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable suite identifier.",
            "example": "12"
          },
          "title": {
            "type": "string",
            "description": "Suite name or address.",
            "example": "Suite 3 - 617 Beaumont Ave"
          },
          "sqft": {
            "type": "integer",
            "description": "Floor area in square feet.",
            "example": 1400
          },
          "rent": {
            "type": "integer",
            "description": "Monthly rent in US dollars.",
            "example": 2200
          },
          "utilities": {
            "type": "string",
            "description": "Which utilities are included in the rent.",
            "example": "Water and trash included"
          },
          "specialFeatures": {
            "type": "array",
            "description": "Notable features of the suite.",
            "items": {
              "type": "string"
            },
            "example": [
              "Grease trap",
              "Drive-thru window"
            ]
          },
          "images": {
            "type": "array",
            "description": "Absolute photo URLs.",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "floorPlans": {
            "type": "array",
            "description": "Absolute floor plan URLs.",
            "items": {
              "type": "string",
              "format": "uri"
            }
          }
        }
      },
      "AvailableSpaceList": {
        "type": "object",
        "title": "AvailableSpaceList",
        "description": "The live available-suite inventory.",
        "required": [
          "count",
          "data"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of suites returned.",
            "example": 4
          },
          "data": {
            "type": "array",
            "description": "The suites.",
            "items": {
              "$ref": "#/components/schemas/AvailableSpace"
            }
          }
        }
      },
      "LeasingInquiry": {
        "type": "object",
        "title": "LeasingInquiry",
        "description": "A prospect's request to be contacted about leasing space.",
        "required": [
          "firstName",
          "lastName",
          "email",
          "message"
        ],
        "properties": {
          "firstName": {
            "type": "string",
            "description": "Prospect's first name. Letters and spaces only.",
            "minLength": 2,
            "maxLength": 50,
            "example": "Maria"
          },
          "lastName": {
            "type": "string",
            "description": "Prospect's last name. Letters and spaces only.",
            "minLength": 2,
            "maxLength": 50,
            "example": "Gonzalez"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Reply-to email address for the prospect.",
            "maxLength": 100,
            "example": "maria@example.com"
          },
          "phone": {
            "type": "string",
            "description": "Optional phone number in any common format.",
            "maxLength": 20,
            "example": "+1 956 555 0142"
          },
          "message": {
            "type": "string",
            "description": "What the prospect is looking for.",
            "minLength": 10,
            "maxLength": 1000,
            "example": "Looking for 1,500 SF of retail space in McAllen starting in January."
          },
          "smsConsent": {
            "type": "boolean",
            "description": "Optional SMS opt-in. True only when the prospect has explicitly agreed to receive text messages; never required to submit an inquiry. Defaults to false.",
            "default": false,
            "example": true
          }
        }
      },
      "LeasingInquiryAccepted": {
        "type": "object",
        "title": "LeasingInquiryAccepted",
        "description": "Confirmation that the inquiry reached the leasing team.",
        "required": [
          "success",
          "message"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true,
            "example": true
          },
          "message": {
            "type": "string",
            "description": "Human-readable confirmation.",
            "example": "Inquiry received. A leasing agent will reply by email."
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the inquiry was accepted, in UTC."
          }
        }
      },
      "ApiIndex": {
        "type": "object",
        "title": "ApiIndex",
        "description": "Discovery document listing every public operation.",
        "required": [
          "name",
          "version",
          "documentation",
          "openapi",
          "endpoints"
        ],
        "properties": {
          "name": {
            "type": "string",
            "example": "Pamm Properties API"
          },
          "version": {
            "type": "string",
            "example": "1.0.0"
          },
          "description": {
            "type": "string"
          },
          "documentation": {
            "type": "string",
            "format": "uri"
          },
          "openapi": {
            "type": "string",
            "format": "uri"
          },
          "llmsTxt": {
            "type": "string",
            "format": "uri"
          },
          "authentication": {
            "type": "string",
            "description": "How to authenticate. Always none for this API.",
            "example": "none"
          },
          "endpoints": {
            "type": "array",
            "description": "One entry per operation.",
            "items": {
              "type": "object",
              "required": [
                "operationId",
                "method",
                "path",
                "description"
              ],
              "properties": {
                "operationId": {
                  "type": "string",
                  "example": "listProperties"
                },
                "method": {
                  "type": "string",
                  "enum": [
                    "GET",
                    "POST"
                  ],
                  "example": "GET"
                },
                "path": {
                  "type": "string",
                  "example": "/api/properties"
                },
                "description": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Health": {
        "type": "object",
        "title": "Health",
        "description": "Service liveness.",
        "required": [
          "status",
          "version"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ],
            "example": "ok"
          },
          "version": {
            "type": "string",
            "example": "1.0.0"
          },
          "time": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Error": {
        "type": "object",
        "title": "Error",
        "description": "The single error envelope used by every endpoint. Branch on error.code, never on error.message.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "hint",
              "status",
              "documentation_url"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable machine-readable error identifier.",
                "enum": [
                  "bad_request",
                  "validation_error",
                  "not_found",
                  "method_not_allowed",
                  "unsupported_media_type",
                  "upstream_unavailable",
                  "internal_error"
                ],
                "example": "not_found"
              },
              "message": {
                "type": "string",
                "description": "Human-readable summary of what went wrong."
              },
              "hint": {
                "type": "string",
                "description": "The concrete next step that resolves the error."
              },
              "status": {
                "type": "integer",
                "description": "HTTP status code, repeated in the body.",
                "example": 404
              },
              "documentation_url": {
                "type": "string",
                "format": "uri",
                "description": "Where to read more."
              },
              "details": {
                "type": "array",
                "description": "Field-level problems. Present on validation_error only.",
                "items": {
                  "type": "object",
                  "required": [
                    "field",
                    "message"
                  ],
                  "properties": {
                    "field": {
                      "type": "string",
                      "example": "email"
                    },
                    "message": {
                      "type": "string",
                      "example": "Please enter a valid email address"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}