# filterProperties

Run a property filter and paginate the matches with limit/offset. Returns a page of properties plus total and hasMore. Pass EITHER filterId (a saved filter from listPropertyFilters) OR filterTree (the same filter-tree DSL saveFilter takes; conditions key `fieldId`, not `field`) to run an UNSAVED tree: same totals, nothing persisted. Use filterTree to verify a filter before saving it, and to see whether a condition keeps a record with no value for its field. NEVER save a filter in order to measure one: save only the final filter the user asked for. Sort with `sort: { field, direction }` (`ASC` / `DESC`). `field` is a CLOSED vocabulary: `spicy_lead_score`, `estimated_value_dollars`, `estimatedRent`, `last_property_signal_date` / `lastPropertySignalDate`, `closed_date` / `closedDate`, `unit_count` / `unitCount`, `latestListingStatusDate` / `z_latest_listing_status_date`, `fsboListedDate`, `frboListedDate`, `fsboListingRemovedDate`, `frboListingRemovedDate`, `listingRemovedDate`, `listingRemovedRentDate`, `listingRemovedSaleDate`, `auction_date` (earliest upcoming auction, properties with none last). Any other field is silently IGNORED (default order, no error), so never infer support from a call that worked. `includeIncompleteRecords: true` lifts the index's completeness gate: by default properties with no parcel identity and no signal (~39% of the index) are HIDDEN, the usual reason a known address is missing. It only widens. Pass the same flag to addPropertiesToList so the bulk selection matches the page shown.

- Call: `POST https://server.goliathdata.com/api/v1/call` with `{ "operationId": "filterProperties", "variables": {...} }`
- Scope: `READ`
- Type: query
- Idempotency: a read; rejects `Idempotency-Key`
- Rate-limited: no
- Result cap: `limit` is clamped to 100, without an error

## Variables

- `filterId`: `ID`
- `filterTree`: `JSON`
- `limit`: `Int` (default `25`)
- `offset`: `Int` (default `0`)
- `sort`: `Sort`
  - `field`: `String!` (required)
  - `direction`: `SortDirection!` (required, one of `ASC`, `DESC`)
- `includeIncompleteRecords`: `Boolean`
- `inSavedAreas`: `Boolean`

## Response (data, an example)

```json
{
  "filterQuery": {
    "applyPropertyFilter": {
      "items": [
        {
          "id": "<ID>",
          "address": {
            "line1": "…",
            "line2": "…",
            "city": "…",
            "state": "…",
            "zip": "…",
            "countyName": "…",
            "addressFull": "…"
          },
          "skipTraceStatus": "PROCESSING",
          "lastSkiptracedAt": "2026-01-01T00:00:00.000Z",
          "isStaleSkiptrace": true,
          "lastPropertySignalDate": "2026-01-01T00:00:00.000Z",
          "spicyLeadScore": 0
        }
      ],
      "pagination": {
        "total": 0,
        "hasMore": true
      }
    }
  }
}
```

## Example

```bash
curl https://server.goliathdata.com/api/v1/call \
  -H "Authorization: Bearer $GOLIATH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "operationId": "filterProperties",
    "variables": {}
  }'
```
