# Find leads looking in an area

Source: https://help.ruuster.com/api/leads-area-interest

```http
GET https://api.ruuster.com/v1/leads/area-interest
```

Your leads who have been looking in a city, zip, county, school zone, neighborhood or subdivision at a price, in one call. Combines the listing views and inquiries your CRM sends back (Ylopo, Zillow, Realtor.com, your IDX site, Ruuster), views on your Ruuster site, and saved searches (Ruuster's and your CRM's). Use it for "who's been searching $500K+ in Santa Rosa Beach" or a neighborhood farming list.

- Authentication: `x-api-key` and `x-email` headers of an owner or admin
- Rate limit: *lookup* call, 20 per minute per key, within the 120 per minute
- Rows count against the daily lead-row quota (50,000 by default)

Answers "which of my leads are interested in this area?" from three kinds of evidence, merged into one row per lead:

- **Listing activity from your CRM**: the property views and inquiries your CRM passes back to Ruuster, including third-party portals (Ylopo, Zillow, Realtor.com and others), your IDX site and Ruuster. Each event is placed on the map by its address.
- **Views on your Ruuster site**: listings your leads viewed, saved or asked to tour there.
- **Saved searches**: your leads' Ruuster saved searches and the saved searches imported from your CRM (`origin: "crm"`), whose zip, city or shape overlaps the area and whose price range overlaps `priceMin`–`priceMax`.

