ListingsFeed

Quickstart

Five minutes from zero to a page of listings. You need a key from the sign-in page (one email click; the Free plan needs no card).

1. First request

export LF_KEY=lf_live_…

curl -s -H "Authorization: Bearer $LF_KEY" \
  "https://listingsfeed.com/v1/listings?state=TX&property_type=industrial&min_sf=50000&limit=5" | jq .

The response has three parts: data (the listings), meta (count, cursor, what you were billed, your quota) and links.next (the next page URL, or null).

2. Python

import os, requests

BASE = "https://listingsfeed.com/v1"
H = {"Authorization": f"Bearer {os.environ['LF_KEY']}"}

def listings(**params):
    """Yield every listing matching params, following cursors."""
    while True:
        r = requests.get(f"{BASE}/listings", headers=H, params=params, timeout=30)
        r.raise_for_status()
        body = r.json()
        yield from body["data"]
        cursor = body["meta"]["next_cursor"]
        if not cursor:
            return
        params = {**params, "cursor": cursor}

for row in listings(state="TX", property_type="industrial", min_sf="50k", limit=100):
    print(row["hash_id"], row["city"], row["building_sf"], row["sale_ask_total"])

3. JavaScript / TypeScript

const BASE = "https://listingsfeed.com/v1";
const headers = { Authorization: `Bearer ${process.env.LF_KEY}` };

async function* listings(params) {
  let cursor;
  do {
    const qs = new URLSearchParams({ ...params, ...(cursor ? { cursor } : {}) });
    const res = await fetch(`${BASE}/listings?${qs}`, { headers });
    if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error.message}`);
    const body = await res.json();
    yield* body.data;
    cursor = body.meta.next_cursor;
  } while (cursor);
}

for await (const l of listings({ state: "TX", property_type: "industrial", limit: "100" })) {
  console.log(l.hash_id, l.city, l.building_sf);
}

4. Keep a local copy in sync

Store updated_at from your last run and ask for changes only. Include inactive rows (Team plan and above) so removals reach you too.

curl -s -H "Authorization: Bearer $LF_KEY" \
  "https://listingsfeed.com/v1/listings?updated_since=2026-09-18T00:00:00Z&include_inactive=1&sort=updated_at&order=asc&limit=1000"

5. CSV and GeoJSON

# CSV, one page per call (plan-sized), next page in the X-Next-Cursor header
curl -s -D - -H "Authorization: Bearer $LF_KEY" \
  "https://listingsfeed.com/v1/listings?state=OR&format=csv&limit=500" -o oregon.csv

# GeoJSON FeatureCollection — drop straight into QGIS, Mapbox, Leaflet
curl -s -H "Authorization: Bearer $LF_KEY" \
  "https://listingsfeed.com/v1/listings?bbox=-97.6,32.5,-96.9,33.1&format=geojson&limit=1000" -o dfw.geojson

For a one-off file without code, use the builder.

6. From an AI assistant

Add the MCP server and ask in plain language: "find industrial buildings over 100k SF for sale within 30 miles of Dallas and give me the brokers." Setup for Claude, ChatGPT and Cursor is on the MCP page.

7. Generate a client

npx @openapitools/openapi-generator-cli generate -i https://listingsfeed.com/openapi.json -g typescript-fetch -o ./listingsfeed
# or
openapi-python-client generate --url https://listingsfeed.com/openapi.json