API Documentation

Access FairLot's mobile home park lot rent database programmatically. Search parks, retrieve rent data, and build integrations with our REST API.

Overview

The FairLot API provides read-only access to mobile home park data across multiple US states. All responses are JSON. API access requires the Founding Member plan ($33/mo billed annually at $396/yr, or $49/mo billed monthly).

The API covers 600+ parks across Vermont and Nevada, with verified lot rent data for 500+ parks.

Quickstart

Get up and running with the FairLot API in three steps.

  1. Subscribe to the Founding Member plan Sign up at fairlot.org/#pricing and subscribe to the Founding Member plan ($33/mo billed annually at $396/yr, or $49/mo billed monthly).
  2. Generate an API key From your dashboard, go to Settings > API Keys and create a new key. Your key will start with fl_live_.
  3. Make your first request Try fetching parks with rent data:
    curl "https://fairlot.org/api/v1/parks?state=VT&has_rent=true&per_page=5" \ -H "Authorization: Bearer fl_live_your_key_here"
    import requests resp = requests.get( "https://fairlot.org/api/v1/parks", headers={"Authorization": "Bearer fl_live_your_key_here"}, params={"state": "VT", "has_rent": "true", "per_page": 5} ) data = resp.json() print(f"Found {data['total']} parks") for park in data["parks"]: print(f" {park['name']}: ${park['latest_lot_rent']}/mo")
    const resp = await fetch( "https://fairlot.org/api/v1/parks?state=VT&has_rent=true&per_page=5", { headers: { "Authorization": "Bearer fl_live_your_key_here" } } ); const data = await resp.json(); console.log(`Found ${data.total} parks`); data.parks.forEach(p => console.log(` ${p.name}: $${p.latest_lot_rent}/mo`) );

Tip: Start with the List Parks endpoint to browse available data, then use Get Park Detail for full rent history on individual parks.

Base URL

https://fairlot.org/api/v1

All endpoints are under the /api/v1/ prefix. For example, the parks list endpoint is:

GET https://fairlot.org/api/v1/parks

Versioning: The current API version is v1. The legacy /api/ prefix (without a version) still works and behaves identically to /api/v1/, but new integrations should use the versioned URL so they are not affected by future changes.

OpenAPI Specification

A machine-readable OpenAPI 3.1 spec is available for client code generation and tooling integration.

curl "https://fairlot.org/api/v1/openapi.json" | python -m json.tool

You can use this spec with tools like OpenAPI Generator, openapi-ts, or import it directly into Postman or Insomnia.

Authentication

FairLot supports two authentication methods:

1. API Keys (Recommended)

Generate an API key from your dashboard. Include it as a Bearer token:

curl https://fairlot.org/api/v1/parks?state=VT&has_rent=true \ -H "Authorization: Bearer fl_live_your_key_here"

2. Session Cookie

For browser-based access, sign in at fairlot.org and the session cookie authenticates automatically.

Plan-Based Access

API responses vary based on your subscription plan. Unauthenticated requests receive limited data with certain fields stripped.

Capability Free (Resident) Founding Member ($33/mo or $49/mo)
Park list (basic fields) Yes Yes (full)
Lot rent data Teaser only (3 per page) Full (all data points)
Owner name, phone, address No Yes
Park detail endpoint No (401) Yes
Full rent history No Yes
CSV export No Yes (watermarked)
API access No Yes
Max results per page 50 200
Daily view limit N/A 150 parks/day

Free tier teaser: Unauthenticated requests to /api/v1/parks will show rent data for up to 3 parks per page, but only for a limited number of parks per page. All other rent-related fields are stripped. To access full data, subscribe at fairlot.org/landing.html#pricing.

Rate Limiting

All API requests are rate-limited using a sliding window algorithm. Rate limit status is returned in response headers on every request.

Header Description
X-RateLimit-Limit Maximum requests allowed in the current window
X-RateLimit-Remaining Requests remaining in the current window
X-RateLimit-Reset Seconds until the rate limit window resets
Retry-After Seconds to wait before retrying (only on 429 responses)

Rate Limit Tiers

Tier Limit Window Applies To
Public (unauthenticated) 60 requests 60 seconds IP-based, non-search requests
Search (unauthenticated) 30 requests 60 seconds IP-based, requests with search terms
Authenticated 120 requests 60 seconds User-based, all authenticated requests
429 Rate Limited Response
{ "detail": "Too many requests. Please slow down." }

