{
  "openapi": "3.0.1",
  "info": {
    "title": "DR Horton $1💰 New Homes, Communities & Move-In Listings",
    "description": "From $1/1K. Extract new-home data from drhorton.com, America’s largest homebuilder. Pull communities and quick move-in homes by state with prices, payment estimates, floor plans, square footage, amenities, and map coordinates.",
    "version": "1.0",
    "x-build-id": "pknRLF7UWjPzbBtIO"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~drhorton-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-drhorton-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/abotapi~drhorton-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-drhorton-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/abotapi~drhorton-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-drhorton-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Search mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "How to choose what to scrape. 'search' iterates the states you pick; 'url' scrapes specific drhorton.com state, market, city, or community pages you paste.",
            "default": "search"
          },
          "states": {
            "title": "States",
            "type": "array",
            "description": "One or more US states to scrape. Each state returns every community and quick move-in home D.R. Horton lists there. Only applies in 'search' mode.",
            "items": {
              "type": "string",
              "enum": [
                "Alabama",
                "Alaska",
                "Arizona",
                "Arkansas",
                "California",
                "Colorado",
                "Connecticut",
                "Delaware",
                "Florida",
                "Georgia",
                "Hawaii",
                "Idaho",
                "Illinois",
                "Indiana",
                "Iowa",
                "Kansas",
                "Kentucky",
                "Louisiana",
                "Maine",
                "Maryland",
                "Massachusetts",
                "Michigan",
                "Minnesota",
                "Mississippi",
                "Missouri",
                "Montana",
                "Nebraska",
                "Nevada",
                "New Hampshire",
                "New Jersey",
                "New Mexico",
                "New York",
                "North Carolina",
                "North Dakota",
                "Ohio",
                "Oklahoma",
                "Oregon",
                "Pennsylvania",
                "Rhode Island",
                "South Carolina",
                "South Dakota",
                "Tennessee",
                "Texas",
                "Utah",
                "Vermont",
                "Virginia",
                "Washington",
                "West Virginia",
                "Wisconsin",
                "Wyoming"
              ]
            },
            "default": [
              "Texas"
            ]
          },
          "state": {
            "title": "State (single, alias)",
            "type": "string",
            "description": "Optional single state name, plain ('New Hampshire') or hyphenated ('New-Hampshire'). Added to the States list in 'search' mode."
          },
          "includeCommunities": {
            "title": "Include communities",
            "type": "boolean",
            "description": "Output one record per community (neighbourhood) with price, bed, bath, sqft ranges, amenities, brand, status, and coordinates.",
            "default": true
          },
          "includeQmiHomes": {
            "title": "Include quick move-in homes",
            "type": "boolean",
            "description": "Output one record per move-in-ready home with a firm price, monthly payment estimate, exact address, lot, beds, baths, and status.",
            "default": true
          },
          "includeFloorPlans": {
            "title": "Include floor plans (detail crawl)",
            "type": "boolean",
            "description": "Output one record per floor plan offered in each community (plan name, plan code, square footage, beds, baths, price). This fetches one extra page per community, so it is slower and billed separately. Leave off for the fast, cheap community + home overview.",
            "default": false
          },
          "minPrice": {
            "title": "Min price (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Keep records priced at or above this amount. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "maxPrice": {
            "title": "Max price (USD)",
            "minimum": 0,
            "type": "integer",
            "description": "Keep records priced at or below this amount. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "minBedrooms": {
            "title": "Min bedrooms",
            "minimum": 0,
            "type": "integer",
            "description": "Keep records with at least this many bedrooms. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "minBathrooms": {
            "title": "Min bathrooms",
            "minimum": 0,
            "type": "number",
            "description": "Keep records with at least this many bathrooms. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "minSqft": {
            "title": "Min square feet",
            "minimum": 0,
            "type": "integer",
            "description": "Keep records with at least this living area. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "maxSqft": {
            "title": "Max square feet",
            "minimum": 0,
            "type": "integer",
            "description": "Keep records with at most this living area. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "minGarages": {
            "title": "Min garage spaces",
            "minimum": 0,
            "type": "integer",
            "description": "Keep records with at least this many garage spaces. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "minStories": {
            "title": "Min stories",
            "minimum": 0,
            "type": "integer",
            "description": "Keep records with at least this many stories. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "propertyType": {
            "title": "Property type contains",
            "type": "string",
            "description": "Keep records whose property type contains this text, for example Townhome or Single family. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "series": {
            "title": "Series / brand contains",
            "type": "string",
            "description": "Keep records whose series or brand contains this text, for example Express or Tradition. Optional, off when empty. Applied to the records of the selected states/URLs before they are saved; records missing the filtered value are left out when the filter is set. Communities are compared on their price/size ranges."
          },
          "startUrls": {
            "title": "URLs",
            "type": "array",
            "description": "drhorton.com URLs to scrape: a state page (drhorton.com/texas), a market page (drhorton.com/texas/dallas), a city page, a community page (returns its floor plans), or a same-origin /api/comms/direct or /api/qmis/direct endpoint. http/https, with or without www, trailing slash, tracking query and mixed-case paths are all accepted; unsupported URLs are skipped with a warning. Only applies in 'url' mode. Leaving it untouched scrapes the four page examples (state, market, city, community); the two API examples in the prefill resolve to the same market data as the market page.",
            "default": [
              "https://www.drhorton.com/texas",
              "https://www.drhorton.com/texas/dallas",
              "https://www.drhorton.com/texas/dallas/richardson",
              "https://www.drhorton.com/texas/dallas/richardson/greenwood-square"
            ],
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Max records",
            "minimum": 0,
            "type": "integer",
            "description": "Stop after this many records across the whole run. The default (20) keeps a trial run small and cheap; set 0 for no limit (full coverage of every selected state, which can be hundreds of records per state).",
            "default": 20
          },
          "proxy": {
            "title": "Proxy",
            "type": "object",
            "description": "Connection settings. Default is the Apify datacenter tier and needs a plan with proxy access. Residential is optional (not included on Apify free plans).",
            "default": {
              "useApifyProxy": true
            }
          },
          "maxResidentialMB": {
            "title": "Residential traffic budget (MB)",
            "minimum": 0,
            "type": "integer",
            "description": "Only applies when the proxy group is RESIDENTIAL. After this many MB of residential traffic, the run switches to the cheaper connection tier for the rest of the run. 0 means no budget cap.",
            "default": 0
          },
          "resumeFromRunId": {
            "title": "Resume from run/dataset ID",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue an interrupted crawl: records already collected there are skipped so you get only what's still missing. One-off continuation of a SPECIFIC run — for ongoing scheduled monitoring of the same search, use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental mode (recurring monitoring)",
            "type": "boolean",
            "description": "For a search you run on a schedule (e.g. daily/weekly): remembers what this exact search returned last time and classifies every record as NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED, so you can act on only what changed. Compared: every output field (prices, selling status, availability counts, beds/baths/sqft, pending/sold flags, the upstream raw object). Excluded from the comparison but still in the output: image and thumbnail links (including the community image and photo gallery on floor-plan rows), badge labels and amenity tag lists, which rotate without a real listing change (list more with Ignore fields below). Off by default so existing scheduled runs are unaffected. Separate from Resume above, which continues one specific interrupted run. Uses State key below to isolate different searches; see Emit unchanged rows / Emit expired rows to control which of those get pushed (both bill extra rows when on).",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional)",
            "type": "string",
            "description": "Names the saved baseline Incremental mode compares against. Leave empty to auto-derive one from mode/states/startUrls/includeCommunities/includeQmiHomes/includeFloorPlans — two differently-configured searches never share a baseline even with this left empty. Set your own text only if you want to explicitly reuse or separate baselines yourself. Ignored when Incremental mode is off."
          },
          "emitUnchanged": {
            "title": "Emit unchanged rows",
            "type": "boolean",
            "description": "When Incremental mode is on: also push rows classified UNCHANGED (identical to last run), not just NEW/UPDATED/REAPPEARED/EXPIRED. Off by default to save you from paying for rows that didn't change. Turning this on bills the per-result event (and the detail-enrichment surcharge, for floor-plan rows) for every unchanged row too.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired rows",
            "type": "boolean",
            "description": "When Incremental mode is on: push a synthetic EXPIRED row for records tracked in a previous run that no longer appear in this one. Only fires after a run that scanned every selected state/URL completely — no cap, resume, or fetch failure truncating it — a partial scan can't tell 'gone' apart from 'not reached yet', so it's skipped (with a log line) otherwise. Off by default; turning it on bills the per-result event for each EXPIRED row emitted. EXPIRED rows count against maxItems like any other record; if maxItems is reached, the remaining gone records stay tracked and are reported on a later run rather than being emitted uncapped.",
            "default": false
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Top-level output field names (for example availableHomes) that must never mark a record UPDATED or appear in changedFields when Incremental mode is on. Added to the built-in exclusions (imageUrl, thumbnail, communityImage, communityImages, badges, badge, amenities). The fields still appear in the output. Ignored when Incremental mode is off.",
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per item (title + key fields), not the full JSON — the complete record stays in the dataset. Leave empty to skip. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL (or id) of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on items written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}