---
title: "Search parcels"
method: POST
path: "/api/v1/search"
tags: ["Search"]
---

# Search parcels

`POST /api/v1/search`

## Request

- Base URL: `https://propraven.com`
- URL: `https://propraven.com/api/v1/search`
- Auth: HTTP bearer

Search parcels with optional geographic bounds and attribute filters. `bounds` and `filters` are both optional (`filters` defaults to `{}`); the body is validated and any bad member is a 400 naming it. `sort` applies to UNBOUNDED queries only: with `bounds`, rows come back in spatial-index order and the response says `sort_applied: false`. `total` is the exact number of matching parcels up to 10,000; beyond that it is 10,000 with `total_is_lower_bound: true`, and it is null if the count timed out (`total_status: "timed_out"`). Traffic-count columns are withheld until verified: they are returned as null with a `withhold_gate` block, and filters on them (minVpd, maxVpd, minVisibilityScore) are refused with 400 `filter_withheld`.

## Request body

- object
  - `bounds` object: Viewport in WGS84 degrees. north > south. west > east is an antimeridian-crossing box.
    - `north` number, required
    - `south` number, required
    - `east` number, required
    - `west` number, required
  - `filters` object: All optional; null means not set. Unknown members are a 400.
    - `zoningCategories` string[]: Zoning categories (Residential, Commercial, Industrial, Mixed-Use, Agricultural, …). Unrecognised labels are reported in `zoning_categories_unrecognized`.
    - `ownerTypes` string[]: Owner entity type (case-insensitive).
    - `propertyType` string[]: Property type group, e.g. Commercial, Residential.
    - `businessTypes` string[]: Business / use type, e.g. car_wash.
    - `absenteeOnly` boolean: Only parcels whose owner state differs from the parcel state.
    - `soldWithin` '6mo' | '1yr' | '3yr' | 'never'
    - `floodZone` string
    - `valueRange` object: Assessed value range.
      - `min` number, nullable
      - `max` number, nullable
    - `yearBuiltRange` object: Year built range.
      - `min` integer, nullable
      - `max` integer, nullable
    - `acreageRange` object: Lot size range in acres.
      - `min` number, nullable
      - `max` number, nullable
    - `minYearsOwned` number
    - `minCrimeScore` number
    - `maxCrimeScore` number
    - `crimeTrend` string
    - `minVpd` number: WITHHELD — refused with 400 filter_withheld until traffic counts are verified.
    - `maxVpd` number: WITHHELD — refused with 400 filter_withheld.
    - `minVisibilityScore` number: WITHHELD — refused with 400 filter_withheld.
  - `sort` 'assessed_value' | 'sale_price' | 'acreage' | 'year_built' | 'deal_score' | 'address' | 'city' | 'state' | 'owner_name' | 'total_assessed_value' | 'zoning' | 'lot_size_acres' | 'ownership_type': Sort field (unbounded queries only). The first five are the primary names; the rest are accepted column names. A legacy `{field, direction}` object is also accepted.
  - `order` 'asc' | 'desc'
  - `limit` integer: Page size. Values above 500 are clamped to 500 (the response echoes the effective limit).
  - `offset` integer

## Response `200`

Search results returned.

- object
  - `data` object[], required
    - `parcel_id` string, required
    - `state_fips` string, required
    - `county_fips` string, required
    - `address` string, nullable, required
    - `city` string, nullable, required
    - `state` string, nullable, required
    - `owner_name` string, nullable, required
    - `total_assessed_value` number, nullable, required
    - `zoning` string, nullable, required
    - `zoning_code_raw` string, nullable, required
    - `year_built` integer, nullable, required
    - `lot_size_acres` number, nullable, required
    - `ownership_type` string, nullable, required
    - `land_use_desc` string, nullable, required
    - `latitude` number, nullable, required
    - `longitude` number, nullable, required
    - `direct_vpd` number, nullable, required
    - `nearby_vpd` number, nullable, required
    - `vpd_visibility_score` number, nullable, required
    - `crime_score` number, nullable, required
    - `crime_tier` number, nullable, required
    - `crime_trend` string, nullable, required
    - `_guards` string[], required
  - `total` integer, required: Exact matching count up to 10,000; 10,000 when capped; null when the count timed out.
  - `total_is_estimate` boolean, required: True only when `total` is capped (a lower bound).
  - `total_is_lower_bound` boolean, required
  - `has_more` boolean, required
  - `limit` integer, required
  - `offset` integer, required
  - `sort_applied` boolean, required: False when `bounds` was given (sort is not applied to bounded queries) or no sort was requested.
  - `withhold_gate` object, required: Present when withheld columns (traffic counts) are in the rows; they are null.
    - `applied` boolean, required
    - `suppressed` string[], required
    - `reason` string, required
    - `reasons` object, required
      - `direct_vpd` string, required
      - `nearby_vpd` string, required
      - `vpd_visibility_score` string, required
    - `withheld_on` string, required
    - `note` string, required
  - `total_status` 'timed_out': Present when the count did not finish.
  - `zoning_categories_applied` string[]
  - `zoning_categories_unrecognized` string[]
  - `zoning_unknown_estimate` integer, nullable
  - `zoning_unknown_is_estimate` boolean
  - `zoning_filter_note` string

## Other responses

- `400`: A query or body parameter is invalid. Nothing was read or charged.
- `401`: Missing, malformed or invalid credential.
- `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.
- `504`: The query did not finish in time. Retry after `Retry-After` seconds or narrow the request.

---

[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)