Pagination

List endpoints return paginated results. Use the page and per_page query parameters to navigate through results.

Parameter Type Default Description
page integer 1 Page number (1-indexed)
per_page integer 50 Results per page (max 50 for free, 200 for Founding Member)

The response includes total, page, and per_page fields so you can calculate total pages:

// total_pages = ceil(total / per_page) { "total": 238, "page": 1, "per_page": 50, "parks": [...] }

Sorting

Use the sort and dir parameters to control result ordering on list endpoints.

Sort Column Description
namePark name (default)
countyCounty name
metro_areaMetro area name
lot_countNumber of lots
latest_lot_rentMost recent lot rent amount
owner_namePark owner name
fetched_atDate the record was last updated

Direction: dir=asc (default) or dir=desc. The order parameter is accepted as an alias for dir.

Error Handling

The API returns standard HTTP status codes. Error responses include a JSON body with a detail field.

Status Meaning Example
200 Success Request completed
401 Unauthorized Missing or invalid session cookie
403 Forbidden Plan upgrade required for this endpoint
404 Not Found Park ID does not exist
429 Too Many Requests Rate limit exceeded (check Retry-After header)
Error response format
{ "detail": "Authentication required" }

List Parks

GET /api/v1/parks

Search and filter mobile home parks across all states. Returns a paginated list of parks with optional rent data. This is the primary endpoint for browsing the FairLot database.

Query Parameters

