Docs

Look up a parcel

Match a parsed street address to its parcel, or learn why it can't be matched to exactly one.

POST https://api.fieldgeist.com/v1/verify/lookup

Matches a street address to a parcel and returns its Fieldgeist ID, county APN, county FIPS code and coordinates. When the address fits more than one parcel, or the building has unit parcels and no unit was given, the answer says so (ambiguous, unit_required) and lists candidates instead of picking one.

Send either the components of an address or a whole parse response.

Authentication

Authorization: Bearer <key>. See Authentication.

Request body

The body is a JSON object in one of two forms:

  • A parse response, unchanged: {"type": "street", "components": {...}, ...}. Only type and components are read.
  • Bare components: {"addressNumber": "400", "streetName": "BROAD", ...}, optionally with "type". Without type, the address is treated as a street address.
FieldTypeRequiredDescription
streetNamestringYesStreet name.
zip5stringOne of zip5 or city5-digit ZIP Code. The fastest and most precise way to locate the address.
citystringOne of zip5 or cityCity. With state, or alone when the city's name exists in only one state.
statestringNoTwo-letter state code. Needed with city when the city's name exists in more than one state.
addressNumberstringNoHouse number. Without it, the answer can only be a parcel with no house number (no_situs_parcel) or not_found.
addressNumberSuffixstringNoSuch as 1/2.
predirectional, postdirectionalstringNoStreet directions, such as W or NW.
streetSuffixstringNoStreet type, such as ST. Leave it out only if you don't know it: without it, every suffix at that house number is a candidate.
occupancyType, occupancyIdstringNoUnit designator and number. The unit number picks a unit parcel in a building that has them.
zip4stringNoAccepted, not used for matching.
typestringNoAddress type from a parse. Anything other than street is refused with 422 unsupported_type.

Values can be strings or numbers. Case and punctuation don't matter: values are normalized the same way the parcel index is.

Request example

curl https://api.fieldgeist.com/v1/verify/lookup \
  -H "Authorization: Bearer $FIELDGEIST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "addressNumber": "400",
    "streetName": "BROAD",
    "streetSuffix": "ST",
    "city": "SEATTLE",
    "state": "WA",
    "zip5": "98109"
  }'

Response

Parcel values on this page (IDs, APNs, coordinates) are illustrative.

200 OK: matched

{
  "status": "matched",
  "fieldgeist_id": "adr_01JA2Z3Y4X5W6V7T8S9R0QPNMA",
  "building_id": null,
  "apn": "198520-0495",
  "fips": "53033",
  "lat": 47.620494,
  "lon": -122.349235,
  "matchConfidence": 1,
  "candidates": [],
  "searched": ["matchkey/v3.2/zip5=98109/part.parquet"],
  "readPath": "chunk",
  "fuzzy": false
}
FieldTypeDescription
statusstringThe outcome. See Statuses.
fieldgeist_idstring | nullThe matched parcel's Fieldgeist ID (adr_…). null when there is no single parcel.
building_idstring | nullThe building's ID (bld_…) when the address has unit parcels. See Condos and units.
apnstring | nullThe county's assessor parcel number, as the county writes it.
fipsstring | null5-digit county FIPS code.
lat, lonnumber | nullCoordinates of the parcel.
matchConfidencenumber0 to 1. How closely the input matched the parcel. 0 when there's no single parcel (ambiguous, not_found); each candidate then has its own. See Match confidence.
unit_requiredbooleanPresent and true when the address has unit parcels and the input named no unit that exists.
unit_countnumberPresent with unit_required: how many unit parcels the address has.
candidatesobject[]Other parcels that fit, up to 10. Empty for a clean single match. See Candidates.
fuzzybooleantrue when the street name matched as a near miss (a typo or variant) rather than exactly. Confidence is lowered.
state_inferredstringPresent when you sent a city without a state or ZIP: the state the city was found in.
searchedstring[]Diagnostic: which parts of the index were read.
readPathstringDiagnostic: how the answer was found (chunk, fuzzy_chunk, whole, fuzzy, none).

Statuses

