Range Lab

Housing Data API

Request access

Overview

The Housing Data API provides read-only access to Range Lab’s curated housing dataset. Use it to display rental and affordable-housing inventory inside your own product or workflow.

  • Authenticated per-request with an API key issued by Range Lab.
  • Results are scoped to the regions granted to your key.
  • Rate limited per minute; see your key’s configured limit.

Base URL

https://basecamp.rangelab.io

Authentication

Send the API key on every request in the x-api-key header.

Each endpoint requires one of the partner scopes:

  • properties:read — rental property endpoints (/api/v1/properties*, /api/v1/metadata/*, and the rentals partner exports).
  • sales:read — for-sale endpoints (/api/v1/sales* and the sales partner exports).
  • housing-resources:read — community housing resources (/api/v1/housing-resources* and the matching partner exports). Read-only projection of the shared resources table.

Scopes are independent — a key can hold any combination, and an admin can grant additional scopes to an existing key without forcing a reissue. Contact partners@rangelab.io to add a scope to a key you already have.

curl -H "x-api-key: rl_live_..." \
  https://basecamp.rangelab.io/api/v1/auth/whoami

Keys are shown exactly once at issuance. Store them in a secret manager; never commit them to source control.

Endpoints

GET/api/v1/auth/whoami

Sanity check. Returns the organization, scopes, rate limit, and allowed regions for your key.

GET/api/v1/health

Authenticated heartbeat endpoint for partner monitoring and connection validation.

GET/api/v1/properties

List properties with filters. Requires the `properties:read` scope. Region filters are additionally ANDed with the key's allowlist.

ParameterTypeDescription
citystringExact city match.
statestringTwo-letter state code (uppercased).
zip_codestringExact ZIP match.
bedsnumberExact bed count.
bathsnumberExact bath count.
min_pricenumberMinimum monthly price.
max_pricenumberMaximum monthly price.
updated_sinceISO 8601Only rows updated at or after this time.
limitnumberMax 100 for JSON, 50,000 for CSV. Default 20.
offsetnumberPagination offset. Default 0.
format"csv" | "json"Optional. Pass format=csv to stream a CSV download instead of JSON. Default json.
fields"core" | "full"Optional, CSV only. "full" adds description, images, fees, amenities, and other rich columns. Default core.
GET/api/v1/properties/:id

Fetch a single property by ID. Returns 404 if the property is outside the key's region scope.

GET/api/v1/properties/count

Return count-only totals for a filter set (same filter parameters as /api/v1/properties).

ParameterTypeDescription
citystringExact city match.
statestringTwo-letter state code (uppercased).
zip_codestringExact ZIP match.
bedsnumberExact bed count.
bathsnumberExact bath count.
min_pricenumberMinimum monthly price.
max_pricenumberMaximum monthly price.
updated_sinceISO 8601Only rows updated at or after this time.
GET/api/v1/properties/changes

Incremental sync feed ordered by updated_at ascending. Useful for pull-based mirrors. Requires `properties:read`.

ParameterTypeDescription
updated_sinceISO 8601Recommended for incremental fetches.
limitnumberMax 100 for JSON, 50,000 for CSV. Default 20.
offsetnumberPagination offset. Default 0.
format"csv" | "json"Optional. Pass format=csv to stream a CSV download instead of JSON. Default json.
fields"core" | "full"Optional, CSV only. Same column set as /properties.
citystringOptional exact city match.
statestringOptional two-letter state code.
zip_codestringOptional exact ZIP match.
GET/api/v1/sales

List for-sale listings with filters. Requires the `sales:read` scope. Region filters are ANDed with the key's allowlist; the key may also carry a county allowlist.

ParameterTypeDescription
citystringExact city match.
statestringTwo-letter state code (uppercased).
zip_codestringExact ZIP match.
countystringExact county match.
bedsnumberExact bed count.
bathsnumberExact bath count.
min_pricenumberMinimum sale price.
max_pricenumberMaximum sale price.
property_typestringOptional exact match.
home_typestringOptional exact match (e.g. single_family).
listing_statusstringOptional exact match.
market_statusstringOptional exact match.
updated_sinceISO 8601Only rows updated at or after this time.
limitnumberMax 100 for JSON, 50,000 for CSV. Default 20.
offsetnumberPagination offset. Default 0.
format"csv" | "json"Optional. Pass format=csv to stream a CSV download instead of JSON.
fields"core" | "full"Optional, CSV only. "full" adds zpid, source, full_address, lot_size, description, images, broker_name, broker_phone.
GET/api/v1/sales/changes

Sales incremental sync feed ordered by updated_at ascending. Same filter set as /sales. Requires `sales:read`.

ParameterTypeDescription
updated_sinceISO 8601Recommended for incremental fetches.
limitnumberMax 100 for JSON, 50,000 for CSV. Default 20.
offsetnumberPagination offset. Default 0.
format"csv" | "json"Optional. Pass format=csv to stream a CSV download instead of JSON.
fields"core" | "full"Optional, CSV only. Same column set as /sales.
GET/api/v1/housing-resources

Community housing resources — rental assistance, housing programs, and utility assistance. Read-only projection of the shared `resources` table, scoped to housing-related categories. Requires the `housing-resources:read` scope. Location columns are `service_state` / `service_city` / `service_county`; the key's allowlist is matched against these and accepts either 2-letter or full state names, and either bare or `"County"`-suffixed county names.

ParameterTypeDescription
citystringExact service_city match.
statestringEither 2-letter abbrev or full state name.
countystringBare county name; "County" suffix is added/stripped automatically.
categorystringOptional. Defaults to all housing-related categories (housing-assistance, housing, utilities). Pass a value within that set to narrow; values outside it return no rows.
subcategorystringOptional. Specific program label, matched case-insensitively against the row's `subcategory` (e.g. "rental assistance", "weatherization", "utility assistance", "homebuyer education"). Each row in the resources table is one program; this filter narrows to a specific one.
updated_sinceISO 8601Only rows updated at or after this time.
limitnumberMax 100 for JSON, 50,000 for CSV. Default 20.
offsetnumberPagination offset. Default 0.
format"csv" | "json"Optional. Pass format=csv to stream a CSV download instead of JSON.
fields"core" | "full"Optional, CSV only. "full" adds description, eligibility_summary, required_documents, hours_of_operation, and the structured_hours JSON blob.
GET/api/v1/housing-resources/changes

Housing-resources incremental sync feed ordered by updated_at ascending. Same baseline and filter set as /housing-resources. Requires `housing-resources:read`.

ParameterTypeDescription
updated_sinceISO 8601Recommended for incremental fetches.
limitnumberMax 100 for JSON, 50,000 for CSV. Default 20.
offsetnumberPagination offset. Default 0.
format"csv" | "json"Optional. Pass format=csv to stream a CSV download instead of JSON.
fields"core" | "full"Optional, CSV only. Same column set as /housing-resources.
GET/api/v1/properties/nearby

Geo-radius query around a coordinate. Returns region-scoped active properties.

ParameterTypeDescription
latnumberRequired latitude.
lngnumberRequired longitude.
radius_milesnumberOptional radius. Default 10, max 200.
limitnumberMax 100 for JSON, 50,000 for CSV. Default 20.
offsetnumberPagination offset. Default 0.
format"csv" | "json"Optional. Pass format=csv to stream a CSV download instead of JSON. Default json.
GET/api/v1/properties/:id/similar

Returns a small set of similar properties in the same market area.

ParameterTypeDescription
limitnumberOptional. Default 10, max 50.
GET/api/v1/metadata/filters

Discover available filter dimensions (cities/states/types) and numeric ranges.

GET/api/v1/metadata/cities

Region-scoped city inventory with per-city property counts.

GET/api/partner/exports/properties

CSV export of properties scoped to the partner's active keys carrying `properties:read`. Partner-portal session auth, not x-api-key. Same filter set as /api/v1/properties.

ParameterTypeDescription
fields"core" | "full"Optional. "full" includes description, images, fees, amenities, etc.
limitnumberMax 50,000.
citystringOptional exact city match.
statestringOptional two-letter state code.
zip_codestringOptional exact ZIP match.
bedsnumberOptional exact bed count.
bathsnumberOptional exact bath count.
min_pricenumberOptional minimum price.
max_pricenumberOptional maximum price.
updated_sinceISO 8601Optional cutoff.
GET/api/partner/exports/changes

CSV export of property changes, ascending by updated_at. Recommended for daily sync. Requires `properties:read`.

ParameterTypeDescription
fields"core" | "full"Optional column set.
updated_sinceISO 8601Pass the previous run's cursor.
limitnumberMax 50,000.
GET/api/partner/exports/cities

Reference CSV of cities in scope (city, state, listing count). Requires `properties:read`.

GET/api/partner/exports/sales

CSV export of sale listings scoped to the partner's active keys carrying `sales:read`. Honors `allowed_counties` on the key (the `property_sale_listings` table has the column; rentals does not).

ParameterTypeDescription
fields"core" | "full"Optional column set; "full" adds zpid, source, broker contact, etc.
limitnumberMax 50,000.
citystringOptional exact city match.
statestringOptional two-letter state code.
countystringOptional exact county match.
zip_codestringOptional exact ZIP match.
min_pricenumberOptional minimum sale price.
max_pricenumberOptional maximum sale price.
home_typestringOptional exact match.
updated_sinceISO 8601Optional cutoff.
GET/api/partner/exports/sales/changes

CSV export of sale-listing changes, ascending by updated_at. Requires `sales:read`.

ParameterTypeDescription
fields"core" | "full"Optional column set.
updated_sinceISO 8601Pass the previous run's cursor.
limitnumberMax 50,000.
GET/api/partner/exports/housing-resources

CSV export of housing-related community resources (rental assistance, housing programs, utility assistance). Requires `housing-resources:read`. Scoped to the partner's allowlist against `service_state` / `service_city` / `service_county`.

ParameterTypeDescription
fields"core" | "full"Optional. "full" includes description, eligibility, required documents, hours, structured_hours.
limitnumberMax 50,000.
citystringOptional exact service_city match.
statestringOptional state (2-letter or full name).
countystringOptional bare county; "County" suffix handled automatically.
categorystringOptional, must be within the housing baseline set.
subcategorystringOptional case-insensitive program label (e.g. "rental assistance").
updated_sinceISO 8601Optional cutoff.
GET/api/partner/exports/housing-resources/changes

CSV export of housing-resources changes, ascending by updated_at. Requires `housing-resources:read`.

ParameterTypeDescription
fields"core" | "full"Optional column set.
updated_sinceISO 8601Pass the previous run's cursor.
limitnumberMax 50,000.

Example request (curl)

curl -G "https://basecamp.rangelab.io/api/v1/properties" \
  -H "x-api-key: rl_live_..." \
  --data-urlencode "city=Medford" \
  --data-urlencode "state=OR" \
  --data-urlencode "limit=20"

Example request (fetch)

const res = await fetch(
  "https://basecamp.rangelab.io/api/v1/properties?city=Medford&state=OR&limit=20",
  { headers: { "x-api-key": process.env.RANGE_LAB_API_KEY } }
);
const { data, meta } = await res.json();

Example response

{
  "data": [
    {
      "id": "uuid",
      "property_name": "Example Apartments",
      "city": "Medford",
      "state": "OR",
      "price": 1450,
      "beds": 2,
      "baths": 1,
      "availability": "available",
      "images": [],
      "detail_url": ""
    }
  ],
  "meta": {
    "total": 120,
    "limit": 20,
    "offset": 0
  }
}

Error codes

StatusErrorMeaning
400bad_requestMalformed request (e.g. missing id).
401missing_header / invalid_key / key_inactiveBad or missing x-api-key header.
403client_inactive / forbiddenClient paused/revoked or missing scope.
404not_foundResource not found or outside your region scope.
429rate_limitedPer-minute rate limit exceeded. Honor Retry-After.
500internal_errorUnexpected server error.

Rate limits

Each key has a per-minute quota (default 60). When exceeded, the response is 429 with a Retry-After header indicating seconds to wait.

CSV export

Append ?format=csv to any list endpoint to receive a streaming CSV download instead of JSON. CSV requests may use a higher limit (up to 50,000) and return a Content-Disposition: attachment header so browsers prompt a save.

  • Supported on the rentals JSON endpoints (/properties, /properties/changes, /properties/search, /properties/nearby, /properties/:id/similar, /metadata/cities), the sales endpoints (/sales, /sales/changes), and the housing-resources endpoints (/housing-resources, /housing-resources/changes).
  • Same x-api-key auth, same rate limit, same region scoping as JSON.
  • Optional fields=full swaps in an extended column set (description, images, structured fields). Default is a leaner core column set suited for ETL pipelines.
  • For full-dataset sync, prefer the /changes variant of each endpoint with updated_since over repeating a full snapshot.
  • CSV exports route through the streaming paged iterator, so the per-request row cap is 50,000 rather than the PostgREST default of 1,000.
curl -G "https://basecamp.rangelab.io/api/v1/properties?format=csv&limit=10000" \
  -H "x-api-key: rl_live_..." \
  -o rangelab-properties.csv

Request access

The Housing Data API is currently in limited partner preview. To request a key, email partners@rangelab.io with your organization name, intended use, and the regions you need to cover.

© 2026 Range Lab