Parameter Type Default Description
state string none Filter by state abbreviation (e.g., VT, NV)
county string none Filter by county name
metro_area string none Filter by metro area name
min_lots integer none Minimum lot count. Alias: lot_count_min
max_lots integer none Maximum lot count. Alias: lot_count_max
has_rent boolean none When true, only return parks that have lot rent data
q string none Full-text search across park name. Aliases: name, search
owner_name string none Filter by park owner name
status string Approved Filter by registration status
sort string name Sort column (see Sorting)
dir string asc Sort direction: asc or desc. Alias: order
page integer 1 Page number (1-indexed)
per_page integer 50 Results per page (max 50 free, 200 Founding Member)
Example: Vermont parks with rent data
curl "https://fairlot.org/api/v1/parks?state=VT&has_rent=true&per_page=3" \ -H "Authorization: Bearer fl_live_your_key_here"
import requests resp = requests.get( "https://fairlot.org/api/v1/parks", headers={"Authorization": "Bearer fl_live_your_key_here"}, params={"state": "VT", "has_rent": "true", "per_page": 3} ) data = resp.json() print(data["total"], "parks found")
const resp = await fetch( "https://fairlot.org/api/v1/parks?state=VT&has_rent=true&per_page=3", { headers: { "Authorization": "Bearer fl_live_your_key_here" } } ); const data = await resp.json(); console.log(data.total, "parks found");
Response
{ "total": 216, "page": 1, "per_page": 3, "parks": [ { "id": "vt-chittenden-birchwood", "name": "Birchwood Mobile Home Park", "county": "Chittenden", "city": "Essex", "address": "123 Birchwood Ln", "state": "VT", "zip": "05452", "lot_count": 84, "owner_name": "Green Mountain Properties LLC", "status": "Approved", "phone": "(802) 555-0142", "metro_area": "Burlington-South Burlington", "park_size_category": "Medium (50-99)", "source": "vt_registry", "fetched_at": "2025-11-15T14:30:00", "latest_lot_rent": 435.0, "latest_rent_source": "verified", "latest_rent_collected_at": "2024-07-01T00:00:00", "latitude": 44.4918, "longitude": -73.1148, "age_restriction": null, "estimated_occupancy": null }, // ... more parks ] }
Example: Large parks sorted by rent (descending)
curl "https://fairlot.org/api/v1/parks?state=NV&min_lots=100&sort=latest_lot_rent&dir=desc" \ -H "Authorization: Bearer fl_live_your_key_here"
Example: Search by park name
curl "https://fairlot.org/api/v1/parks?q=maple&state=VT" \ -H "Authorization: Bearer fl_live_your_key_here"

Get Park Detail

GET /api/v1/parks/{park_id}

Retrieve detailed information for a single park, including its full rent history. Requires authentication (Founding Member plan). Full rent history is included with the Founding Member plan.

Path Parameters

Parameter Type Description
park_id string required The unique park identifier (from the list endpoint)
Example
curl "https://fairlot.org/api/v1/parks/vt-chittenden-birchwood" \ -H "Authorization: Bearer fl_live_your_key_here"
import requests resp = requests.get( "https://fairlot.org/api/v1/parks/vt-chittenden-birchwood", headers={"Authorization": "Bearer fl_live_your_key_here"} ) park = resp.json() print(park["name"], "-", len(park["lot_rents"]), "rent records")
const resp = await fetch( "https://fairlot.org/api/v1/parks/vt-chittenden-birchwood", { headers: { "Authorization": "Bearer fl_live_your_key_here" } } ); const park = await resp.json(); console.log(park.name, "-", park.lot_rents.length, "rent records");
Response
{ "id": "vt-chittenden-birchwood", "name": "Birchwood Mobile Home Park", "county": "Chittenden", "city": "Essex", "address": "123 Birchwood Ln", "state": "VT", "zip": "05452", "lot_count": 84, "owner_name": "Green Mountain Properties LLC", "status": "Approved", "phone": "(802) 555-0142", "metro_area": "Burlington-South Burlington", "park_size_category": "Medium (50-99)", "source": "vt_registry", "fetched_at": "2025-11-15T14:30:00", "latitude": 44.4918, "longitude": -73.1148, "owner_address": "456 Main St, Burlington, VT 05401", "age_restriction": null, "estimated_occupancy": null, "latest_lot_rent": 435.0, "lot_rents": [ { "lot_rent_monthly": 435.0, "lot_rent_min": 410.0, "lot_rent_max": 460.0, "lot_rent_double_wide": 510.0, "source": "verified", "confidence": "high", "collected_at": "2024-07-01T00:00:00", "notes": null }, { "lot_rent_monthly": 410.0, "lot_rent_min": 390.0, "lot_rent_max": 430.0, "lot_rent_double_wide": 480.0, "source": "verified", "confidence": "high", "collected_at": "2023-07-01T00:00:00", "notes": null } ], "upgrade_hint": null }

Founding Member plan: The lot_rents array contains the full rent history for the park. The upgrade_hint field will be null for Founding Member subscribers.

401 Unauthorized
{ "detail": "Authentication required" }
404 Not Found
{ "detail": "Park not found" }

Aggregate Statistics

GET /api/v1/stats

Returns aggregate statistics across all parks, broken down by state, county, metro area, and park size category. Includes rent stats (median, average, min, max) per grouping. This endpoint is public but rate-limited.

Example
curl "https://fairlot.org/api/v1/stats"
Response (abbreviated)
{ "total_parks": 613, "parks_with_rent_data": 504, "rent_snapshot": { "count": 504, "median": 425.0, "avg": 468.32, "min": 125.0, "max": 1850.0 }, "by_state": [ { "state": "NV", "park_count": 375, "parks_with_rent": 288 }, { "state": "VT", "park_count": 238, "parks_with_rent": 216 } ], "by_county": [ { "county": "Chittenden", "state": "VT", "park_count": 24, "rent": { "count": 19, "median": 445.0, "avg": 452.38, "min": 320.0, "max": 610.0 } } // ... more counties ], "by_metro": [ { "metro_area": "Burlington-South Burlington", "park_count": 28, "rent": { "count": 22, "median": 440.0, "avg": 448.5, "min": 310.0, "max": 610.0 } } // ... more metros ], "by_size_category": [ { "park_size_category": "Small (1-49)", "park_count": 1842 }, { "park_size_category": "Medium (50-99)", "park_count": 614 }, { "park_size_category": "Large (100-249)", "park_count": 423 }, { "park_size_category": "Very Large (250+)", "park_count": 98 } ] }

Privacy gating: Counties and metros with fewer than 3 rent data points will have their rent stats suppressed (only count will be returned) to prevent re-identification of individual submitters.

Parks GeoJSON

GET /api/v1/parks-geo

Returns all approved parks that have coordinates, optimized for map rendering. This is a lightweight endpoint designed for plotting markers on a map.

Example
curl "https://fairlot.org/api/v1/parks-geo" \ -H "Authorization: Bearer fl_live_your_key_here"
Response (abbreviated)
{ "parks": [ { "id": "vt-chittenden-birchwood", "name": "Birchwood Mobile Home Park", "latitude": 44.4918, "longitude": -73.1148, "lot_count": 84, "county": "Chittenden", "state": "VT", "owner_name": "Green Mountain Properties LLC", "latest_lot_rent": 435.0 } // ... more parks ] }

Field gating: Unauthenticated users will see owner_name as null. The latest_lot_rent field is visible without auth only for a limited number of parks per page as a teaser.

CSV Export

GET /api/v1/export/parks

Export park data as a CSV file. Requires Founding Member plan. The CSV includes watermark rows containing the authenticated user's email to prevent unauthorized redistribution.

Accepts the same filter parameters as the List Parks endpoint (state, county, has_rent, etc.).

Example
curl "https://fairlot.org/api/v1/export/parks?state=VT&has_rent=true" \ -H "Authorization: Bearer fl_live_your_key_here" \ -o parks.csv
import requests resp = requests.get( "https://fairlot.org/api/v1/export/parks", headers={"Authorization": "Bearer fl_live_your_key_here"}, params={"state": "VT", "has_rent": "true"} ) with open("parks.csv", "wb") as f: f.write(resp.content) print("Saved", len(resp.content), "bytes")
const resp = await fetch( "https://fairlot.org/api/v1/export/parks?state=VT&has_rent=true", { headers: { "Authorization": "Bearer fl_live_your_key_here" } } ); const blob = await resp.blob(); // Save or process the CSV blob

Returns a text/csv response with columns including Park ID, Name, County, Address, City, State, Zip, Lot Count, Owner, Phone, Metro Area, Size Category, Lot Rent (Monthly), Rent Source, Rent Collected At, Latitude, and Longitude.

List States

GET /api/v1/states

Returns a list of all states in the database with park counts and the number of parks that have rent data. This endpoint is public and does not require authentication.

Example
curl "https://fairlot.org/api/v1/states"
Response
[ { "state": "FL", "park_count": 1811, "parks_with_rent": 18 }, { "state": "CO", "park_count": 762, "parks_with_rent": 0 }, { "state": "NV", "park_count": 375, "parks_with_rent": 288 }, { "state": "VT", "park_count": 238, "parks_with_rent": 216 } ]

Response Schemas

ParkListItemResponse

Each park in the /api/v1/parks response contains these fields:

Field Type Description
idstringUnique park identifier
namestringPark name
countystring?County name
citystring?City name
addressstring?Street address (gated)
statestring?Two-letter state code
zipstring?ZIP code (gated)
lot_countinteger?Number of lots in the park
owner_namestring?Park owner name (gated)
statusstring?Registration status (e.g., "Approved")
phonestring?Park phone number (gated)
metro_areastring?Metro/MSA area name
park_size_categorystring?Size bucket (gated)
sourcestring?Data source identifier (gated)
fetched_atstring?ISO 8601 timestamp of last data pull (gated)
latest_lot_rentfloat?Most recent monthly lot rent (gated)
latest_rent_sourcestring?Source of the rent data (gated)
latest_rent_collected_atstring?When rent was collected (gated)
latitudefloat?GPS latitude
longitudefloat?GPS longitude
age_restrictionstring?Age restriction type (e.g., "55+")
estimated_occupancyfloat?Estimated occupancy rate (0-1)

LotRentResponse

Each entry in the lot_rents array on park detail:

Field Type Description
lot_rent_monthlyfloatMonthly lot rent amount
lot_rent_minfloat?Minimum lot rent in the park
lot_rent_maxfloat?Maximum lot rent in the park
lot_rent_double_widefloat?Lot rent for double-wide homes
sourcestring?Data source identifier
confidencestring?Confidence level: "high", "medium", or "low"
collected_atstring?ISO 8601 timestamp of data collection
notesstring?Additional notes about this data point

RentStatsResponse

Aggregate rent stats returned within the /api/v1/stats response:

Field Type Description
countintegerNumber of rent data points in this group
medianfloat?Median monthly lot rent
avgfloat?Average monthly lot rent
minfloat?Lowest lot rent in the group
maxfloat?Highest lot rent in the group

Field Gating

The following fields are set to null for unauthenticated (free tier) users on the /api/v1/parks endpoint:

Exception: A limited number of parks per page show rent fields (latest_lot_rent, latest_rent_source, latest_rent_collected_at) as a teaser for unauthenticated users.

Support

For API questions, integration help, or to request a dedicated API key, contact us at [email protected].

If you need higher rate limits or custom data exports for enterprise use, let us know your requirements and we will work with you on a solution.