> ## Documentation Index
> Fetch the complete documentation index at: https://api.docs.dealmachine.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Searching

> How to search for properties and people using the DealMachine API

The DealMachine API lets you search for properties and people using a powerful combination of filters, field selection, pagination, and sorting. This page walks through the complete workflow.

## The Search Workflow

Searching follows three steps:

<Steps>
  <Step title="Discover">
    Use the discovery endpoints to find available filters and fields: - [List
    Filters](/api-reference/filters/list-filters) — see what you can search by - [List
    Fields](/api-reference/fields/list-fields) — see what data you can return
  </Step>

  <Step title="Build">
    Construct your search request: - Pick filters and set their operators and values - Choose which
    fields to include in the response - Set pagination and sorting preferences
  </Step>

  <Step title="Search">
    Send your request to the appropriate search endpoint: - [Search
    Properties](/api-reference/properties/search-properties) — `POST /v1/properties/search` -
    [Search People](/api-reference/people/search-people) — `POST /v1/people/search`
  </Step>
</Steps>

## Search Endpoints

| Endpoint                | Method | Description                |
| ----------------------- | ------ | -------------------------- |
| `/v1/properties/search` | POST   | Search for properties      |
| `/v1/people/search`     | POST   | Search for people/contacts |

Both endpoints use POST because the filter arrays and request bodies are too complex for query parameters.

## Request Structure

Every search request has the same structure:

```json theme={null}
{
  "locations": [
    { "type": "state", "code": "TX" },
    { "type": "zip_code", "code": "90210" }
  ],
  "filters": [
    {
      "filter_id": "estimated_value",
      "operator": "range",
      "value": { "min": 100000, "max": 500000 }
    },
    {
      "filter_id": "equity_percent",
      "operator": "greater_than",
      "value": 40
    }
  ],
  "fields": ["estimated_value", "equity_percent", "last_sale_date", "owner_name"],
  "page": 1,
  "per_page": 25,
  "sort": [{ "field_id": "estimated_value", "direction": "desc" }]
}
```

