> ## 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.

# Enrich by APN

Look up properties by Assessor's Parcel Number (APN). Each item in the `data` array provides an `apn`, and the API normalizes formatting automatically (dashes, spaces, dots are all handled). Optionally include a `location` to narrow results to a specific area.

<Note>
  Each request accepts up to **250 items** in the `data` array. The response returns every submitted
  item with a `matched` flag indicating whether a property was found.
</Note>

## Body Parameters

<ParamField body="data" type="array" required>
  Array of APN objects to look up (max 250).

  <Expandable title="APN object properties">
    <ParamField body="apn" type="string" required>
      Assessor's Parcel Number (e.g., `"0123-45-6789"`). Formatting varies by county — the API normalizes to the raw unformatted form automatically.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="location" type="object">
  Location to narrow results to a specific area. When omitted, results are not filtered by location.

  <Expandable title="Location object properties">
    <ParamField body="type" type="string" required>
      Location type: `"state"`, `"zip_code"`, or `"county"`.
    </ParamField>

    <ParamField body="code" type="string" required>
      Location code. For states, use the 2-letter abbreviation (e.g., `"TX"`). For ZIP codes, use the 5-digit code (e.g., `"78704"`). For counties, use the FIPS code (e.g., `"48453"`).
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="fields" type="string[]">
  [Field IDs](/concepts/fields) to include in results. Can include both property and people fields.
  Omit or pass an empty array for the default set.
</ParamField>

<ParamField body="contact_audience" type="string">
  Which contacts to include on matched properties.

  Options: `owners`, `owners_and_family`, `renters`, `residents`, `none`

  Use `none` or omit this parameter to return property data without contacts or people data credit charges. Any other value includes a `contacts` array.
</ParamField>

***

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.v2.dealmachine.com/v1/enrichment/apn" \
    -H "Authorization: Bearer dm_sk_live_xxx" \
    -H "Content-Type: application/json" \
    -d '{
      "data": [
        { "apn": "0123-45-6789" },
        { "apn": "9876-54-3210" }
      ],
      "location": { "type": "state", "code": "TX" },
      "fields": ["estimated_value", "equity_percent", "bedrooms", "full_name", "phones"],
      "contact_audience": "owners"
    }'
  ```

  ```typescript Node.js theme={null}
  const response = await fetch('https://api.v2.dealmachine.com/v1/enrichment/apn', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      data: [{ apn: '0123-45-6789' }, { apn: '9876-54-3210' }],
      location: { type: 'state', code: 'TX' },
      fields: ['estimated_value', 'equity_percent', 'bedrooms', 'full_name', 'phones'],
      contact_audience: 'owners',
    }),
  });

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

  console.log(`Matched ${totals.matched} of ${totals.submitted}`);
  for (const item of data) {
    if (item.matched) {
      console.log(
        `APN ${item.input.apn} → ${item.full_address} — $${item.estimated_value.toLocaleString()}`
      );
    } else {
      console.log(`No match for APN ${item.input.apn}`);
    }
  }
  ```

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

  response = requests.post(
      "https://api.v2.dealmachine.com/v1/enrichment/apn",
      headers={"Authorization": f"Bearer {api_key}"},
      json={
          "data": [
              {"apn": "0123-45-6789"},
              {"apn": "9876-54-3210"},
          ],
          "location": {"type": "state", "code": "TX"},
          "fields": [
              "estimated_value",
              "equity_percent",
              "bedrooms",
              "full_name",
              "phones",
          ],
          "contact_audience": "owners",
      },
  )

  body = response.json()
  for item in body["data"]:
      if item["matched"]:
          print(f"APN {item['input']['apn']} → {item['full_address']} — ${item['estimated_value']:,}")
      else:
          print(f"No match for APN {item['input']['apn']}")
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "data": [
      {
        "input": {
          "apn": "0123-45-6789"
        },
        "matched": true,
        "dm_property_id": "prop_a1b2c3",
        "full_address": "1200 Barton Springs Rd, Austin, TX 78704",
        "address": "1200 Barton Springs Rd",
        "city": "Austin",
        "state": "TX",
        "zip": "78704",
        "latitude": 30.2598,
        "longitude": -97.7544,
        "images": {
          "street_view": "https://img.dealmachine.com/sv/30.2598,-97.7544.jpg",
          "satellite": "https://img.dealmachine.com/sat/30.2598,-97.7544.jpg",
          "roadmap": "https://img.dealmachine.com/map/30.2598,-97.7544.jpg"
        },
        "estimated_value": 575000,
        "equity_percent": 72,
        "bedrooms": 4,
        "contacts": [
          {
            "dm_person_id": "per_x1y2z3",
            "full_name": "John Smith",
            "phones": [{ "number": "5125551234", "type": "wireless", "do_not_call": false }],
            "match_status": "matched"
          }
        ]
      },
      {
        "input": {
          "apn": "9876-54-3210"
        },
        "matched": false,
        "match_failure": {
          "code": "not_found",
          "reason": "No property found matching the provided APN in this county"
        }
      }
    ],
    "totals": {
      "submitted": 2,
      "matched": 1,
      "unmatched": 1
    },
    "credits": {
      "used": 1,
      "properties": 1,
      "people": 0,
      "deduplicated": 0
    }
  }
  ```

  ```json 400 Validation Error theme={null}
  {
    "error": {
      "code": "validation_error",
      "message": "Validation failed",
      "request_id": "req_abc123def456",
      "details": {
        "issues": [
          {
            "path": "apns[0].apn",
            "message": "Required"
          }
        ]
      }
    }
  }
  ```

  ```json 401 Unauthorized theme={null}
  {
    "error": {
      "code": "invalid_api_key",
      "message": "The provided API key is invalid",
      "request_id": "req_def456ghi789"
    }
  }
  ```

  ```json 429 Rate Limited theme={null}
  {
    "error": {
      "code": "rate_limit_exceeded",
      "message": "Too many requests. Please retry after the specified time.",
      "request_id": "req_ghi789jkl012"
    }
  }
  ```