**The area** is looked up in Ruuster's boundary library by name: a city or town (`Santa Rosa Beach, FL`), a county (`Walton County, FL`), a zip (`32459`), a school district or attendance zone, a neighborhood or subdivision (`WaterColor, Santa Rosa Beach FL`; the part after the comma picks between same-named places). `meta.area` says which boundary was used and `meta.alternates` lists others that matched; pass one's `boundaryId` to use it instead. A city counts activity inside its boundary **or** addressed to that mailing city (a beach community's mailing city is often much larger than its census boundary). A community with no official boundary (many unincorporated beach and resort towns) is matched by its mailing city alone, and `meta.area.source` is `mailing_city`. A zip counts its boundary or the listing's zip. Every other kind of area is its boundary only. Saved searches for a whole county count for any area inside it (`matchedOn: "area:county"`) but rank below searches aimed at the area itself.

**Price**: activity is counted for listings priced inside `priceMin`–`priceMax`. Portal events that arrive without a price are kept and counted in `priceUnknown`. Saved searches count when their range overlaps the band; an open-ended search (no maximum) always overlaps a minimum. This is a lookup call.

## Query parameters

| Name | Type | Default | Description |
|---|---|---|---|
| `area` | string | required unless `boundaryId` | City and state, county, zip, school zone, neighborhood or subdivision, for example `Santa Rosa Beach, FL` or `WaterColor, Santa Rosa Beach FL` |
| `boundaryId` | string | | A boundary from `meta.alternates`, in place of `area` |
| `priceMin` | integer | | Lowest listing price, in dollars |
| `priceMax` | integer | | Highest listing price, in dollars |
| `days` | integer | `180` | How far back to look, 1 to 400 days |
| `signals` | string | `activity,savedSearch` | Comma-separated: `activity` (CRM and Ruuster listing activity), `savedSearch` |
| `limit` | integer | `100` | Leads returned, 1 to 200, strongest interest first |
| `countOnly` | `0` \| `1` | `0` | `1` returns `{ "total": n }` and no rows |

## Response

`data.total` is the number of leads found and `data.leads` has one row per lead, strongest first: leads with an inquiry or tour request, then leads with a fitting saved search, then the most views, then the most recent.

| Field | Description |
|---|---|
| `lead` | The short lead form: `leadId`, `firstName`, `lastName`, `email` and `phone` when lead contact details are on, `crmExternalId` (the person's id in your CRM), `crmStatus`, `crmTags`, `agentId`, `createdAt`, `lastLoginAt` |
| `savedSearches` | Fitting saved searches: `searchId`, `name`, `origin` (`crm` or `ruuster`), `matchedOn` (`zip`, `city`, or `area:<kind>`), `priceMin`, `priceMax`, `criteria` (types, beds and other filters as saved) and `updatedAt` |
| `activity` | `views`, `inquiries`, `favorites` and `tourRequests` in the area and price band; `sources` (where the activity came from, for example `Ylopo`, `Zillow`, `Ruuster`); `priceSeen` (`min`, `max` of the prices viewed); `priceUnknown` (events with no price); `lastAt`; `examples` (up to three addresses) |

`meta.area` is the boundary used (`boundaryId`, `name`, `tier`, `region`, `context`, `source`, `quality`), `meta.alternates` other matches, `meta.since` the first day counted, `meta.counts` what each source contributed, `meta.crmEventTypesCovered` the CRM event types Ruuster receives, and `meta.crmEvents` how current the CRM activity is: `asOf` (it refreshes every 15 minutes) and `backfillDone` (false while the past year is still loading). An area that can't be found returns `404 not_found`. Rows count against your daily lead-row quota.

## Example request

cURL:

```bash
curl -s "https://api.ruuster.com/v1/leads/area-interest?area=Santa%20Rosa%20Beach%2C%20FL&priceMin=500000&limit=2" \
  -H "x-api-key: $RUUSTER_API_KEY" \
  -H "x-email: $RUUSTER_EMAIL"
```

Node.js:

```javascript
const res = await fetch("https://api.ruuster.com/v1/leads/area-interest?area=Santa%20Rosa%20Beach%2C%20FL&priceMin=500000&limit=2", {
  headers: {
    "x-api-key": process.env.RUUSTER_API_KEY,
    "x-email": process.env.RUUSTER_EMAIL,
  },
});
const body = await res.json();
if (!body.ok) throw new Error(`${body.error.code}: ${body.error.message} (${body.requestId})`);
console.log(body.data);
```

Python:

```python
import os
import requests

res = requests.get(
    "https://api.ruuster.com/v1/leads/area-interest?area=Santa%20Rosa%20Beach%2C%20FL&priceMin=500000&limit=2",
    headers={"x-api-key": os.environ["RUUSTER_API_KEY"], "x-email": os.environ["RUUSTER_EMAIL"]},
    timeout=30,
)
body = res.json()
if not body["ok"]:
    raise RuntimeError(f'{body["error"]["code"]}: {body["error"]["message"]} ({body.get("requestId")})')
print(body["data"])
```

## Example response

```json
{
  "ok": true,
  "data": {
    "total": 41,
    "leads": [
      {
        "lead": { "leadId": "unregistered:8d2b6f19-4e37-4a85-b0c9-7f1e3d5a2b68", "firstName": "Priya", "lastName": "Shah",
                  "email": "priya.shah@example.com", "phone": "+18505550187", "crmExternalId": "51907",
                  "crmStatus": "Active Buyer", "crmTags": ["30A"], "agentId": "e5a7d3c1-9b46-4f28-8c0e-6d2a1f7b3e95",
                  "createdAt": "2026-05-23T15:44:12Z", "lastLoginAt": null },
        "savedSearches": [
          { "searchId": "1838c017-0a00-467c-9afc-0f37a0ba2b73", "name": "30A homes", "origin": "crm", "matchedOn": "city",
            "priceMin": 600000, "priceMax": 1500000, "criteria": { "type": ["house"] }, "updatedAt": "2026-10-02T14:10:00Z" }
        ],
        "activity": { "views": 38, "inquiries": 1, "favorites": 0, "tourRequests": 0, "sources": ["Ylopo", "Zillow"],
                      "priceSeen": { "min": 615000, "max": 1450000 }, "priceUnknown": 2, "lastAt": "2026-10-17T15:34:24Z",
                      "examples": ["261 W Bartons Way, Santa Rosa Beach", "11 Beachside Dr #532, Santa Rosa Beach"] }
      },
      {
        "lead": { "leadId": "user:c0ff3e21-8a4b-4c7d-9e15-2b6f8d3a1c04", "firstName": "Sam", "lastName": "Lee",
                  "email": "sam.lee@example.com", "phone": "+18505550142", "crmExternalId": "48213",
                  "crmStatus": "Nurture", "crmTags": [], "agentId": "7c1e9b42-3d85-4a6f-9e07-1b2c8d4f5a69",
                  "createdAt": "2026-03-21T18:20:05Z", "lastLoginAt": "2026-10-15T02:11:40Z" },
        "savedSearches": [],
        "activity": { "views": 152, "inquiries": 0, "favorites": 3, "tourRequests": 0, "sources": ["Ruuster"],
                      "priceSeen": { "min": 505000, "max": 849900 }, "priceUnknown": 0, "lastAt": "2026-10-15T15:38:41Z",
                      "examples": ["96 Tradewinds Dr, Santa Rosa Beach"] }
      }
    ]
  },
  "meta": {
    "area": { "boundaryId": "4b1f2a9e-7c3d-4e8f-9a1b-2c3d4e5f6a7b", "name": "Santa Rosa Beach", "tier": "place", "region": "FL",
              "context": "", "source": "tiger_cdp", "quality": "official" },
    "alternates": [],
    "days": 180,
    "since": "2026-04-22",
    "priceBand": { "min": 500000, "max": null },
    "signals": ["activity", "savedSearch"],
    "counts": { "crmActivityLeads": 39, "listingsInArea": 812, "ruusterViewRows": 640, "savedSearchLinks": 12 },
    "crmEventTypesCovered": ["viewedProperty", "propertyInquiry"],
    "crmEvents": { "asOf": "2026-10-19T21:30:12Z", "backfillDone": true },
    "nextCursor": null,
    "truncated": true
  }
}
```
