---
title: "Get parcel by ID"
method: GET
path: "/api/v1/parcels/{id}"
tags: ["Parcels"]
---

# Get parcel by ID

`GET /api/v1/parcels/{id}`

## Request

- Base URL: `https://propraven.com`
- URL: `https://propraven.com/api/v1/parcels/{id}`
- Auth: HTTP bearer

Retrieve a single parcel by its composite ID (county_fips:parcel_id).

## Path parameters

- `id` string, required

## Response `200`

Parcel found.

- Parcel
  - `id` string, uuid, required: PropRaven parcel UUID. Accepted by GET /parcels/{id}.
  - `county_fips` string, required: 3-digit within-state county FIPS code (the 5-digit form is `state_fips` + `county_fips`).
  - `state_fips` string, required: 2-digit state FIPS code.
  - `parcel_id` string, required: County-assigned parcel identifier (APN as the county publishes it). The canonical id is `state_fips:county_fips:parcel_id`.
  - `address` string, nullable, required
  - `normalized_address` string, nullable, required
  - `city` string, nullable, required
  - `state` string, nullable, required: USPS 2-letter state code of `state_fips` ("37" → "NC"). Always a string; the 2-digit FIPS is `state_fips`.
  - `zip` string, nullable, required
  - `zip5` string, nullable, required
  - `zip_plus4` string, nullable, required
  - `latitude` number, nullable, required
  - `longitude` number, nullable, required
  - `land_use_code` string, nullable, required
  - `land_use_desc` string, nullable, required
  - `total_assessed_value` number, nullable, required
  - `land_assessed_value` number, nullable, required
  - `improvement_assessed_value` number, nullable, required
  - `last_sale_price` number, nullable, required: Price of the last sale. From the parcel record; where null, filled from the same county-recorder deed that supplies `last_sale_date` (`last_sale_price_basis: county_recorder_deeds`). A nominal consideration (≤ $1,000) is never served as a price. A sentinel price ($0, $1 or $100) is served as null with `last_sale_price_raw` and `last_sale_price_flag: sentinel_value` (#557).
  - `last_sale_date` string, date, nullable, required: Date of the last sale. From the parcel record; where the record's date is null or withheld (e.g. a county collection stamp, `site_gate`), filled from the latest arm's-length transfer in the county recorder's per-deed rows (`last_sale_date_basis: county_recorder_deeds`, `last_sale_source: "County recorder (deeds)"`).
  - `market_value` number, nullable, required: County market value: the market (just / full cash / appraised) value on the county assessor's record, or null when the record carries none. Never PropRaven's model output: a stored value that is the same figure as `avm_value` (and not the county's own assessed value) is withheld here and `market_value_basis` says so. PropRaven's model is `avm_value` ("PropRaven estimate").
  - `avm_value` number, nullable, required: PropRaven estimate: PropRaven's own automated valuation (a model output — see `avm_method`, `avm_method_family`, `avm_method_basis`). Not the county's value and not a licensed appraisal. Display it as "PropRaven estimate", never as "market value".
  - `avm_confidence` string, nullable, required
  - `avm_method` string, nullable, required
  - `tax_amount` number, nullable, required
  - `tax_year` integer, nullable, required
  - `deal_score` number, nullable, required: Composite deal opportunity score from 0 to 100.
  - `price_per_sqft` number, nullable, required
  - `comp_sale_price` number, nullable, required
  - `comp_sale_date` string, nullable, required
  - `comp_similarity_score` number, nullable, required
  - `estimated_monthly_rent` number, nullable, required
  - `estimated_annual_rent` number, nullable, required
  - `rent_yield_pct` number, nullable, required
  - `rental_confidence` string, nullable, required
  - `gross_rent_multiplier` number, nullable, required
  - `land_improvement_ratio` number, nullable, required
  - `improvement_to_land_ratio` number, nullable, required
  - `is_redevelopment_candidate` boolean, nullable, required
  - `building_sqft` number, nullable, required
  - `year_built` integer, nullable, required
  - `lot_size_acres` number, nullable, required
  - `lot_size_sqft` number, nullable, required
  - `bedrooms` integer, nullable, required
  - `bathrooms` number, nullable, required
  - `stories` number, nullable, required
  - `units` integer, nullable, required
  - `unit_count` integer, nullable, required
  - `construction_type` string, nullable, required
  - `owner_name` string, nullable, required
  - `owner_address` string, nullable, required: Owner's mailing street line. Read from whichever mailing column family the record fills (owner_address/… or owner_mailing_/…), one family per parcel — the same rule as GET /api/v1/parcels/{id}/owner. People data: requires an account; metered and logged (see `owner_mailing_fields`).
  - `owner_city` string, nullable, required: Owner's mailing city, from the same family as `owner_address`.
  - `owner_state` string, nullable, required: Owner's mailing state, from the same family as `owner_address`.
  - `owner_zip` string, nullable, required: Owner's mailing ZIP, from the same family as `owner_address`.
  - `ownership_type` string, nullable, required
  - `owner_entity_type` string, nullable, required
  - `entity_type` string, nullable, required
  - `is_entity_owned` boolean, nullable, required
  - `is_absentee` boolean, nullable, required
  - `is_pe_aggregator` boolean, nullable, required
  - `owner_occupied_flag` boolean, nullable, required
  - `owner_occupied_flag_basis` string: How the served owner_occupied_flag was derived (one rule with is_absentee, so the row never says both absentee and owner-occupied): `recomputed_from_row` = from this record's own mailing address versus its situs; `input_missing` = the record lacks those inputs and owner_occupied_flag is null. Present whenever owner_occupied_flag is served and the derivation ran.
  - `data_quality_score` number, nullable, required
  - `flood_zone` string, nullable, required
  - `is_sfha` boolean, nullable, required
  - `is_opportunity_zone` boolean, nullable, required
  - `is_justice40` boolean, nullable, required
  - `is_flip` boolean, nullable, required
  - `deed_count` integer, nullable, required
  - `permit_count` integer, nullable, required
  - `permit_count_12mo` integer, nullable, required
  - `zoning` string, nullable, required
  - `county_name` string, nullable, required
  - `property_type` string, nullable, required
  - `_guards` string[], required
  - `is_flip_basis` string, required
  - `land_improvement_ratio_stored` number, nullable, required
  - `land_improvement_ratio_basis` string, required
  - `improvement_to_land_ratio_basis` string, required
  - `is_absentee_basis` string, required
  - `owner_state_norm` string, nullable, required
  - `is_out_of_state` boolean, nullable, required
  - `identity_gate` object, required
    - `applied` boolean, nullable, required
    - `suppressed` string[], required
    - `reason` string, nullable, required
    - `join_key_basis` string, required
    - `twins_in_other_counties` integer, nullable, required
    - `coords_basis` string, required
    - `unmeasured` string[], required
    - `served_under_doubt` string[], required
    - `note` string, nullable, required
  - `site_gate` object, required
    - `applied` boolean, nullable, required
    - `suppressed` string[], required
    - `reason` string, nullable, required
    - `labelled` string[], required
    - `mailing_basis` string, required
    - `note` string, nullable, required
  - `derived_gate` object, required
    - `applied` boolean, nullable, required
    - `suppressed` string[], required
    - `recomputed` string[], required
    - `unevaluated` unknown[], required
      - unknown
    - `reason` string, nullable, required
    - `note` string, nullable, required
  - `rent_gate` object, required
    - `applied` boolean, nullable, required
    - `suppressed` string[], required
    - `reason` string, nullable, required
    - `rental_confidence` string, nullable, required
    - `note` string, nullable, required
  - `county_name_basis` string, required
  - `avm_method_family` string, nullable, required
  - `avm_method_basis` string, required
  - `is_flip_dominant_share_pct` number, nullable
  - `price_per_sqft_basis` string: What price_per_sqft divides by building_sqft, read from the row (#557): `market_value` (county market value), `avm_value` (PropRaven estimate), `total_assessed_value`, `last_sale_price`, `unreproduced` (no served value reproduces it), or `input_missing` (no building_sqft; the ratio is withheld).
  - `market_value_basis` 'county_record' | 'propraven_estimate' | 'unavailable': What `market_value` is: `county_record` (the record's market-value column as the county source published it), `propraven_estimate` (the stored value was PropRaven's own estimate, so `market_value` is null; the estimate is in `avm_value`), or `unavailable`.
  - `market_value_note` string: Present when `market_value` was withheld because it was PropRaven's estimate, not the county's value.
  - `value_labels` object: The display label for each value field: `market_value` → "County market value", `avm_value` → "PropRaven estimate".
    - `market_value` 'County market value', required
    - `avm_value` 'PropRaven estimate', required
  - `last_sale_date_basis` string: Why `last_sale_date` holds what it does: `county_recorder_deeds` when filled from the deeds, or the site gate's reason when the record's own date was withheld (e.g. `sale_date_modal_collection_stamp`).
  - `last_sale_date_raw` string, nullable: The record's own last-sale date when the site gate withheld it (evidence, not a sale date).
  - `last_sale_price_basis` string: `county_recorder_deeds` when `last_sale_price` was filled from the deeds; `nominal_consideration_not_a_price` / `not_recorded_on_deed` when the date was filled but the deed carries no market price.
  - `last_sale_source` 'County recorder (deeds)': Present when a last-sale field was filled from deeds: "County recorder (deeds)".
  - `mailing_family_basis` 'owner_mailing': Present when the owner mailing fields were read from the `owner_mailing_*` column family because the `owner_address` family is not mail-ready: `owner_mailing`.
  - `assessed_value_parts_check` object: Whether land_assessed_value + improvement_assessed_value equals total_assessed_value within 1 % (floor $1). The three values are served as recorded either way (#557).
    - `status` 'within_tolerance' | 'parts_do_not_sum', required
    - `land_plus_improvement` number, required
    - `total_assessed_value` number, required
    - `difference` number, required
    - `difference_pct` number, nullable, required
    - `tolerance_pct` number, required
    - `note` string
  - `price_per_sqft_note` string: The formula behind price_per_sqft_basis, in words.
  - `entity_type_raw` string, nullable: The name-pattern entity_type when it was reconciled to owner_entity_type for a government owner (#557).
  - `entity_type_basis` string: `reconciled_to_owner_entity_type` when entity_type was overridden.
  - `entity_type_note` string
  - `land_use_code_raw` string, nullable: The stored land_use_code when the code/description pair was swapped at source and served swapped back.
  - `land_use_desc_raw` string, nullable: The stored land_use_desc when it was a code (withheld) or part of a swapped pair.
  - `land_use_basis` string: `swapped_at_source`: land_use_code and land_use_desc were stored in each other's fields.
  - `land_use_desc_basis` string: `code_not_description`: the source's description field holds a code (e.g. DC tax class, a second NY property-class code); withheld, kept as land_use_desc_raw.
  - `land_use_desc_note` string
  - `last_sale_price_raw` number: The stored sale price when it is a sentinel ($0 / $1 / $100) served as null.
  - `last_sale_price_flag` 'sentinel_value'
  - `is_redevelopment_candidate_raw` union: The stored flag when it was served false for a government-owned parcel.
    - boolean
    - string
  - `is_redevelopment_candidate_basis` string: `government_owner`: a government-owned parcel is not a redevelopment candidate.

## Other responses

- `400`: A query or body parameter is invalid. Nothing was read or charged.
- `401`: Missing, malformed or invalid credential.
- `404`: The resource (or the endpoint) does not exist.
- `405`: The endpoint exists but does not support this method. `Allow` lists the methods it does.
- `429`: Rate limit exceeded.
- `500`: Unexpected server error. The body never carries database or driver text.

---

[API](https://skmtc.dev/propraven/apis/propraven-api.md) · [All operations](https://skmtc.dev/propraven/apis/propraven-api/llms.txt) · [OpenAPI document](https://skmtc.dev/propraven/apis/propraven-api/revisions/37f8158c4eda?raw)