</ResponseExample>

## Response Fields

The response contains a `data` array and a `totals` object. There is no pagination — all submitted items are returned in a single response.

### Matched Result

When `matched` is `true`, the result contains all [always-included property fields](/concepts/response-format#properties) plus any requested fields.

| Field                             | Type    | Description                                                                           |
| --------------------------------- | ------- | ------------------------------------------------------------------------------------- |
| `input`                           | object  | Echo of the original input object                                                     |
| `matched`                         | boolean | `true`                                                                                |
| `dm_property_id`                  | string  | DealMachine internal property ID                                                      |
| `full_address`                    | string  | Complete formatted address                                                            |
| `address`, `city`, `state`, `zip` | string  | Parsed address components                                                             |
| `latitude`, `longitude`           | number  | Property coordinates                                                                  |
| `images`                          | object  | Signed URLs for `street_view`, `satellite`, and `roadmap`                             |
| `contacts`                        | array   | Contacts matching `contact_audience`. Omitted when the audience is `none` or not set. |
| *requested fields*                | varies  | Any fields specified in `fields`                                                      |

### Unmatched Result

| Field                  | Type    | Description                                                                           |
| ---------------------- | ------- | ------------------------------------------------------------------------------------- |
| `input`                | object  | Echo of the original input object                                                     |
| `matched`              | boolean | `false`                                                                               |
| `match_failure`        | object  | Structured failure with `code` and `reason`                                           |
| `match_failure.code`   | string  | Machine-readable failure code (see [Match Failure Codes](#match-failure-codes) below) |
| `match_failure.reason` | string  | Human-readable explanation of why no match was found                                  |

### Match Failure Codes

These codes are shared across all enrichment endpoints.

| Code            | Description                                                                                                                           |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `not_found`     | No matching record exists for the provided input                                                                                      |
| `invalid_input` | The input could not be processed (e.g., invalid address, invalid email, invalid phone number). The `reason` field provides specifics. |

### Totals

| Field       | Type    | Description                                 |
| ----------- | ------- | ------------------------------------------- |
| `submitted` | integer | Number of items in the request `data` array |
| `matched`   | integer | Number of items that matched a property     |
| `unmatched` | integer | Number of items that did not match          |

## Credits

This endpoint consumes 1 [property data credit](/concepts/credits) per matched property. A non-`none` `contact_audience` adds people data credits for included contacts. Use `none` for zero people data credits. Only matched results consume credits. Credits are deduplicated within your billing period, so accessing the same entity again is free.

Every response includes a `credits` object with a full breakdown of what was charged. See [Credits](/concepts/credits) for details.

## Notes

* Each item only requires the `apn` field. The API normalizes formatting (dashes, dots, spaces) to the raw unformatted form automatically.
* The `location` parameter is optional. When provided, results are scoped to that area. When omitted, the search is nationwide.
* Items are matched independently — one failed match does not affect others.
* The `input` object is always echoed back so you can correlate results with your input data.
* When `contact_audience` is set to an audience other than `none`, each matched result includes a `contacts` array with the same structure and match behavior as [Search Properties](/api-reference/properties/search-properties#contact-match-status).
