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

# Migrating from v2 to v3

> Field-by-field guide to moving an integration from the v2 to the v3 data generation.

## TL;DR

**Most integrations run unchanged.** v3 serves the same endpoints, the same
authentication, and the same flat response shape as v2 — there is no new URL,
header, or version parameter. Of the v2 response contract, the large majority
of fields return under the same names with the same meanings.

What to check in your integration:

* **Identifiers** — if you persist `_id`, switch to `realieParcelId`. See
  [the warning below](#use-realieparcelid-not-_id).
* **Past-sale fields** — if you read any of the fixed "past/prior sale" scalar
  fields, switch to the `transfers` array, which now carries the full event
  history. See [Removed fields](#removed-fields-57).
* **Coded fields** — 13 coded fields use new code vocabularies. Do not decode
  v3 values against v2 tables; use the
  [Property Feature Field Key](/api-reference/v3/feature-key). See
  [Code vocabularies](#code-vocabularies).
* **Bathrooms** — bathroom counts are now decimals (`2.5`), not truncated
  integers. See [Type changes](#type-changes).

The complete v3 field list is documented in the
[Property Data Schema (v3)](/api-reference/v3/property-data-schema).

## Use realieParcelId, not \_id

<Warning>
  **`_id` is not stable across data releases.** `_id` values are regenerated on
  each data load. If you store `_id` and use it to re-fetch or join properties
  later, those references will break at the next release.

  **`realieParcelId` is the persistent parcel identifier.** It is new in v3,
  returned on every property, and stable across releases. Persist it instead of
  `_id`.
</Warning>

## Restored fields (16)

The v2 debt and ownership analytics — lien rollups, LTV/equity estimates, and
owner tenure counts — were modeled estimates produced by our previous data
provider, not recorded facts. They are carried forward under their **exact v2
field names** as **frozen estimates, captured May 2026** (the final v2 data
refresh). They do not update with new data releases, and they never mix into
the recorded mortgage and lien data.

| Field                     | What it is                                                            |
| ------------------------- | --------------------------------------------------------------------- |
| `totalLienCount` \*       | Count of open liens                                                   |
| `totalLienBalance` \*     | Combined open lien balance                                            |
| `lenderName` \*           | Lender on the most recent mortgage                                    |
| `totalFinancingHistCount` | Count of financing events on record                                   |
| `LTVCurrentEstCombined`   | Estimated current combined loan-to-value                              |
| `LTVCurrentEstRange`      | Range band for the LTV estimate                                       |
| `equityCurrentEstBal`     | Estimated current equity balance                                      |
| `equityCurrentEstRange`   | Range band for the equity estimate                                    |
| `LTVPurchase`             | Loan-to-value at purchase                                             |
| `ownershipStartDate`      | Date the current owner took possession (now returned as `YYYY-MM-DD`) |
| `lengthOfResidenceMonths` | Months the current owner has held the property                        |
| `lengthOfResidenceCode`   | Coded length-of-residence band                                        |
| `ownerParcelCount`        | Parcels held by the same owner                                        |
| `ownerResCount`           | Residential parcels held by the same owner                            |
| `ownerComCount`           | Commercial parcels held by the same owner                             |
| `ownerOriginCode`         | Owner origin code                                                     |

For parcels with no archived analytics, these keys are simply absent, matching
v2's absent-vs-null conventions.

### Recorded facts win: the three starred fields

`totalLienCount`, `totalLienBalance`, and `lenderName` can also be derived
from recorded lien and mortgage records in the new data generation, and
**recorded facts win when known**:

* When lien records are known for a parcel — including a known-empty set,
  which counts as zero — `totalLienCount` and `totalLienBalance` are computed
  from the recorded liens (count, and sum of amounts). The frozen estimate
  fills in only when lien data is entirely unknown for the parcel.
* When mortgage records are known, `lenderName` comes from the most recent
  recorded mortgage. If that record carries no lender name, the field is
  omitted — a known record without a lender never falls back to the frozen
  estimate. The frozen value is used only when no mortgage data is known.

The other 13 restored fields have no recorded-fact counterpart, so no
precedence applies: archived value present → returned; absent → key absent.

## Removed fields (57)

These v2 fields have no equivalent key in v3. They fall into a few families,
and every family has a replacement path except the last.

### Past-sale scalar slots → the `transfers` array

v2 copied individual past sale/transfer events into fixed per-event columns.
v3 returns the full event history instead: the same data (and more) is in the
`transfers` array. Page the array rather than reading fixed "past/prior"
slots.

Removed (31 fields): `assessorSaleBookNumber`, `assessorSaleDocumentNumber`,
`assessorSaleDocumentType`, `assessorSalePageNumber`, `assessorSalePrice`,
`assessorSalePriceCode`, `assessorSaleRecordingDate`, `pastBookSale`,
`pastBookTransfer`, `pastDistressedSale`, `pastDistressedTransfer`,
`pastDocumentNumberSale`, `pastDocumentNumberTransfer`,
`pastDocumentTypeSale`, `pastDocumentTypeTransfer`, `pastPageSale`,
`pastPageTransfer`, `pastPriceCodeSale`, `pastPriceCodeTransfer`,
`pastPriceSale`, `pastPriceTransfer`, `pastRealEstateOwnedSale`,
`pastRealEstateOwnedTransfer`, `pastRecoDateSale`, `pastRecordingDateSale`,
`pastSaleDateTransfer`, `priorSalesDate`, `saleBookLastSale`,
`saleDocumentNumberLastSale`, `saleDocumentTypeLastSale`, `salePageLastSale`

Also removed (5 last-sale/transfer scalars of the same flattening class):
`salePriceCodeLastSale`, `salePriceCodeLastTransfer`, `salePriceLastTransfer`,
`purchaseSaleDate`, `purchaseRecordingDate`. The latest event is covered by
the flat `transferDate`/`transferPrice` fields, and per-event codes by
`transfers[].saleCode`.

`transfers` is sorted **newest-first**, and each entry carries exactly these
11 keys (a key is absent when the source record has no value):

```json theme={null}
{
  "transferDate": "2024-01-05",
  "transferDateObject": "2024-01-05T00:00:00.000Z",
  "transferPrice": 2700000,
  "recordingDate": "2024-01-10",
  "transferDocNum": "2024R0119502",
  "transferDocType": "WD",
  "bookNum": "1234",
  "pageNum": "56",
  "grantee": "SMITH, JOHN",
  "qualified": true,
  "saleCode": "TQ0022"
}
```

The flat latest-sale fields (`transferDate`, `transferPrice`, and the other
latest-sale scalars) are always derived from the newest dated entry of
`transfers`, so the scalars and the array cannot disagree.

### Per-transfer deed flags

Removed (2): `distressedDeedTransfer`, `realEstateOwnedDeedTransfer` — flags
of the retired fixed transfer slots. The latest sale keeps its flat flags
(`distressedSale`, `realEstateOwnedPurchaseSale`); entries of the `transfers`
array do not carry per-event distressed/REO flags.

### Owner name splits

Removed (6): `owner1FirstName`, `owner1MiddleName`, `owner1LastName`,
`owner2FirstName`, `owner2MiddleName`, `owner2LastName`.

The new source delivers owner names as raw `LAST FIRST` strings (`ownerName`,
and now also `ownerName2`); there is no authoritative split today, so these
keys are absent (not empty-string). An owner-name parsing initiative may
restore them in a future release.

### Assessment component scalars

Removed (2): `assessedBuildingValue`, `assessedLandValue` — superseded by
`totalBuildingValue`/`totalLandValue` plus the full `assessments` history
array.

### Administrative fields

Removed (10): `citySection`, `countyUSPS`, `districtNum`, `jurisdiction`,
`legalUnit`, `phaseNum`, `secTwnRng`, `siteId`, `tractNum`,
`forecloseFileDate`.

These convenience fields have no source in the new data generation, or have
structured equivalents:

| Removed             | Use instead                           |
| ------------------- | ------------------------------------- |
| `secTwnRng`         | `section`, `township`, `range`        |
| `tractNum`          | `siteCensusTract`                     |
| `countyUSPS`        | `county`                              |
| `forecloseFileDate` | `forecloseRecordDate` / `auctionDate` |

### Archived: USPS carrier route

Removed (1): `siteCarrierRoute` — not returned by the v3 API, neither flat
nor nested. The underlying value is retained in our archives and may be
restored in a future release.

### Raw codes → descriptive fields

Alongside the removals above, v3 favors readable values over raw source codes
for a few characteristics: air conditioning arrives as the new boolean
`airConditioning`, and building condition and quality arrive as the
descriptive fields `conditionDesc` and `gradeDesc`.

## Type changes

* **`totalBathrooms` — integer → decimal.** After a bathroom-count
  data-quality improvement, fractional values (e.g. `2.5`) are now real JSON
  numbers. The same applies to the room-level bath fields (`fullBathrooms`,
  `halfBathrooms`).
* **`ownershipStartDate` — format.** Now returned as `YYYY-MM-DD` (v2
  returned `YYYYMMDD`).

## New fields worth adopting (32)

The headline additions:

* **`realieParcelId`** — the stable parcel identifier. Persist this, not
  `_id`.
* **`transfers`** — not new, but newly central: it now carries the full sale
  history that v2 spread across fixed past-sale slots, with the 11-key event
  shape shown above.
* **`airConditioning`** — boolean air-conditioning presence.
* **`conditionDesc` / `gradeDesc`** — descriptive building condition and
  quality, replacing raw-code lookups.

The full list of 32 fields absent from the v2 response:

* **Stable key:** `realieParcelId`
* **Identity / location:** `ownerName2`, `geometry`, `location`,
  `zipCodePlusFour`, `fullAddress`, `formattedAddress`
* **Aliases of kept fields:** `legalDescription` (= `legalDesc`), `lotNumber`
  (= `lotNum`), `blockNumber` (= `blockNum`)
* **Building:** `roomCount`, `unitCount`, `effectiveYearBuilt`,
  `fullBathrooms`, `halfBathrooms`, `airConditioning`, `styleDesc`,
  `conditionDesc`, `gradeDesc`
* **Land:** `depth`
* **Sale:** `qualified` — boolean qualification of the latest sale; also
  per-event on `transfers[]`
* **Valuation:** `compModelValue`, `compModelValueMin`, `compModelValueMax`,
  `compPpsf`, `compCount`, `compMaxDistMi`, `compWindowMo`,
  `compModelVersion`, `modelVersion`, `estimateAgreementPct`, and
  `modelConfidenceBucket`

<Note>
  **Internal model fields.** `modelConfidenceBucket` is internal-only and not
  returned by the public API. The v2-era model diagnostics
  (`modelValueStdDev`, `modelConfidence`, `modelDate`, `modelValueRange`) and
  `realieSquareFootage` likewise remain excluded from public responses —
  unchanged from v2, which excluded the same set.
</Note>

## Code vocabularies

**13 fields change vocabulary.** The keys are unchanged, but the values are
not the v2 letter codes — do not decode them against v2 tables. Decode every
value with the [Property Feature Field Key](/api-reference/v3/feature-key):

| Field                  | Decode table                                       |
| ---------------------- | -------------------------------------------------- |
| `wallType`             | [Feature Field Key](/api-reference/v3/feature-key) |
| `garageType`           | [Feature Field Key](/api-reference/v3/feature-key) |
| `basementType`         | [Feature Field Key](/api-reference/v3/feature-key) |
| `constructionType`     | [Feature Field Key](/api-reference/v3/feature-key) |
| `floorType`            | [Feature Field Key](/api-reference/v3/feature-key) |
| `poolCode`             | [Feature Field Key](/api-reference/v3/feature-key) |
| `roofType`             | [Feature Field Key](/api-reference/v3/feature-key) |
| `roofStyle`            | [Feature Field Key](/api-reference/v3/feature-key) |
| `lotCode`              | [Feature Field Key](/api-reference/v3/feature-key) |
| `buyerIDCode`          | [Feature Field Key](/api-reference/v3/feature-key) |
| `buyerVestingCode`     | [Feature Field Key](/api-reference/v3/feature-key) |
| `transfers[].saleCode` | [Feature Field Key](/api-reference/v3/feature-key) |
| `forecloseCode`        | [Feature Field Key](/api-reference/v3/feature-key) |

Notes:

* **`useCode` is unchanged** — the same 4-digit scheme as v2. A small number
  of v2 codes are retired by the new source: for example, in Florida the
  generic codes `4001` and `8017` are retired and those parcels are re-coded
  to specific successor codes.
* **`buyerVestingCode` numeric values are by design** — the new vocabulary,
  not a data defect (e.g. code `60` = "Limited Liability Company /
  Partnership").
* **`transferDocType`** — a small share of records (\~2%) carry numeric source
  codes not yet in the named table; they will be folded into named codes in
  an upcoming release.
* **`transfers[].saleCode` uses the Realie code system** (`TQ####`
  sale-qualification codes, e.g. `TQ0022` = valid arm's-length sale,
  `TQ0013` = non-market or forced transfer) — one vocabulary across every
  sale event. The related `priceDerivation` codes (`PD####`, how the price
  figure was obtained) are included in bulk exports today and come to API
  responses in an upcoming release.

## Data freshness

Sale histories now extend through **mid-May 2026 in most states**, via a
fast-path append of recent recordings. Appended recent events carry a reduced
record shape until they backfill in subsequent data releases:

* `qualified` is absent on nearly all events recorded after March 2026 (the
  qualification determination lags the recording), and seller (grantor) and
  title-company details are similarly not yet attached.
* `transfers[].saleCode` (`TQ####`) carries the qualification semantics —
  prefer it over `qualified` for recent events.
* `transferPrice` is sparse on recent events in non-disclosure states (for
  example Texas), where recorded documents do not carry a price.

## One more vocabulary change is coming

Sale-qualification and price-derivation codes already use **Realie's own
code system** (`TQ####`/`PD####`). Building and characteristic code values
migrate to prefixed Realie codes in an upcoming data release. We are
pre-announcing it so you can plan for exactly one further vocabulary change
after this migration. The complete
mapping will be published in the [changelog](/api-reference/v3/changelog)
before it ships.
