---
title: "Get Properties By Id"
method: GET
path: "/properties"
tags: ["Properties", "Properties"]
---

# Get Properties By Id

`GET /properties`

**Beta.** Query parameters, response fields, and the absence-trust surface may still change in response to how the endpoint is used in practice. Treat the shape as unstable while it is in beta. Returns properties by their address id. Provide up to 50 `id` query parameters in one call; rows come back in request order and unknown ids are omitted (no per-id 404). A non-address geolocation id (city, county, or jurisdiction) is rejected.

## Query parameters

- `id` string[], required — Address geolocation id. Up to 50 `id` params per request.

## Response `200`

The requested properties, in request order.

- PaginatedPropertiesResponse — Paginated /properties response; carries the honesty summary on absence pages.
  - `items` PropertiesRead[], required — The list of items returned in the response following given criteria.
    - `id` string, required — The base64 address handle; the property's public id.
    - `street_no` string, nullable — Street number of the address.
    - `street` string, nullable — Street name of the address.
    - `city` string, nullable — City of the address.
    - `city_id` string, nullable — Base64 city handle.
    - `zip_code` string, nullable — ZIP code of the address.
    - `zip_code_ext` string, nullable — ZIP+4 extension of the address.
    - `county` string, nullable — County of the address.
    - `county_id` string, nullable — Base64 county handle.
    - `state` string, nullable — State of the address.
    - `lat` number, nullable — Latitude of the address.
    - `long` number, nullable — Longitude of the address.
    - `permit_count` integer — Count of permits linked to the address.
    - `untagged_permit_count` integer — Count of the address's permits carrying no canonical tag.
    - `total_job_value` integer — Sum of permit job values in integer cents (dollars x 100).
    - `contractor_count` integer — Distinct contractors across the address's permits.
    - `tags` string[] — Distinct canonical tags present on the address's permits.
    - `tag_status_pairs` string[] — Distinct tag:status pairs (status folded to 'unknown' when NULL).
    - `statuses` string[] — Distinct permit statuses incl the 'unknown' NULL fold.
    - `tag_tally` object — Map tag -> permit count.
    - `last_date_by_tag` object — Map tag -> latest permit start_date.
    - `last_unfinaled_date_by_tag` object — Map tag -> latest non-final start_date under the clear rule.
    - `last_date_by_pair` object — Map tag:status -> latest permit start_date.
    - `last_date_by_status` object — Map status -> latest permit start_date.
    - `last_permit_date` string, date, nullable — Latest permit start_date across all of the address's permits; null when never permitted.
    - `apn` string, nullable — Assessor parcel number.
    - `property_type` string, nullable — Property type.
    - `property_type_detail` string, nullable — Property type detail.
    - `year_built` integer, nullable — Year the property was built.
    - `lot_size` integer, nullable — Lot size of the property.
    - `story_count` integer, nullable — Number of stories in the property.
    - `unit_count` integer, nullable — Number of units in the property.
    - `building_area` integer, nullable — Building area of the property.
    - `assess_market_value` integer, nullable — Assessed market value in integer cents (dollars x 100).
    - `owner_type` string, nullable — Type of property owner.
    - `legal_owner` string, nullable — Legal owner of the property.
    - `trust` PropertyTrust — Per-row absence-honesty surface for one property in an absence-class response. Present and non-null on every row of an absence or mixed-exclusion response, absent on presence-only responses (optional-by-polarity, wired at the route). Every field is required: a row whose (jurisdiction, tag) trust lookup misses carries the conservative-fallback instance rather than a null object.
      - `unresolved_rate` number, required — Share of the row jurisdiction's permits of the tag that never linked to an address.
      - `coverage_tier` 'high' | 'medium' | 'low', required — Coverage bucket for the row's jurisdiction (90/50 cutoffs).
      - `data_horizon` string, date, required — Most recent start_date past which 'no X since D' is under-observed; never null.
      - `horizon_basis` 'measured' | 'pooled' | 'prior', required — How data_horizon was estimated: a measured cohort, a pooled fallback, or the state prior.
      - `trust_jurisdiction_basis` 'own' | 'dominant' | 'unknown', required — Whether the trust join used the row's own jurisdiction, its ZIP's dominant one, or none.
      - `trust_jurisdiction_error_bar` number — Measured error rate of the trust jurisdiction: the 6.13% ZIP-dominant estimate error on a 'dominant' basis, 0 on an 'own' or 'unknown' basis.
      - `footprint_basis` 'matched' | 'unknown', required — Whether footprint suppression could resolve the row's geo scope.
      - `flags` string[] — Row-grain honesty flags, e.g. since_d_beyond_horizon or trust_row_missing.
  - `size` integer, required — The number of items returned in the response.
  - `next_cursor` string, nullable, required — The cursor for retrieving the next page of results.
  - `total_count` TotalCount — Capped result count with Elasticsearch-style {value, relation} shape. When the exact count is known and within the cap, relation is "eq" and value is that exact count. When the count exceeds the cap, relation is "gte" and value is the cap the count was probed against, meaning "the actual count is at least value". The cap is COUNT_CAP for every wire-facing endpoint; internal guard paths probe against their own cap, so value carries whatever cap produced it.
    - `value` integer, required — The count value; capped at the probe's cap (10,000 on the wire).
    - `relation` 'eq' | 'gte', required — "eq" means value is the exact count. "gte" means the actual count is at least value (the cap).
  - `trust_summary` TrustSummary — Response-level, row-weighted absence-honesty summary for an absence-class page.
    - `rows_flagged` integer, required — Number of rows on the page carrying a trust flag.
    - `row_weighted_unresolved_rate` number, required — Row-weighted mean unresolved_rate across the page.
    - `expected_miss_rate` number, required — Estimated share of true matches absent from arrived data due to ingestion lag.
    - `suppressed_scopes` integer, required — Number of footprint scopes excluded from the result by suppression.

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/shovels/apis/the-shovels-api-v2.md) · [All operations](https://skmtc.net/shovels/apis/the-shovels-api-v2/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/shovels/the-shovels-api-v2/revisions/d3f0e1f3afa8/schema)