| Parameter                     | Type           | Required    | Description                                                                                                                                                           |
| ----------------------------- | -------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `locations`                   | array          | Conditional | Array of [location objects](/concepts/locations) defining where to search (max 15, OR logic). Required unless filters or Query Builder protocol filters are provided. |
| `filters`                     | array          | Conditional | Array of [filter objects](/concepts/filter-values). Required unless locations or Query Builder protocol filters are provided.                                         |
| `fields`                      | string\[]      | No          | [Field IDs](/concepts/fields) to include in results. Omit for defaults.                                                                                               |
| `page`                        | integer        | No          | Page number (default: `1`)                                                                                                                                            |
| `per_page`                    | integer        | No          | Results per page (default: `25`, max: `250`)                                                                                                                          |
| `sort`                        | array          | No          | [Sort objects](/concepts/pagination#sorting) for ordering results                                                                                                     |
| `include_lists`               | object         | No          | Restrict results to records in list IDs for the searched entity (`property_list_ids`, `people_list_ids`, or `company_list_ids`).                                      |
| `exclude_lists`               | object         | No          | Exclude records in list IDs for the searched entity.                                                                                                                  |
| `exclude_previously_exported` | boolean/object | No          | Exclude records already exported by your organization. Pass `true` for the default entity criteria or a full Query Builder object.                                    |
| `bigquery_data_environment`   | integer        | No          | Query Builder dataset environment: `1` production, `2` staging, `3` development.                                                                                      |

## Search Logic

**Locations** use **OR** logic — a record is included if it falls within any of the provided locations.

**Filters** use **AND** logic — every filter must match for a record to be included.

```json theme={null}
{
  "locations": [
    { "type": "county", "code": "48201" },
    { "type": "zip_code", "code": "78704" }
  ],
  "filters": [
    {
      "filter_id": "estimated_value",
      "operator": "range",
      "value": { "min": 200000, "max": 600000 }
    },
    { "filter_id": "is_absentee_owner", "value": true }
  ]
}
```

This finds properties that are:

* In Harris County, TX **OR** ZIP 78704 (locations — OR)
* **AND** valued between $200k–$600k (filter — AND)
* **AND** owned by an absentee owner (filter — AND)

There is no OR grouping or nesting for filters. To achieve OR-like behavior for a single filter field, use operators like `contains_any` or `any_of`. For geographic OR logic, use multiple [locations](/concepts/locations).

## List And Export Protocol Filters

Search, count, and export endpoints also accept the Query Builder protocol fields for list membership and previous-export exclusion. The API fills `organization_id` and `organization_partition_key` from your API key, so most requests only need list IDs or `true` for export exclusion:

```json theme={null}
{
  "locations": [],
  "include_lists": { "property_list_ids": [123, 456] },
  "exclude_lists": { "property_list_ids": [789] },
  "exclude_previously_exported": true,
  "bigquery_data_environment": 3
}
```

For people endpoints, use `people_list_ids`; for property endpoints, use `property_list_ids`. You may also pass the full `exclude_previously_exported` object when you need date, source, export type, credit type, or `credits_used` criteria.

## Field Selection

Use the `fields` array to control which data points appear in the response:

```json theme={null}
{ "fields": ["estimated_value", "equity_percent", "last_sale_date"] }
```

* Pass an array of `field_id` strings from the [List Fields](/api-reference/fields/list-fields) endpoint.
* Omit `fields` or pass an empty array to get the default set of fields.
* Some base fields (address, internal ID) are always included regardless. See [Response Format](/concepts/response-format#always-included-fields).

<Tip>
  Filters select records; fields select returned data. You can filter owners by property criteria
  without adding property credits when you use `anchor: "people"` and return only property
  address/context fields. See [Credit-efficient queries](/concepts/credit-efficient-queries).
</Tip>

## Complete Example

Here's a full end-to-end example: find high-equity absentee-owned single-family homes across Harris County and Dallas County in Texas, sorted by value.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.v2.dealmachine.com/v1/properties/search" \
    -H "Authorization: Bearer dm_sk_live_xxx" \
    -H "Content-Type: application/json" \
    -d '{
      "locations": [
        { "type": "county", "code": "48201" },
        { "type": "county", "code": "48113" }
      ],
      "filters": [
        {
          "filter_id": "property_type_id",
          "operator": "contains_any",
          "value": [1]
        },
        {
          "filter_id": "equity_percent",
          "operator": "greater_than_or_equal",
          "value": 40
        },
        {
          "filter_id": "is_absentee_owner",
          "value": true
        }
      ],
      "fields": [
        "estimated_value",
        "equity_percent",
        "last_sale_date",
        "owner_name",
        "bedrooms",
        "bathrooms",
        "square_footage"
      ],
      "page": 1,
      "per_page": 25,
      "sort": [
        { "field_id": "estimated_value", "direction": "desc" }
      ]
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.v2.dealmachine.com/v1/properties/search', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer dm_sk_live_xxx',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      locations: [
        { type: 'county', code: '48201' },
        { type: 'county', code: '48113' },
      ],
      filters: [
        {
          filter_id: 'property_type_id',
          operator: 'contains_any',
          value: [1],
        },
        {
          filter_id: 'equity_percent',
          operator: 'greater_than_or_equal',
          value: 40,
        },
        {
          filter_id: 'is_absentee_owner',
          value: true,
        },
      ],
      fields: [
        'estimated_value',
        'equity_percent',
        'last_sale_date',
        'owner_name',
        'bedrooms',
        'bathrooms',
        'square_footage',
      ],
      page: 1,
      per_page: 25,
      sort: [{ field_id: 'estimated_value', direction: 'desc' }],
    }),
  });

  const { data, pagination } = await response.json();

  console.log(`Found ${pagination.total_results} properties`);
  for (const property of data) {
    console.log(
      `${property.address}, ${property.city} — $${property.estimated_value.toLocaleString()}`
    );
  }
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.v2.dealmachine.com/v1/properties/search",
      headers={"Authorization": "Bearer dm_sk_live_xxx"},
      json={
          "locations": [
              {"type": "county", "code": "48201"},
              {"type": "county", "code": "48113"},
          ],
          "filters": [
              {
                  "filter_id": "property_type_id",
                  "operator": "contains_any",
                  "value": [1],
              },
              {
                  "filter_id": "equity_percent",
                  "operator": "greater_than_or_equal",
                  "value": 40,
              },
              {
                  "filter_id": "is_absentee_owner",
                  "value": True,
              },
          ],
          "fields": [
              "estimated_value",
              "equity_percent",
              "last_sale_date",
              "owner_name",
              "bedrooms",
              "bathrooms",
              "square_footage",
          ],
          "page": 1,
          "per_page": 25,
          "sort": [{"field_id": "estimated_value", "direction": "desc"}],
      },
  )

  body = response.json()
  print(f"Found {body['pagination']['total_results']} properties")

  for prop in body["data"]:
      print(f"{prop['address']}, {prop['city']} — ${prop['estimated_value']:,}")
  ```
</CodeGroup>

### Example Response

```json theme={null}
{
  "data": [
    {
      "dm_property_id": "prop_a1b2c3",
      "address": "1200 Barton Springs Rd",
      "city": "Austin",
      "state": "TX",
      "code": "78704",
      "estimated_value": 875000,
      "equity_percent": 72,
      "last_sale_date": "2015-08-20",
      "owner_name": "Johnson Family Trust",
      "bedrooms": 4,
      "bathrooms": 3,
      "square_footage": 2800
    },
    {
      "dm_property_id": "prop_d4e5f6",
      "address": "4500 Oak Lawn Ave",
      "city": "Dallas",
      "state": "TX",
      "zip": "75219",
      "estimated_value": 650000,
      "equity_percent": 55,
      "last_sale_date": "2018-03-10",
      "owner_name": "Robert Chen",
      "bedrooms": 3,
      "bathrooms": 2,
      "square_footage": 2100
    }
  ],
  "pagination": {
    "page": 1,
    "per_page": 25,
    "total_results": 3412,
    "total_pages": 137,
    "has_next_page": true,
    "has_previous_page": false
  }
}
```

## Related Guides

<CardGroup cols={2}>
  <Card title="Locations" icon="map-location-dot" href="/concepts/locations">
    Define where to search — states, counties, ZIP codes, radius, and polygons.
  </Card>

  <Card title="Filter Values" icon="sliders" href="/concepts/filter-values">
    Complete reference for every operator and its expected value shape.
  </Card>

  <Card title="Pagination & Sorting" icon="arrow-down-1-9" href="/concepts/pagination">
    Control page size, navigate results, and sort by multiple fields.
  </Card>

  <Card title="Response Format" icon="brackets-curly" href="/concepts/response-format">
    Understand the data + pagination response envelope.
  </Card>

  <Card title="Filters" icon="filter" href="/concepts/filters">
    Learn about filter types, operators, and categories.
  </Card>

  <Card title="Fields" icon="table-columns" href="/concepts/fields">
    Explore available data fields and their capabilities.
  </Card>

  <Card title="Credits" icon="coins" href="/concepts/credits">
    Understand how search requests consume credits.
  </Card>
</CardGroup>
