{
  "openapi": "3.1.0",
  "info": {
    "title": "The Slava House Explore API",
    "version": "1.0.0",
    "description": "Read-only API over Southern California MLS listings (Los Angeles + Orange County), sourced from CRMLS via IDX. Intended for AI agents and developers. See /llms.txt for usage guidance and attribution rules.",
    "contact": {
      "name": "Slava Ploshkin",
      "url": "https://theslavahouse.com/slavaploshkin"
    },
    "license": {
      "name": "IDX data — attribution required, redistribution prohibited"
    }
  },
  "servers": [
    {
      "url": "https://theslavahouse.com/explore",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Usage guidance for AI agents",
    "url": "https://theslavahouse.com/explore/llms.txt"
  },
  "paths": {
    "/api/listings/search": {
      "get": {
        "operationId": "searchListings",
        "summary": "Search on-market listings",
        "description": "Search Southern California (Los Angeles + Orange County) homes for sale or rent. Filter by price, beds, baths, size, year built, property type, and a geographic bounding box. Returns a paginated list with a total count.",
        "parameters": [
          {
            "name": "transaction",
            "in": "query",
            "required": false,
            "description": "Sale or rent. Defaults to sale.",
            "schema": {
              "type": "string",
              "enum": [
                "sale",
                "rent"
              ]
            },
            "example": "sale"
          },
          {
            "name": "minPrice",
            "in": "query",
            "required": false,
            "description": "Minimum list price in USD.",
            "schema": {
              "type": "integer"
            },
            "example": 500000
          },
          {
            "name": "maxPrice",
            "in": "query",
            "required": false,
            "description": "Maximum list price in USD.",
            "schema": {
              "type": "integer"
            },
            "example": 2000000
          },
          {
            "name": "beds",
            "in": "query",
            "required": false,
            "description": "Minimum number of bedrooms.",
            "schema": {
              "type": "integer"
            },
            "example": 3
          },
          {
            "name": "baths",
            "in": "query",
            "required": false,
            "description": "Minimum number of bathrooms.",
            "schema": {
              "type": "integer"
            },
            "example": 2
          },
          {
            "name": "minSqft",
            "in": "query",
            "required": false,
            "description": "Minimum living area (square feet).",
            "schema": {
              "type": "integer"
            },
            "example": 1500
          },
          {
            "name": "maxSqft",
            "in": "query",
            "required": false,
            "description": "Maximum living area (square feet).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "propertyTypes",
            "in": "query",
            "required": false,
            "description": "Comma-separated property type ids (e.g. single-family,condo,townhouse,multi-family,land).",
            "schema": {
              "type": "string"
            },
            "example": "single-family,condo"
          },
          {
            "name": "yearBuiltMin",
            "in": "query",
            "required": false,
            "description": "Earliest year built.",
            "schema": {
              "type": "integer"
            },
            "example": 1990
          },
          {
            "name": "yearBuiltMax",
            "in": "query",
            "required": false,
            "description": "Latest year built.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "zip",
            "in": "query",
            "required": false,
            "description": "Filter to a single 5-digit ZIP code (hard filter).",
            "schema": {
              "type": "string"
            },
            "example": "90077"
          },
          {
            "name": "minLng",
            "in": "query",
            "required": false,
            "description": "West edge of the search bounding box (longitude).",
            "schema": {
              "type": "number"
            },
            "example": -118.7
          },
          {
            "name": "minLat",
            "in": "query",
            "required": false,
            "description": "South edge of the search bounding box (latitude).",
            "schema": {
              "type": "number"
            },
            "example": 33.9
          },
          {
            "name": "maxLng",
            "in": "query",
            "required": false,
            "description": "East edge of the search bounding box (longitude).",
            "schema": {
              "type": "number"
            },
            "example": -118.1
          },
          {
            "name": "maxLat",
            "in": "query",
            "required": false,
            "description": "North edge of the search bounding box (latitude).",
            "schema": {
              "type": "number"
            },
            "example": 34.2
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Result ordering.",
            "schema": {
              "type": "string",
              "enum": [
                "newest",
                "oldest",
                "price-desc",
                "price-asc"
              ]
            },
            "example": "newest"
          },
          {
            "name": "top",
            "in": "query",
            "required": false,
            "description": "Page size (max enforced server-side).",
            "schema": {
              "type": "integer"
            },
            "example": 24
          },
          {
            "name": "skip",
            "in": "query",
            "required": false,
            "description": "Offset for pagination.",
            "schema": {
              "type": "integer"
            },
            "example": 0
          },
          {
            "name": "showAll",
            "in": "query",
            "required": false,
            "description": "Set to 1 to skip curated browse defaults and return everything matching the filters.",
            "schema": {
              "type": "boolean"
            },
            "example": true
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListingSearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/listings/detail": {
      "get": {
        "operationId": "listingDetail",
        "summary": "Full detail for one listing",
        "description": "Return the complete listing record (photos, remarks, facts, attribution) for a single MLS listing key. Use the id from a search result or the listingKey embedded in a /homes/{city}/{slug} page.",
        "parameters": [
          {
            "name": "listingKey",
            "in": "query",
            "required": true,
            "description": "MLS ListingKey (the `id` field from search results).",
            "schema": {
              "type": "string"
            },
            "example": "1150723072"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListingDetailResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/listings/clusters": {
      "get": {
        "operationId": "listingClusters",
        "summary": "Map clusters for a bounding box",
        "description": "Aggregate listing counts into map clusters for the given bounding box and zoom level. Useful for map overlays. A bounding box (minLng,minLat,maxLng,maxLat) is required.",
        "parameters": [
          {
            "name": "minLng",
            "in": "query",
            "required": true,
            "description": "West edge (longitude).",
            "schema": {
              "type": "number"
            },
            "example": -118.7
          },
          {
            "name": "minLat",
            "in": "query",
            "required": true,
            "description": "South edge (latitude).",
            "schema": {
              "type": "number"
            },
            "example": 33.9
          },
          {
            "name": "maxLng",
            "in": "query",
            "required": true,
            "description": "East edge (longitude).",
            "schema": {
              "type": "number"
            },
            "example": -118.1
          },
          {
            "name": "maxLat",
            "in": "query",
            "required": true,
            "description": "North edge (latitude).",
            "schema": {
              "type": "number"
            },
            "example": 34.2
          },
          {
            "name": "zoom",
            "in": "query",
            "required": false,
            "description": "Map zoom level (2-22). Controls cluster granularity.",
            "schema": {
              "type": "integer"
            },
            "example": 11
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListingClustersResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/listings/price-history": {
      "get": {
        "operationId": "priceHistory",
        "summary": "Price and status history for a listing",
        "description": "Return the MLS price-change and status-change history for a single listing key.",
        "parameters": [
          {
            "name": "listingKey",
            "in": "query",
            "required": true,
            "description": "MLS ListingKey.",
            "schema": {
              "type": "string"
            },
            "example": "1150723072"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceHistoryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Listing": {
        "type": "object",
        "description": "A single MLS listing.",
        "properties": {
          "id": {
            "type": "string",
            "description": "MLS ListingKey."
          },
          "mlsNumber": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "description": "URL slug used in /homes/{city}/{slug}."
          },
          "status": {
            "type": "string",
            "enum": [
              "Active",
              "Coming Soon",
              "Active Under Contract",
              "Pending",
              "Sold"
            ]
          },
          "transaction": {
            "type": "string",
            "enum": [
              "sale",
              "rent"
            ]
          },
          "listPrice": {
            "type": "number",
            "description": "USD."
          },
          "address": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "zip": {
            "type": "string"
          },
          "neighborhood": {
            "type": "string"
          },
          "neighborhoodSlug": {
            "type": "string"
          },
          "lat": {
            "type": "number"
          },
          "lng": {
            "type": "number"
          },
          "locationApprox": {
            "type": "boolean",
            "description": "True when lat/lng fell back to the ZIP centroid (no exact parcel point in the feed)."
          },
          "canonicalUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Absolute canonical page URL for this listing. Link here rather than assembling /homes/{city}/{slug} yourself."
          },
          "propertyType": {
            "type": "string"
          },
          "beds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "baths": {
            "type": [
              "number",
              "null"
            ]
          },
          "sqft": {
            "type": [
              "integer",
              "null"
            ]
          },
          "lotSqft": {
            "type": [
              "integer",
              "null"
            ]
          },
          "yearBuilt": {
            "type": [
              "integer",
              "null"
            ]
          },
          "hoaMonthly": {
            "type": [
              "number",
              "null"
            ]
          },
          "garageSpaces": {
            "type": [
              "integer",
              "null"
            ]
          },
          "parkingTotal": {
            "type": [
              "integer",
              "null"
            ]
          },
          "photos": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "publicRemarks": {
            "type": [
              "string",
              "null"
            ]
          },
          "listingTypes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "MLS-supplied listing type labels."
          },
          "amenities": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Amenity chips (e.g. pool, ac, waterfront)."
          },
          "highlights": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Short highlight chips shown above the description."
          },
          "searchTags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Filter chip ids derived at ingest (pets, pool, views, …)."
          },
          "featureGroups": {
            "type": "array",
            "description": "Grouped facts for the Facts & features section.",
            "items": {
              "$ref": "#/components/schemas/ListingFeatureGroup"
            }
          },
          "attribution": {
            "description": "CRMLS IDX listing credit. Only present when the feed supplied values — never fabricated.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/ListingAttribution"
              },
              {
                "type": "null"
              }
            ]
          },
          "priceHistory": {
            "type": "array",
            "description": "Omitted on search responses unless priceHistoryComplete is true. Use /api/listings/detail or /api/listings/price-history for the authoritative log.",
            "items": {
              "$ref": "#/components/schemas/PriceHistoryEntry"
            }
          },
          "priceHistoryComplete": {
            "type": "boolean",
            "description": "True when priceHistory is the full HistoryTransactional log (not the sparse fallback)."
          },
          "listedDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "ISO date the listing first came on market (drives Newest sort)."
          },
          "lastActivityDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "ISO date of the latest activity (later of on-market date and last price change)."
          },
          "originatingMls": {
            "type": [
              "string",
              "null"
            ],
            "description": "Originating MLS, e.g. CRMLS (RESO OriginatingSystemName)."
          },
          "mlsDisclaimer": {
            "type": [
              "string",
              "null"
            ],
            "description": "MLS compliance disclaimer to display verbatim when present."
          },
          "lastUpdated": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "virtualTourUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          }
        },
        "required": [
          "id",
          "mlsNumber",
          "slug",
          "status",
          "listPrice",
          "address",
          "city",
          "state",
          "zip",
          "lat",
          "lng",
          "propertyType"
        ]
      },
      "ListingSearchResponse": {
        "type": "object",
        "properties": {
          "listings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Listing"
            }
          },
          "shownCount": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "totalIsEstimate": {
            "type": "boolean"
          },
          "skip": {
            "type": "integer"
          },
          "top": {
            "type": "integer"
          },
          "hasMore": {
            "type": "boolean"
          }
        },
        "required": [
          "listings",
          "total",
          "skip",
          "top",
          "hasMore"
        ]
      },
      "ListingDetailResponse": {
        "type": "object",
        "properties": {
          "listing": {
            "$ref": "#/components/schemas/Listing"
          }
        },
        "required": [
          "listing"
        ]
      },
      "ListingCluster": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "lat": {
            "type": "number"
          },
          "lng": {
            "type": "number"
          },
          "count": {
            "type": "integer"
          },
          "minPrice": {
            "type": "number"
          },
          "maxPrice": {
            "type": "number"
          }
        },
        "required": [
          "id",
          "lat",
          "lng",
          "count"
        ]
      },
      "ListingClustersResponse": {
        "type": "object",
        "properties": {
          "clusters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ListingCluster"
            }
          },
          "exact": {
            "type": "boolean"
          },
          "scannedRows": {
            "type": "integer"
          },
          "totalMatched": {
            "type": "integer"
          }
        },
        "required": [
          "clusters",
          "exact"
        ]
      },
      "ListingAttribution": {
        "type": "object",
        "description": "CRMLS IDX listing credit. Render only the fields the feed provides.",
        "properties": {
          "agentName": {
            "type": [
              "string",
              "null"
            ]
          },
          "agentLicense": {
            "type": [
              "string",
              "null"
            ],
            "description": "CA DRE license."
          },
          "agentEmail": {
            "type": [
              "string",
              "null"
            ]
          },
          "agentPhone": {
            "type": [
              "string",
              "null"
            ]
          },
          "officeName": {
            "type": [
              "string",
              "null"
            ]
          },
          "officeLicense": {
            "type": [
              "string",
              "null"
            ]
          },
          "officePhone": {
            "type": [
              "string",
              "null"
            ]
          },
          "coAgentName": {
            "type": [
              "string",
              "null"
            ]
          },
          "coAgentLicense": {
            "type": [
              "string",
              "null"
            ]
          },
          "coOfficeName": {
            "type": [
              "string",
              "null"
            ]
          },
          "contactInfo": {
            "type": [
              "string",
              "null"
            ],
            "description": "CRMLS IDXContactInfo — how to reach the listing broker."
          }
        }
      },
      "ListingFeatureGroup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "title",
          "items"
        ]
      },
      "PriceHistoryEntry": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "event": {
            "type": "string",
            "enum": [
              "price_change",
              "listed",
              "pending",
              "sold",
              "removed",
              "other"
            ]
          },
          "price": {
            "type": "number"
          },
          "source": {
            "type": [
              "string",
              "null"
            ],
            "description": "Originating MLS for this event, e.g. CRMLS."
          },
          "mlsNumber": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "date",
          "event",
          "price"
        ]
      },
      "PriceHistoryResponse": {
        "type": "object",
        "properties": {
          "priceHistory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PriceHistoryEntry"
            }
          }
        },
        "required": [
          "priceHistory"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        },
        "required": [
          "error"
        ]
      }
    }
  }
}