{
 "openapi": "3.1.0",
 "info": {
  "title": "HousingFeed rental listings",
  "version": "2026-09-20",
  "summary": "US rental listings collected directly from property managers (Display Feed, licensed for display) and a pay-per-row Data API over the whole database.",
  "description": "HousingFeed has two products on one database.\n\n**Display Feed**: manager-direct US rental listings, verified weekly, licensed for public display in the licensee's product with attribution and a link back to the source (terms: https://housingfeed.com/display-feed-terms). It is delivered as CSV/JSONL exports plus API pulls after an order form; there is no self-serve endpoint. Request a sample at https://housingfeed.com/display-feed#sample.\n\n**Data API**: the whole database (portals included, 30 countries), pay per row on Apify, internal use only (research, analytics, internal tools, model evaluation). No public display rights.\n\nThis document describes the two machine-callable surfaces: the keyless 10-row live sample on housingfeed.com and the Data API actor on Apify. Field coverage varies by source; every field is nullable.\n\n**Versioning and deprecation.** The housingfeed.com endpoints are version 1, reachable at `/api/v1/sample` (canonical) and `/api/sample` (alias); every response carries `X-API-Version: 1`. Fields are only ever added, never renamed or removed, within a version. A breaking change ships as `/api/v2/...`; the old version keeps working for at least 6 months and its responses carry `Deprecation` and `Sunset` headers (RFC 8594) from the day the new version is announced, with the timeline repeated on /docs. The Data API actor follows Apify's actor versioning; its input schema is copied into this file on every build.\n\n**Rate limits.** The sample endpoint allows roughly 30 requests per 10 minutes per IP and returns the RFC RateLimit header fields (`RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, `RateLimit-Policy`) on every response and `Retry-After` on 429.",
  "termsOfService": "https://housingfeed.com/terms",
  "contact": {
   "name": "HousingFeed (Simple Studio B.V.)",
   "url": "https://housingfeed.com/contact",
   "email": "hello@housingfeed.com"
  }
 },
 "externalDocs": {
  "description": "Human documentation",
  "url": "https://housingfeed.com/docs"
 },
 "servers": [
  {
   "url": "https://housingfeed.com",
   "description": "housingfeed.com (keyless sample)"
  }
 ],
 "paths": {
  "/api/v1/sample": {
   "get": {
    "operationId": "getLiveSample",
    "summary": "Ten real listings from the live database, no key (v1; /api/sample is an alias)",
    "description": "Same query semantics as the Data API, hard-capped at 10 rows, roughly 30 requests per 10 minutes per IP. Use `tier=display` to see only listings that are in the Display Feed universe.",
    "parameters": [
     {
      "name": "country",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "Country code, e.g. `US`. With `tier=display` only `US` is valid."
     },
     {
      "name": "state",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "US state code, e.g. `TX`."
     },
     {
      "name": "city",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "City name, substring match."
     },
     {
      "name": "platform",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      },
      "description": "One source key. With `tier=display` it must be in the Display Feed allowlist."
     },
     {
      "name": "min_rent",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      },
      "description": "Minimum monthly rent (in the listing's currency). Alias: `minRent`."
     },
     {
      "name": "max_rent",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      },
      "description": "Maximum monthly rent. Alias: `maxRent`."
     },
     {
      "name": "min_beds",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      },
      "description": "Minimum bedrooms. Alias: `minBeds`."
     },
     {
      "name": "max_beds",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      },
      "description": "Maximum bedrooms. Alias: `maxBeds`."
     },
     {
      "name": "min_lat",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      },
      "description": "Bounding box, south edge. Alias: `minLat`."
     },
     {
      "name": "max_lat",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      },
      "description": "Bounding box, north edge. Alias: `maxLat`."
     },
     {
      "name": "min_lng",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      },
      "description": "Bounding box, west edge. Alias: `minLng`."
     },
     {
      "name": "max_lng",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number"
      },
      "description": "Bounding box, east edge. Alias: `maxLng`."
     },
     {
      "name": "fresh_days",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "default": 90
      },
      "description": "Only rows read in the last N days. Default 90; with `tier=display` capped at the Display Feed window (30). Alias: `freshDays`."
     },
     {
      "name": "new_since_days",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer"
      },
      "description": "Only rows first seen in the last N days (delta feed). Alias: `newSinceDays`."
     },
     {
      "name": "sort",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "best",
        "newest",
        "oldest",
        "cheapest",
        "rent_desc"
       ],
       "default": "best"
      },
      "description": "Ordering. `best` ranks geocoded rows with a photo first and spreads across sources."
     },
     {
      "name": "tier",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "display"
       ]
      },
      "description": "`display` restricts to the Display Feed universe: manager-direct US sources, live at source within 30 days, rent in a plausible band."
     },
     {
      "name": "require_photo",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "1"
       ]
      },
      "description": "Only rows with a photo. Alias: `requirePhoto`."
     },
     {
      "name": "require_geo",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "1"
       ]
      },
      "description": "Only rows with coordinates. Alias: `requireGeo`."
     }
    ],
    "responses": {
     "200": {
      "description": "Up to 10 listings.",
      "headers": {
       "RateLimit-Limit": {
        "schema": {
         "type": "string"
        },
        "description": "Requests allowed per window (about 30 per 10 minutes per IP)."
       },
       "RateLimit-Remaining": {
        "schema": {
         "type": "string"
        },
        "description": "Requests left in the current window."
       },
       "RateLimit-Reset": {
        "schema": {
         "type": "string"
        },
        "description": "Seconds until the window resets."
       },
       "X-API-Version": {
        "schema": {
         "type": "string"
        },
        "description": "Always `1` for this version."
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "query",
          "count",
          "sample"
         ],
         "properties": {
          "query": {
           "type": "object",
           "description": "The filters as applied."
          },
          "count": {
           "type": "integer"
          },
          "sample": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Listing"
           }
          },
          "note": {
           "type": "string"
          }
         }
        }
       }
      }
     },
     "429": {
      "description": "Rate limited.",
      "headers": {
       "Retry-After": {
        "schema": {
         "type": "string"
        },
        "description": "Seconds to wait before retrying."
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "Database temporarily unavailable.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "503": {
      "description": "Sample not configured.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/run-sync-get-dataset-items": {
   "servers": [
    {
     "url": "https://api.apify.com/v2/acts/housingfeed~rental-listings-api",
     "description": "Data API on Apify (pay per row; Apify account token)"
    }
   ],
   "post": {
    "operationId": "queryDataApi",
    "summary": "Query the Data API: returns matching listings as JSON (or CSV/XLSX with ?format=)",
    "description": "Runs the HousingFeed actor synchronously and returns the dataset items. Billed per returned row on Apify (see https://apify.com/housingfeed/rental-listings-api). Rights: internal use only; public display requires the Display Feed licence.",
    "security": [
     {
      "apifyToken": []
     }
    ],
    "parameters": [
     {
      "name": "format",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "json",
        "csv",
        "xlsx",
        "xml"
       ],
       "default": "json"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "country": {
          "type": "string",
          "description": "Country. Return listings from one country only. Blank = all countries.",
          "enum": [
           "",
           "US",
           "JP",
           "BR",
           "ES",
           "UK",
           "DE",
           "FR",
           "CA",
           "AU",
           "BE",
           "PL",
           "AT",
           "IT",
           "PK",
           "RO",
           "CH",
           "PT",
           "AE",
           "NO",
           "BH",
           "EU",
           "EG",
           "QA",
           "AR",
           "SA",
           "MX",
           "IE",
           "PE",
           "EC",
           "NL"
          ],
          "default": ""
         },
         "state": {
          "type": "string",
          "description": "State / region. US state code (e.g. CA, NY, TX) or region. Blank = all."
         },
         "city": {
          "type": "string",
          "description": "City. City name, partial match (e.g. \"Los Angeles\"). Blank = all."
         },
         "zip": {
          "type": "string",
          "description": "ZIP / postal code. Exact ZIP or postal code, e.g. 94110. Blank = all."
         },
         "minRent": {
          "type": "integer",
          "description": "Min rent. Minimum monthly rent, in the listing's local currency."
         },
         "maxRent": {
          "type": "integer",
          "description": "Max rent. Maximum monthly rent, in the listing's local currency."
         },
         "minBeds": {
          "type": "integer",
          "description": "Min bedrooms. Minimum number of bedrooms."
         },
         "maxBeds": {
          "type": "integer",
          "description": "Max bedrooms. Maximum number of bedrooms."
         },
         "platform": {
          "type": "string",
          "description": "Platform. Restrict to one source platform key, e.g. appfolio, zumper, apartments_com, zillow, buildium, rightmove, suumo, idealista, immoscout, leboncoin, otodom, immoweb, kijiji, hotpads. Blank = all 64 sources. For several sources use `platforms`."
         },
         "platforms": {
          "type": "array",
          "description": "Platforms (several). Up to 10 source platform keys to include, e.g. [\"zumper\",\"appfolio\",\"buildium\"]. Each source is queried separately and merged. Leave empty for all sources.",
          "items": {
           "type": "string"
          }
         },
         "availableNow": {
          "type": "boolean",
          "description": "Available now only. Only return listings marked available now.",
          "default": false
         },
         "newSinceDays": {
          "type": "integer",
          "minimum": 0,
          "maximum": 365,
          "description": "New in the last N days (delta feed). Only listings first seen by HousingFeed within the last N days. Schedule a daily run with newSinceDays: 1 and you get a live delta feed of new rentals; dedupe on the `id` field. 0 or blank = no limit."
         },
         "freshDays": {
          "type": "integer",
          "minimum": 0,
          "maximum": 365,
          "default": 90,
          "description": "Max age of a listing (days). Exclude listings last scraped more than N days ago (default 90). Set 0 to include everything ever collected. Every row carries scraped_at, first_seen_at and last_seen_at so you can judge freshness yourself."
         },
         "minLat": {
          "type": "string",
          "description": "Min latitude. South edge of a bounding box, decimal degrees (e.g. 25.70). Set any combination of the four bounds; when a geo filter is used, only listings with exact coordinates are returned. Combines with all other filters."
         },
         "maxLat": {
          "type": "string",
          "description": "Max latitude. North edge of the bounding box (e.g. 25.86)."
         },
         "minLng": {
          "type": "string",
          "description": "Min longitude. West edge of the bounding box (e.g. -80.32). Boxes crossing the 180° antimeridian are not supported."
         },
         "maxLng": {
          "type": "string",
          "description": "Max longitude. East edge of the bounding box (e.g. -80.10)."
         },
         "sort": {
          "type": "string",
          "description": "Sort order. best (default): geocoded listings with a photo first, freshest first, mixed across sources so a run shows the breadth of the feed. newest/oldest by scrape time, cheapest or rent_desc by monthly rent.",
          "enum": [
           "best",
           "newest",
           "oldest",
           "cheapest",
           "rent_desc"
          ],
          "default": "best"
         },
         "maxItems": {
          "type": "integer",
          "description": "Max results. Maximum number of listings to return (1-5000). You are charged per returned listing.",
          "default": 100,
          "maximum": 5000,
          "minimum": 1
         },
         "refresh": {
          "type": "boolean",
          "description": "Live refresh (slower). Re-scrape the portal platforms live for the freshest data instead of serving the database. Slow (minutes) and covers the portal tier only. Leave off for normal queries.",
          "default": false
         }
        },
        "additionalProperties": false,
        "description": "Easiest way to try it: click Start with the prefilled input (California, 2+ bedrooms, $1,000–3,500) — 100 listings in a few seconds, straight from the HousingFeed database of 1.9M live rentals from 70+ sources in 30 countries. Every field is optional; blank returns the freshest listings across all sources. You are charged per returned listing (maxItems caps the cost). For only new listings, set newSinceDays."
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Array of listings.",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/Listing"
         }
        }
       }
      }
     },
     "401": {
      "description": "Missing or invalid Apify token."
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "Listing": {
    "type": "object",
    "description": "One rental listing in the public schema. Every field is nullable; coverage varies by source (see /coverage#fields).",
    "properties": {
     "id": {
      "type": [
       "string",
       "null"
      ],
      "description": "Stable listing id, `platform:source_id:listing_id`."
     },
     "platform": {
      "type": [
       "string",
       "null"
      ],
      "description": "Source key (e.g. `appfolio`, `zumper`). Display Feed eligibility is per source; see /data/."
     },
     "source_id": {
      "type": [
       "string",
       "null"
      ],
      "description": "The source account or site within the platform."
     },
     "listing_id": {
      "type": [
       "string",
       "null"
      ],
      "description": "The listing's id at its source."
     },
     "url": {
      "type": [
       "string",
       "null"
      ],
      "description": "The listing page at the source. Attribution and link-back target for Display Feed licensees."
     },
     "address": {
      "type": [
       "string",
       "null"
      ],
      "description": "Full address string as published."
     },
     "street": {
      "type": [
       "string",
       "null"
      ],
      "description": "Street line."
     },
     "city": {
      "type": [
       "string",
       "null"
      ],
      "description": "City as published."
     },
     "canonical_city": {
      "type": [
       "string",
       "null"
      ],
      "description": "Normalised city name where resolved."
     },
     "state": {
      "type": [
       "string",
       "null"
      ],
      "description": "US state code or region."
     },
     "zip": {
      "type": [
       "string",
       "null"
      ],
      "description": "Postal code."
     },
     "country": {
      "type": [
       "string",
       "null"
      ],
      "description": "ISO-like country code (`US`, `UK`, `DE` ...)."
     },
     "lat": {
      "type": [
       "number",
       "null"
      ],
      "description": "Latitude (geocoded when the source publishes none)."
     },
     "lng": {
      "type": [
       "number",
       "null"
      ],
      "description": "Longitude."
     },
     "rent_min": {
      "type": [
       "number",
       "null"
      ],
      "description": "Monthly asking rent in `currency` (lower bound when a range is published)."
     },
     "rent_max": {
      "type": [
       "number",
       "null"
      ],
      "description": "Upper bound of a published rent range."
     },
     "currency": {
      "type": [
       "string",
       "null"
      ],
      "description": "ISO currency of rent_min/rent_max."
     },
     "rent_usd": {
      "type": [
       "number",
       "null"
      ],
      "description": "rent_min converted to USD at a fixed rate."
     },
     "rent_per_sqft": {
      "type": [
       "number",
       "null"
      ],
      "description": "rent_usd / sqft_min when both are present and plausible."
     },
     "rent_per_sqm": {
      "type": [
       "number",
       "null"
      ],
      "description": "Same, per square metre."
     },
     "beds": {
      "type": [
       "integer",
       "null"
      ],
      "description": "Bedrooms; 0 = studio."
     },
     "baths": {
      "type": [
       "number",
       "null"
      ],
      "description": "Bathrooms (may be fractional)."
     },
     "sqft_min": {
      "type": [
       "number",
       "null"
      ],
      "description": "Size in square feet."
     },
     "sqft_max": {
      "type": [
       "number",
       "null"
      ],
      "description": "Upper bound of a size range."
     },
     "property_type": {
      "type": [
       "string",
       "null"
      ],
      "description": "Normalised: apartment, house, condo, townhouse, room, studio, ..."
     },
     "furnished": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "True when the source says furnished."
     },
     "available": {
      "type": [
       "string",
       "null"
      ],
      "description": "Availability as published: a date string or `NOW`."
     },
     "units_available": {
      "type": [
       "integer",
       "null"
      ],
      "description": "Units available for floorplan-level rows."
     },
     "granularity": {
      "type": [
       "string",
       "null"
      ],
      "description": "`unit` or `floorplan`."
     },
     "image": {
      "type": [
       "string",
       "null"
      ],
      "description": "Primary photo URL (by reference; never re-hosted)."
     },
     "images": {
      "type": [
       "array",
       "null"
      ],
      "items": {
       "type": "string"
      },
      "description": "Gallery URLs where the source publishes one."
     },
     "description": {
      "type": [
       "string",
       "null"
      ],
      "description": "The manager's listing text; generated boilerplate removed."
     },
     "amenities": {
      "type": [
       "array",
       "null"
      ],
      "items": {
       "type": "string"
      },
      "description": "Amenity strings as published."
     },
     "first_seen_at": {
      "type": [
       "string",
       "null"
      ],
      "description": "When HousingFeed first saw the listing at its source (ISO 8601)."
     },
     "last_seen_at": {
      "type": [
       "string",
       "null"
      ],
      "description": "When HousingFeed last verified it live at its source (ISO 8601)."
     },
     "scraped_at": {
      "type": [
       "string",
       "null"
      ],
      "description": "Timestamp of the last successful read (ISO 8601)."
     }
    },
    "required": [
     "id",
     "platform",
     "url"
    ]
   },
   "Error": {
    "type": "object",
    "required": [
     "error",
     "code"
    ],
    "properties": {
     "error": {
      "type": "string",
      "description": "Short error name."
     },
     "code": {
      "type": "string",
      "description": "Stable machine-readable code (e.g. RATE_LIMITED, NOT_FOUND)."
     },
     "message": {
      "type": "string"
     },
     "hint": {
      "type": "string",
      "description": "What to do instead."
     },
     "docs": {
      "type": "string",
      "format": "uri"
     }
    }
   }
  },
  "securitySchemes": {
   "apifyToken": {
    "type": "apiKey",
    "in": "query",
    "name": "token",
    "description": "Your Apify API token (https://console.apify.com/account/integrations)."
   }
  }
 },
 "x-housingfeed": {
  "llms": "https://housingfeed.com/llms.txt",
  "markdown_negotiation": "Send `Accept: text/markdown` to any page URL for a Markdown rendering.",
  "versioning": "path (/api/v1/); X-API-Version header; Deprecation + Sunset headers and a 6-month overlap on any breaking change",
  "alias_paths": [
   "/api/sample"
  ],
  "display_feed_sample_request": "https://housingfeed.com/display-feed#sample",
  "mcp": "https://apify.com/housingfeed/rental-listings-api/api/mcp"
 }
}