statusMeaningTop-level parcel fieldsWhat to do
matchedOne parcel fits.SetUse it. Check unit_required and fuzzy.
matched_buildingThe building matched, but not a unit parcel. Either the input named a unit that has no parcel of its own (the answer is the building's parcel), or the building has only unit parcels and the input named none of them (no top-level parcel; the units are the candidates).The building's parcel, or null with unit candidatesUse the building's parcel if that's enough. If unit_required is true, ask for the unit.
ambiguousTwo or more different parcels fit equally well, for example 3 SPRUCE when there's a 3 SPRUCE ST and a 3 SPRUCE CT.nullShow the candidates, or ask for the missing part (usually the suffix or a direction).
no_situs_parcelA weak match. The input had no house number, so the answer is a parcel on that street; or, in a single-ZIP search, the house number isn't on the street and the street has exactly one parcel with no house number on record.SetDon't treat it as a match without checking. matchConfidence is low.
not_foundNo parcel fits.nullCheck the input. Billed like any answer.

200 OK: ambiguous

{
  "status": "ambiguous",
  "fieldgeist_id": null,
  "building_id": null,
  "apn": null,
  "fips": null,
  "lat": null,
  "lon": null,
  "matchConfidence": 0,
  "candidates": [
    {
      "apn": "1234-0001",
      "fips": "53033",
      "lat": 47.611,
      "lon": -122.335,
      "zip5": "98101",
      "addressNumber": "3",
      "streetName": "SPRUCE",
      "streetSuffix": "CT",
      "occupancyId": null,
      "matchConfidence": 0.85,
      "fieldgeist_id": "adr_01JA2Z3Y4X5W6V7T8S9R0QPSP1",
      "building_id": null
    },
    {
      "apn": "1234-0002",
      "fips": "53033",
      "lat": 47.612,
      "lon": -122.336,
      "zip5": "98101",
      "addressNumber": "3",
      "streetName": "SPRUCE",
      "streetSuffix": "ST",
      "occupancyId": null,
      "matchConfidence": 0.85,
      "fieldgeist_id": "adr_01JA2Z3Y4X5W6V7T8S9R0QPSP2",
      "building_id": null
    }
  ],
  "searched": ["matchkey/v3.2/zip5=98101/part.parquet"],
  "readPath": "chunk",
  "fuzzy": false
}

The input was {"addressNumber": "3", "streetName": "SPRUCE", "zip5": "98101"}. With "streetSuffix": "CT" the same request returns matched.

200 OK: unit required

A condo building whose units are separate parcels, looked up without a unit:

{
  "status": "matched_building",
  "fieldgeist_id": null,
  "building_id": "bld_01JA2Z3Y4X5W6V7T8S9R0QPNMC",
  "apn": null,
  "fips": null,
  "lat": null,
  "lon": null,
  "matchConfidence": 0.8,
  "unit_required": true,
  "unit_count": 2,
  "candidates": [
    {
      "apn": "777-1",
      "fips": "53033",
      "lat": 47.61,
      "lon": -122.31,
      "zip5": "98109",
      "addressNumber": "600",
      "streetName": "PINE",
      "streetSuffix": "ST",
      "occupancyId": "1",
      "matchConfidence": 0.8,
      "fieldgeist_id": "adr_01JA2Z3Y4X5W6V7T8S9R0QPNMD",
      "building_id": "bld_01JA2Z3Y4X5W6V7T8S9R0QPNMC"
    },
    {
      "apn": "777-2",
      "fips": "53033",
      "lat": 47.61,
      "lon": -122.31,
      "zip5": "98109",
      "addressNumber": "600",
      "streetName": "PINE",
      "streetSuffix": "ST",
      "occupancyId": "2",
      "matchConfidence": 0.8,
      "fieldgeist_id": "adr_01JA2Z3Y4X5W6V7T8S9R0QPNME",
      "building_id": "bld_01JA2Z3Y4X5W6V7T8S9R0QPNMC"
    }
  ],
  "searched": ["matchkey/v3.2/zip5=98109/part.parquet"],
  "readPath": "chunk",
  "fuzzy": false
}

Sending "occupancyId": "2" returns matched with that unit's parcel (adr_…NME) and the same building_id. A building that has its own parcel and unit parcels returns matched with the building's parcel plus unit_required: true. See Condos and units.

unit_required can come with matched or matched_building. Check the flag, not the status.

Candidates

Each candidate is a parcel that fits the input:

FieldTypeDescription
fieldgeist_idstring | nullThe parcel's Fieldgeist ID.
building_idstring | nullIts building's ID, for unit parcels.
apn, fips, lat, lonAs at the top level.
zip5, addressNumber, streetName, streetSuffix, occupancyIdstring | nullThe parcel's address as the index records it, so you can tell candidates apart.
matchConfidencenumberHow closely the input matched this candidate.
fuzzybooleanPresent and true when this candidate's street name was a near miss.

Candidates are capped at 10 per answer; unit_count gives the full number of units.

City without a ZIP

Without zip5, the lookup searches the city. When the city's name exists in only one state, the state can be left out and the answer includes state_inferred:

{ "status": "matched", "fieldgeist_id": "adr_…", "state_inferred": "TX", "...": "..." }

When the name exists in several states, the request is refused:

{
  "error": "location_required",
  "message": "city is in 3 states: add a state or zip5",
  "states": 3
}

Errors

StatuserrorCause
400invalid_jsonThe body isn't valid JSON.
400components_requiredThe body isn't an object, or a component is not a string or number.
400street_requiredNo streetName.
400location_requiredNeither zip5 nor city, or a city that exists in more than one state without a state. The second case adds states.
422unsupported_typetype isn't street (PO boxes, rural routes and other types have no parcel). The response echoes type.
500internal_errorThe lookup failed on our side. Retry.
503matchkey_unavailableThe parcel index is unavailable. Retry later.
401, 402, 403, 429See Errors.
{
  "error": "unsupported_type",
  "type": "po_box",
  "message": "only type=street addresses can be matched to a parcel"
}

On this page