Property records API

Look up recorded owners, sales and mortgage history by address. API access is included with Pro, Team and Business.

Authentication

Create a key under API in your workspace and send it as a bearer token. Keys belong to a workspace and use the same monthly credits as the website.

Authorization: Bearer wh_live_your_key

Keep keys on your server. Reading results requires lookup:read; submitting lookups requires lookup:write. Revoke a key from your workspace at any time.

Look up addresses

POST/api/v1/batches

Send up to 1,000 addresses in a batch. Formatting and common abbreviations are normalized before matching. Include the city and state, or ZIP, whenever possible.

Request
curl https://whohouse.io/api/v1/batches \
  -H 'Authorization: Bearer wh_live_your_key' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: your-unique-batch-id' \
  -d '{"addresses":["104 Example St, Omaha, NE"]}'

The API returns 202 Accepted with a job ID and status. Reuse an Idempotency-Key when retrying the same request to avoid creating a second job. For one address, use POST /api/v1/lookup with {"address":"104 Example St, Omaha, NE"}.

Source responses are cached server-side for up to 24 hours. Job acceptance and result readiness are separate; cold lookups depend on the source. No fixed response-time SLA is offered.

Read results

GET/api/v1/batches/{id}

Poll with a short delay until the job’s status is completed. Results keep your input order, and each address has its own status.

Completed result · illustrative
{
  "job": {
    "id": "job_example",
    "status": "completed",
    "total": 1,
    "completed": 1,
    "matched": 1
  },
  "items": [
    {
      "index": 0,
      "input": "104 Example St, Omaha, NE",
      "status": "matched",
      "result": {
        "address": "104 Example St, Omaha, NE 68152",
        "owner": {
          "name": "WHITAKER, DEAN R; WHITAKER, MARISOL A",
          "displayNames": [
            "Dean R Whitaker",
            "Marisol A Whitaker"
          ],
          "relationship": "recorded_owner",
          "label": "Recorded owner",
          "source": "County property record"
        },
        "property": {
          "propertyType": "house",
          "yearBuilt": 1998
        },
        "source": {
          "name": "County property record",
          "updatedAt": null,
          "retrievedAt": "2026-10-06T12:00:00Z"
        }
      }
    }
  ],
  "pagination": {
    "limit": 100,
    "offset": 0,
    "total": 1
  }
}

owner.name is exactly as recorded. owner.displayNames lists the same people first-name-first for display, and a co-owner recorded without a surname shares the one beside it (SMITH JOHN & JANE becomes John Smith and Jane Smith). Sales and mortgages carry buyerNames, sellerNames, borrowerNames and lenderNames the same way. sales contains recorded buyers, sellers, prices and dates. mortgages contains dated source loan records, including borrowers, lenders, amounts, status, rates and balances when supplied. Missing fields are omitted, not guessed. A past sale may contain only a date; it does not establish a chain of title.

context is what OpenStreetMap maps around the address, when its location is known: atAddress (businesses and amenities with their hours, open-now status, phone, website, payment, accessibility and every mapped tag), building (type, floors, height, roof, year and footprint), street (class, speed limit, lanes, sidewalks), neighborhood, town, nearby (the nearest grocery, school, park, transit stop, pharmacy, hospital and more, with distances) and counts. It is © OpenStreetMap contributors under the Open Database License, kept separate from the owner record, and uses no credits. See the terms for reuse.

owner_unavailable means property facts were found without an owner name. not_found, ambiguous and invalid mean the address needs review. Only successful owner lookups use credits; repeated matches to the same property in a billing period don’t count again. Results are retained for 30 days, up to 500 completed jobs per workspace.

Exports

Download a CSV from GET /api/v1/batches/{id}/export.csv. The default properties table keeps complete histories in JSON columns. Use ?table=mortgages or ?table=sales for one row per record, joined by input_index. export.json returns the complete structured response. Add index=0 to export one input. Exports include every result and use no additional credits.

Errors and limits

StatusMeaning
400Check the address list and request format.
401The API key is missing or invalid.
402The workspace’s credits are used.
403Check workspace access, membership, key scopes and plan.
409An idempotency key was reused with a different request.
429A request limit was reached. Retry after the Retry-After header.
503A source is temporarily unavailable.

Use bounded concurrency and retry temporary failures with a delay. There are no automatic overage charges.

Compare plans

Sign in