# Documentation
# Changelog
***
## August 4, 2026
### Fewer empty responses on person search
Three changes to how `GET /v2/person/` and `GET /v1/person/` narrow
results substantially reduce the number of searches that return no
results. None of them break the response shape or require callers to
update existing integrations.
**Automatic fuzzy-match fallback on zero results.** When an exact-name
search returns no results, the API now automatically retries the same
request with fuzzy matching enabled (phonetic variants, nicknames,
initials, typos) before returning. Exact-first precision is preserved
for searches that succeed on the first pass; only zero-result searches
trigger the fallback. The `include_fuzzy_matching` request parameter
continues to work as documented — setting it to `true` still forces
fuzzy matching on the first pass. Setting it to `false` (the default)
no longer disables fuzzy matching outright; it disables it only for
the first pass. See [Fuzzy Matching](/documentation/person-search/fuzzy-matching)
for details.
**New `strict_match` request parameter to opt out of the fallback.**
Callers whose use case treats "no results" as authoritative (for
example, verifying a name genuinely does not exist in the dataset) can
now set `strict_match=true` on the request to suppress the automatic
fuzzy fallback. A zero-result exact query is returned as-is, without
retrying. `strict_match=true` and `include_fuzzy_matching=true` are
semantically contradictory; setting both on the same request returns
HTTP 400.
**Age filter no longer excludes records without a known DOB.** When
`min_age` or `max_age` is set, records for which no date of birth is on
file are now **included** in results. The filter continues to exclude
records whose known DOB falls outside the requested range — the
behaviour change only affects records with a `null` `age` field. A
strong name-and-address match now returns even when the person's age is
unknown, where previously any age filter would drop that record. See
[Filter by Age Range](/documentation/person-search/filter-by-age-range).
***
## August 3, 2026
### `age` field on v2 person responses
Every record returned by `GET /v2/person/` and `GET /v2/person/{id}`
now includes an `age` field alongside `date_of_birth`:
```json
{
"id": "P19Xrg1Zr34",
"name": "Jane Smith",
"is_dead": false,
"age": 68,
"date_of_birth": "1957-12-22",
"...": "..."
}
```
`age` is computed from `date_of_birth` at response time. When only a
birth year is on file, `age` is a year-based approximation. When the
DOB is missing or unparseable, `age` is `null`. Existing `min_age` /
`max_age` request parameters filter by the same computed age; there
is no behavior change to those parameters.
This change is purely additive: no existing field on Person Search or
Person Details has changed type, nullability, or presence.
Response key order was also normalized on both endpoints so identity
fields and match signals appear before the larger array fields; rely
on key names, not position, when parsing.
***
## June 18, 2026
### `result_metadata` on v2 person search
Every record in a `GET /v2/person/` response now carries a top-level
`result_metadata` object summarizing each list and linking back to the
canonical Person Details URL:
```json
{
"results": [
{
"id": "P19Xrg1Zr34",
"name": "...",
"phones": [...],
"emails": [...],
"historic_addresses": [...],
"owned_properties": [...],
"result_metadata": {
"details_url": "/v2/person/P19Xrg1Zr34",
"phones": { "displayed": 3, "additional": 0 },
"emails": { "displayed": 1, "additional": 0 },
"historic_addresses": { "displayed": 4, "additional": 0 },
"owned_properties": { "displayed": 0, "additional": 0 }
}
}
],
"metadata": { ... }
}
```
`displayed` is the actual length of the list on this response;
`additional` is the count linked to the person but not included.
Today `additional` is always `0`. A future release will tune Person
Search to behave more like search: lean, ranked previews of each
list focused on the items most likely to help a caller pick a match
and decide whether to traverse for the full record. Payloads will be
smaller and results easier to scan. Person Details (`details_url`)
will always carry the full lists for callers who want everything;
`additional` is the forward-compatible signal for how many more
items live there. Safe to begin parsing now.
`details_url` is `null` for the rare result that arrives without a
canonical Whitepages person ID (e.g., an unresolved phone-owner
record); those records aren't part of the upcoming tuning.
This change is purely additive: no existing field on Person Search
responses has changed type, nullability, or presence.
***
## June 1, 2026
### Address ID support on property details
`GET /v2/property/{property_id}` now accepts either a Whitepages property ID
(`R` prefix) or an address ID (`A` prefix). Address IDs are resolved to the
associated property before lookup, so you can look up property details directly
from the address IDs found throughout other API responses.
Not every address ID has full property details, so lookups by address ID may
return `404`. These responses are not billed.
### Billability changes
Billing rules have been simplified:
* `400 Bad Request` responses are no longer billable on any endpoint.
* `404 Not Found` responses on `GET /v2/property/{property_id}` are no longer
billable, so you can optimistically look up property details by address ID.
`2xx` responses remain billable, as do `404` responses on all other endpoints.
See [Billing](/references/billing) for the full policy. These changes apply to
usage from June 1, 2026 onward — usage on or before May 31, 2026 is governed by
the [prior billing policy](/references/billing-prior-to-2026-06-01).
***
## April 22, 2026
### Pagination on v2 person search
The v2 person search endpoint now supports pagination. Use `page` (1–10, default 1)
and `page_size` (1–15, default 15) to page through results. Every response now
includes a `metadata` object:
```json
{
"results": [...],
"metadata": {
"result_count": 432,
"page": 1,
"page_size": 15
}
}
```
`result_count` reflects the total number of matching records for your query.
See the [pagination guide](/documentation/person-search/pagination) for details.
Going beyond your initial 15 results requires additional requests. Each page
after the first counts as another billable query against your plan. See
[Billing](/references/billing) for details.
***
## April 2, 2026
### Fuzzy name matching
Person search now accepts `include_fuzzy_matching=true` to broaden results with
phonetic, nickname, and misspelling matching. See the [fuzzy matching guide](/documentation/person-search/fuzzy-matching).
***
## March 26, 2026
### Email as a search parameter
Person search now accepts an `email` address alongside name, phone, and address.
***
## March 25, 2026
### Address field breakdown
Address objects in person responses now include discrete fields — `line1`, `city`,
`state`, and `zip` — in addition to the formatted address string.
***
## March 12, 2026
### v2 person search and detail endpoints
The v2 person search (`GET /v2/person/`) and detail (`GET /v2/person/{id}`)
endpoints are now available. v2 responses include enriched data:
* `current_addresses` and `historic_addresses` as separate lists
* `match_score` — a relevance and completeness score from 1–99
* `matched_by` — which input fields contributed to the match
* `emails` — email addresses with confidence scores
The v1 person endpoints (`GET /v1/person/` and `GET /v1/person/{id}`) are
deprecated. Whitepages will announce a removal date. Migrate to v2 for all new
integrations.
***
## February 20, 2026
### Webhooks for property deed events
Subscribe to real-time property deed events and receive HTTP POST notifications
when deeds record in your target jurisdictions.
* `POST /v1/webhooks` — create a subscription
* `GET /v1/webhooks` — list subscriptions
* `PUT /v1/webhooks/{id}` — update a subscription
* `DELETE /v1/webhooks/{id}` — remove a subscription
* `POST /v1/webhooks/{id}/test` — send a test delivery
See the [Webhook Quickstart](/documentation/webhooks/quickstart) for setup instructions.
***
## February 18, 2026
### Regions endpoint
`GET /v1/regions/states` and `GET /v1/regions/states/{state}/counties` return
the list of supported states and counties, including a `webhook_available` field
indicating which jurisdictions support deed event delivery.
***
## February 11, 2026
### Address confidence scores
Address objects in person responses now include a `score` field (0–100) indicating
confidence in the address association with the person.
***
## January 9, 2026
### Search by geographic radius
Person search now accepts a `radius` parameter (in miles) alongside an address
to restrict results to records within that distance. See the [search by radius guide](/documentation/person-search/search-by-radius).
***
## December 11, 2025
### Age range filter
Person search accepts `min_age` and `max_age` parameters (18–65) to filter
results to people within a specific age range.
***
## December 9, 2025
### Component name parameters
In addition to `name`, person search now accepts `first_name`, `middle_name`,
and `last_name` as discrete parameters. `name` and the component parameters
are mutually exclusive.
***
## November 21, 2025
### Historical locations
Person search accepts `include_historical_locations=true` to include past
addresses in address matching. By default, only current addresses are considered.
# FAQ
import { Callout } from "fumadocs-ui/components/callout";
## What do I do when my trial usage runs out?
When a trial key uses up its allowance, data calls return `Limit Exceeded` (not a `429`). The allowance does not refill — to keep going, [purchase a plan](/documentation/purchasing-api) or contact `api@whitepages.com`. Documentation calls keep working regardless; only data calls consume the allowance. See [Rate Limits](/references/rate-limits#monthly-query-limits--trial-exhaustion).
## How are rate limits applied?
There are two distinct limits:
* **`429 Too Many Requests`** — short-term throttling. Back off and retry with exponential backoff; it clears on its own. Rate limits vary by plan, and higher limits can be requested through [support](mailto:api@whitepages.com).
* **`Limit Exceeded`** — you have used up your monthly plan limit or trial allowance. It persists until your quota resets (next month for a plan) or you upgrade.
Neither a `429` nor a `5xx` is billed. See [Rate Limits](/references/rate-limits).
## What counts as a breaking change?
Removing or renaming an endpoint or field, changing a field's type, adding a required parameter, or changing auth or error formats. **Adding** a new optional parameter, a new field, a new endpoint, or a new enum value is **not** breaking — so always ignore unknown fields. Breaking changes ship only in a new API version with at least 30 days' notice. Full detail: [Breaking Changes Policy](/references/versioning/breaking-changes-policy).
## Is person search the same as phone lookup?
Yes. Reverse phone lookup, address lookup, and name search are all the same `GET /v2/person/` endpoint with different parameters — pass `phone=` for a reverse phone lookup. There is no separate phone endpoint. See the [Capability Map](/documentation/agentic-guidance/capability-map).
Not seeing your question? Use `search_documentation` over the MCP server, or
email `api@whitepages.com`.
# Getting Started
The Whitepages Pro API provides access to comprehensive person and property data. Whether you're verifying identities, enriching customer records, or researching properties, our API delivers the data you need.
## Get Your API Key
To access the API, you'll need an API key. Sign up for a **free trial** at [whitepages.com/pro-api](https://www.whitepages.com/pro-api).
Your API key authenticates all requests and tracks usage for billing. Never
expose it in client-side code or public repositories. If your key is
compromised, contact [api@whitepages.com](mailto:api@whitepages.com) for a
replacement.
Follow our [Making Your First
Request](/documentation/making-your-first-request) guide for step-by-step
instructions using Postman—no coding required.
## Available APIs
## Making Requests
All API requests require your API key in the `X-Api-Key` header:
```bash
curl 'https://api.whitepages.com/v2/person?name=John%20Smith' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Responses are returned in JSON format. Each successful request consumes one billable query — see [Billing](/references/billing) for the full policy on which responses are billed.
## Next Steps
Ready to make your first API call? Start with the [Person Search](/documentation/person-search) tutorial.
# Getting a Trial API Key
This guide walks you through the process of signing up for a free trial API key. The trial gives you access to all API endpoints so you can evaluate the service before committing to a paid plan.
## Step 1: Visit the API Page
Go to [whitepages.com/pro-api](https://www.whitepages.com/pro-api) to access the API signup page.
You'll see the "Get API Access" form on the right side of the page.
## Step 2: Enter Your Contact Information
The first form requires three pieces of information:
* **Full Name** - Your full name
* **Business Email Address** - A valid business email address (required for trial approval)
* **Phone Number** - Your phone number in the format (555) 555-5555
Fill in your details and click the **Start for Free** button.
Using a business email address (e.g., [yourname@company.com](mailto:yourname@company.com)) rather than a
personal email increases your chances of trial approval and faster processing.
## Step 3: Provide API Usage Details
After submitting your contact information, you'll be asked to provide more details about your API needs.
Fill out the following fields:
* **Anticipated Monthly API Calls** - Select your expected usage volume
* **Do you have a technical resource for implementation?** - Indicate if you have development resources
* **Who is the end user for the data?** - Select who will be using the data (Internal Staff, Businesses you serve, Consumers, or Other)
* **Briefly describe how you plan to use the API** - Provide a short description of your use case
Click **Access API Trial** to submit your request.
The trial signup does not require a credit card. You can evaluate the API
completely free during the trial period.
## Step 4: Check Your Email
After submitting the form, you'll see a confirmation message.
Check your email for instructions on how to activate your trial key.
## Step 5: Start Using Your API Key
Once you receive your API key, you can start making requests immediately. Include your key in the `X-Api-Key` header:
```bash
curl 'https://api.whitepages.com/v2/person?name=John%20Smith' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Never share your API key publicly or commit it to version control. If your key
is compromised, contact [api@whitepages.com](mailto:api@whitepages.com)
immediately.
## Trial Limitations
The trial API key includes:
* Access to all API endpoints
* 50 queries to evaluate the API
* Full response data (no field restrictions)
For production use or higher query volumes, visit the [API Pricing](https://www.whitepages.com/pro-api/pricing/plans) page.
## Next Steps
# Guides
In-depth guides for integrating and using the Whitepages Pro API.
Detailed guides are under development.
# Making Your First Request
Ready to test your API key? Pick the use case that matches what you're building and try it right here in your browser — or follow the step-by-step guide using Postman.
## Try It Now
Paste your API key once, then run a sample request for the use case you care about. Each section links to a deeper guide if you want to learn more.
## Using Postman (No Code Required)
Postman is a free tool that lets you interact with APIs without writing code. Click the button below to import our pre-configured collection, or follow the manual setup steps.
### What You'll Need
* Your Whitepages Pro API key (received via email after [signing up for a trial](/documentation/getting-trial-api-key))
* [Postman](https://www.postman.com/downloads/) (free download)
### Step-by-Step Guide
### Download and Open Postman
Download Postman from [postman.com/downloads](https://www.postman.com/downloads/) and install it. Create a free account or skip sign-in to continue.
### Create a New Request
1. Click the **+** button to open a new request tab
2. Make sure **GET** is selected in the dropdown (it's the default)
### Enter the API URL
Paste this URL into the request field:
```
https://api.whitepages.com/v2/person?name=John%20Smith&city=Seattle&state_code=WA
```
### Add Your API Key
1. Click the **Headers** tab below the URL field
2. In the **Key** column, enter: `X-Api-Key`
3. In the **Value** column, paste your API key
Make sure to use `X-Api-Key` exactly as shown, with capital X, A, and K.
### Send the Request
Click the **Send** button. You should see a JSON response in the panel below.
```json title="Example Response"
[
{
"id": "P1234567890",
"name": "John Smith",
"current_addresses": [
{
"address": "123 Main St, Seattle, WA 98101"
}
],
"phones": [
{
"number": "(206) 555-0198",
"type": "mobile"
}
]
}
]
```
If you see data like this, your API key is working correctly.
## Using cURL (Command Line)
If you prefer the command line, you can use cURL:
```bash
curl 'https://api.whitepages.com/v2/person?name=John%20Smith&city=Seattle&state_code=WA' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Replace `YOUR_API_KEY` with your actual API key.
## Troubleshooting
### 403 Forbidden or "Invalid API Key"
* Double-check that you copied the entire API key from your email
* Verify the header name is exactly `X-Api-Key` (case-sensitive)
* Make sure there are no extra spaces before or after your API key
### No Results Found
A 404 response with no results is normal—it means your API key is working, but no records matched your search. Try different search parameters.
### Need Help?
Contact [api@whitepages.com](mailto:api@whitepages.com) if you continue to have issues.
## Next Steps
Now that you've made your first request, explore what else you can do:
# Property Search
The Property Search API returns ownership and resident information for a given property. Use it to identify property owners, find current residents, or verify property details.
## Make Your First Request
### Send a Request
Search for property details by address:
```bash title="Request"
curl 'https://api.whitepages.com/v2/property/?street=STREET_ADDRESS&city=CITY&state_code=STATE_CODE' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Replace `YOUR_API_KEY` with your actual API key, and replace `STREET_ADDRESS`, `CITY`, and `STATE_CODE` with the address of the property you want to look up (URL-encode any spaces).
### Review the Response
A successful request returns property details with owner and resident information:
```json title="Response"
{
"result": {
"property_id": "RSAMPLE0001",
"apn": "197500-0015",
"property_address": {
"full_address": "123 Main Street, Seattle, WA 98101",
"line1": "123 Main Street",
"city": "Seattle",
"state": "WA",
"zip": "98101",
"house": "123",
"street": "Main",
"street_type": "Street",
"county": "King"
},
"mailing_address": {
"full_address": "PO Box 4242, Bellevue, WA 98009",
"line1": "PO Box 4242",
"city": "Bellevue",
"state": "WA",
"zip": "98009",
"house": "4242",
"street": "PO Box",
"street_type": null,
"county": "King"
},
"geolocation": {
"lat": 47.60621,
"lng": -122.33207
},
"ownership_info": {
"owner_type": "individual",
"business_owners": [
{ "name": "Acme Holdings LLC" },
{ "name": "Sample Trust" }
],
"person_owners": [
{
"id": "PSAMPLE0001",
"name": "John Smith",
"current_addresses": [
{
"address_id": "ASAMPLE0001",
"full_address": "123 Main Street, Seattle, WA 98101",
"line1": "123 Main Street",
"city": "Seattle",
"state": "WA",
"zip": "98101"
}
],
"phones": [
{ "number": "(206) 555-0142", "type": "Mobile" },
{ "number": "(425) 555-0188", "type": "Landline" }
],
"emails": [
{ "email": "john.smith@example.com" },
{ "email": "j.smith@example.org" }
]
},
{
"id": "PSAMPLE0011",
"name": "Jane Smith",
"current_addresses": [
{
"address_id": "ASAMPLE0001",
"full_address": "123 Main Street, Seattle, WA 98101",
"line1": "123 Main Street",
"city": "Seattle",
"state": "WA",
"zip": "98101"
}
],
"phones": [{ "number": "(206) 555-0143", "type": "Mobile" }],
"emails": [{ "email": "jane.smith@example.com" }]
}
]
},
"residents": [
{
"id": "PSAMPLE0001",
"name": "John Smith",
"current_addresses": [
{
"address_id": "ASAMPLE0001",
"full_address": "123 Main Street, Seattle, WA 98101",
"line1": "123 Main Street",
"city": "Seattle",
"state": "WA",
"zip": "98101"
}
],
"phones": [
{ "number": "(206) 555-0142", "type": "Mobile" },
{ "number": "(425) 555-0188", "type": "Landline" }
],
"emails": [
{ "email": "john.smith@example.com" },
{ "email": "j.smith@example.org" }
]
},
{
"id": "PSAMPLE0011",
"name": "Jane Smith",
"current_addresses": [
{
"address_id": "ASAMPLE0001",
"full_address": "123 Main Street, Seattle, WA 98101",
"line1": "123 Main Street",
"city": "Seattle",
"state": "WA",
"zip": "98101"
}
],
"phones": [{ "number": "(206) 555-0143", "type": "Mobile" }],
"emails": [{ "email": "jane.smith@example.com" }]
},
{
"id": "PSAMPLE0013",
"name": "Emily Smith",
"current_addresses": [
{
"address_id": "ASAMPLE0001",
"full_address": "123 Main Street, Seattle, WA 98101",
"line1": "123 Main Street",
"city": "Seattle",
"state": "WA",
"zip": "98101"
}
],
"phones": [{ "number": "(206) 555-0144", "type": "Mobile" }],
"emails": [{ "email": "emily.smith@example.com" }]
}
]
}
}
```
The response includes the verified property with geolocation, property owners, and current residents.
## Request Parameters
| Parameter | Required | Description | Example |
| ------------ | -------- | --------------------- | ----------------- |
| `street` | No\* | Street address | `123 Main Street` |
| `city` | No\* | City name | `Seattle` |
| `state_code` | No\* | Two-letter state code | `WA` |
| `zipcode` | No\* | ZIP code | `98101` |
At least one parameter is required. Include multiple parameters for more
precise results.
**Example with ZIP code:**
```
https://api.whitepages.com/v2/property/?street=123%20Main%20Street&zipcode=98101
```
**Example by property ID:**
```
https://api.whitepages.com/v2/property/RSAMPLE0001
```
## Property Details by ID
The property details endpoint accepts either a Whitepages property ID (`R` prefix) or an address ID (`A` prefix). Address IDs are resolved to the associated property before lookup, so you can pass the address IDs found throughout other API responses directly:
```
https://api.whitepages.com/v2/property/{property_id_or_address_id}
```
Not every address ID has full property details, so lookups by address ID may
return `404`. These responses are not billed — see
[Billing](/references/billing) — so you can optimistically look up property
details for any address ID you encounter.
## Address Standardization
Property addresses (both physical and mailing) are **not** processed through CASS certification. Property address data is sourced directly from county assessor and recorder records and is stored as-received without USPS standardization.
For person address standardization details, see [Search by
Address](/documentation/person-search/search-by-address#address-standardization-cass).
## What's Next
You've completed the getting started tutorials. Explore the [References](/references) section for complete API documentation.
# Purchasing the API
This guide walks you through the process of purchasing a paid Whitepages Pro API subscription. Paid plans offer higher query limits and are suitable for production use.
## Step 1: Visit the Pricing Page
Go to [whitepages.com/pro-api/pricing/plans](https://www.whitepages.com/pro-api/pricing/plans) to view paid plans.
The page shows three primary pricing cards along the top — **Starter**, **Growth**, and **Scale** — covering the most common monthly query volumes. Below them, an **Additional Plans** section lists higher standard tiers (**Advanced** and **Enterprise**) plus a **Higher-Volume Plans** row that routes to sales for custom pricing above the standard ceiling.
The 14-day trial isn't on `/plans`. See [Getting a Trial API
Key](/documentation/getting-trial-api-key) — you can evaluate the API with 50
free queries before purchasing.
## Step 2: Select Your Plan
### Monthly vs Annual Billing
Use the **Monthly / Annual** toggle at the top of the page to switch billing cadence. Annual plans are 15% cheaper than the equivalent monthly plan.
### Pick a Tier
Pick one of the three primary cards (Starter / Growth / Scale) and click **Get Pro Access**, or open the **Additional Plans** section below and click the price button next to a higher tier (Advanced / Enterprise) to proceed to checkout.
For volumes above the highest standard tier, pick **Higher-Volume Plans** in
the Additional Plans section and click **Contact Sales** — that opens a
[meeting
booker](https://outlook.office.com/bookwithme/user/b7040ad01ea34d8cb94e8db9809e7b12%40whitepages.com?anonymous\&ismsaljsauthenabled)
for our sales team. It's the same link as the Contact Sales button on the
[pricing page](https://www.whitepages.com/pro-api/pricing/plans).
## Step 3: Complete the Checkout Form
After clicking "Get Pro Access", you'll be taken to the secure checkout page.
### Account Details
Fill in the following information:
* **Email Address** - Your business email where the API key will be sent
* **Company Name** - Your company or organization name
If you already have a Whitepages consumer account, you must use a different
email address for your API account. You can either use a separate business
email or add `+api` to your existing email (e.g., `yourname+api@company.com`)
to create a new API account.
* **Company Address** - Your business address
* **Use Case** - Select how you plan to use the API:
* Contact Enrichment
* Identity Verification
* Reverse Phone Lookup
* Property & Owner Research
* Other
* **Phone** - Your contact phone number
Your account confirmation and billing receipts will be sent to this email
address. Make sure it's correct before submitting.
### Payment Information
Enter your payment details:
* **Cardholder Name** - Name as it appears on your card
* **Card Number** - Your credit card number (Visa, Mastercard, American Express, or Discover accepted)
* **Expiration Date** - Card expiration month and year
* **CVV** - The 3 or 4 digit security code on your card
* **Billing ZIP Code** - The ZIP code associated with your billing address
## Step 4: Review and Submit
Before submitting, review your order summary on the right side of the page:
* Verify the plan name and query volume
* Check the monthly price
* Note that sales tax may be added based on your location
Check the box to agree to the recurring charges, then click **Submit Order**.
You can cancel your subscription at any time by contacting Whitepages customer
support. There are no long-term contracts for monthly plans.
## Step 5: Copy Your API Key
After successful payment, your API key will be displayed on the confirmation screen.
Your API key is only shown once after purchase. Copy it immediately and store
it in a secure location such as a password manager or secrets vault. You will
not receive your API key via email.
## Using Your API Key
Include your API key in the `X-Api-Key` header with every request:
```bash
curl 'https://api.whitepages.com/v2/person?name=John%20Smith' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Never share your API key publicly or commit it to version control. If your key
is compromised, contact [api@whitepages.com](mailto:api@whitepages.com)
immediately.
## Managing Your Subscription
To manage your subscription, upgrade your plan, or view usage statistics:
1. Log in at [whitepages.com/auth/login](https://www.whitepages.com/auth/login)
2. Navigate to your account dashboard
3. View billing history and current usage
For billing questions or to cancel your subscription, contact customer support at (800) 916-7806 or visit [support.whitepages.com](https://support.whitepages.com/hc/en-us).
## Next Steps
# Regions
The Regions API provides access to the full list of US states and their associated counties. This data is used across the Whitepages platform for geographic filtering, webhook subscriptions, and event coverage lookups.
Use the interactive browser below to explore available regions, or jump to the API reference for programmatic access.
## Browse Regions
## API Reference
| Endpoint | Description |
| -------------------------------------------------- | -------------------------------------- |
| [List States](/references/regions/list_states) | Retrieve all US states and territories |
| [List Counties](/references/regions/list_counties) | Retrieve counties for a given state |
## Next Steps
# Authentication
import { Callout } from "fumadocs-ui/components/callout";
All API requests require a valid API key provided in the `X-Api-Key` header.
## API Key
Include your API key in every request using the `X-Api-Key` header:
```bash
curl -X GET "https://api.whitepages.com/v2/person/" \
-H "X-Api-Key: your-api-key-here"
```
Keep your API key secure. Do not expose it in client-side code or public
repositories.
## Obtaining an API Key
* **Trial key**: Provisioned through self-serve sign-up. Visit the [Getting a Trial API Key](/documentation/getting-trial-api-key) guide to get started.
* **Production key**: Requires purchasing an API product at [whitepages.com/pro-api/pricing/plans](https://www.whitepages.com/pro-api/pricing/plans).
## Error Responses
If authentication fails, you will receive a `403 Forbidden` response:
```json
{
"message": "Forbidden"
}
```
Common causes for authentication errors:
* Missing `X-Api-Key` header
* Invalid or revoked API key
* API key not authorized for the requested endpoint
# Billing Policy For Usage Prior to 2026-06-01
import { Callout } from "fumadocs-ui/components/callout";
This policy applies only to usage on or before May 31, 2026. For usage from
June 1, 2026 onward, see the current [Billing](/references/billing) policy.
API usage was tracked and billed based on successful requests.
## Billing Rules
| Response Type | Billable |
| ------------------ | -------- |
| 2xx (Success) | Yes |
| 4xx (Client Error) | Yes |
| 5xx (Server Error) | No |
| 429 (Rate Limit) | No |
Only requests to Person and Property endpoints were charged. Account endpoints
were not billable.
## Billable Requests
All `2xx` (success) and `4xx` (client error) responses from Person and Property endpoints were charged to your account.
## Non-Billable Requests
The following responses were **not** charged:
* `5xx` (server error) responses - issues on our end
* `429` (rate limit) responses - when you've exceeded rate limits
## Billing Period
Usage was calculated from the start of the month in UTC time. Billing cycles reset on the 1st of each month at 00:00 UTC.
## Support
For billing inquiries about usage during this period, please contact our team at [api@whitepages.com](mailto:api@whitepages.com).
# Billing
import { Callout } from "fumadocs-ui/components/callout";
API usage is tracked and billed based on successful requests.
The billing rules below apply to usage from June 1, 2026 onward. For usage on
or before May 31, 2026, see the [Billing Policy For Usage Prior to
2026-06-01](/references/billing-prior-to-2026-06-01).
## Billing Rules
| Response Type | Billable |
| ------------------ | -------------------------------------------- |
| 2xx (Success) | Yes |
| 404 (Not Found) | Yes, except `GET /v2/property/{property_id}` |
| 400 (Bad Request) | No |
| 403 (Forbidden) | No |
| 429 (Rate Limit) | No |
| 5xx (Server Error) | No |
All Person and Property endpoints are billable, across every API version (v1
and v2). Account, Regions, Events, and Webhooks endpoints are not billable.
## Billable Requests
The following responses from Person and Property endpoints, in any API version, are charged to your account:
* All `2xx` (success) responses
* `404` (not found) responses, except on `GET /v2/property/{property_id}`
## Non-Billable Requests
The following responses are **not** charged:
* `400` (bad request) responses - missing or invalid parameters
* `403` (forbidden) responses - even when an API key is provided
* `404` (not found) responses on `GET /v2/property/{property_id}`
* `429` (rate limit) responses - when you've exceeded rate limits
* `5xx` (server error) responses - issues on our end
### Property details lookups and 404s
`GET /v2/property/{property_id}` accepts either a Whitepages property ID (`R` prefix) or an address ID (`A` prefix). Not every address ID has full property details, so these lookups may return `404`. Because `404` responses on this endpoint are never billed, you can optimistically look up property details for the address IDs you encounter throughout other API responses.
## Billing Period
Usage is calculated from the start of the month in UTC time. Your billing cycle resets on the 1st of each month at 00:00 UTC.
## Usage Reports
Detailed usage reports are available through the [Account Usage](/references/account/get_account_usage_data) endpoint. You can query:
* Daily request counts
* Usage over custom date ranges (up to 90 days)
* Total requests for a time period
## Support
For billing inquiries, quota adjustments, or plan changes, please contact our team at [api@whitepages.com](mailto:api@whitepages.com).
# Routes
import { Cards, Card } from "fumadocs-ui/components/card";
The Whitepages Pro API provides comprehensive access to person and property data with enterprise-grade authentication and usage tracking.
Before using the API, review the [Authentication](/references/authentication), [Rate Limits](/references/rate-limits), and [Billing](/references/billing) documentation.
## Account API
Account management endpoints for retrieving usage statistics.
## Events API
## Person V2 API
## Property V2 API
## Regions API
## Webhooks API
Manage webhook subscriptions for near-live property event notifications. Register an HTTPS endpoint, choose an event type and geographic region, and receive POST notifications when matching events occur. Currently supports `deed.*` events in Texas counties.
# Rate Limits
import { Callout } from "fumadocs-ui/components/callout";
The API enforces two different kinds of limit, and both return `429`:
* **Rate limits** bound how *fast* requests arrive. They clear on their own.
* **Usage caps** bound how *much* you consume in a billing period. They persist until the period resets or you buy more queries.
Telling them apart matters, because retrying only helps for one of them.
## Which 429 did I get?
Three responses share the `429` status — one rate limit and two usage caps. Each is identified by a single field in the body:
| Identifying field | Kind | Meaning | What to do |
| -------------------------------- | ---------- | ----------------------------------- | ------------------------------ |
| `"message": "Too Many Requests"` | Rate limit | Too many requests per second | Back off and retry |
| `"message": "Limit Exceeded"` | Usage cap | Gateway quota for the period is out | Wait for the reset, or upgrade |
| `"error": "usage_cap_exceeded"` | Usage cap | Your plan's query allowance is out | Upgrade, or wait for the reset |
Only the third sets `error`, so branching on its presence is the reliable check. The first two carry `message` and nothing else; the third carries the full set of fields below.
## Rate limits
When you send requests too quickly, the API returns:
```json
{
"message": "Too Many Requests"
}
```
Wait before retrying, and implement exponential backoff in your application.
Rate limits vary by plan; higher limits can be requested through
[support](mailto:api@whitepages.com).
## Usage caps
Every plan includes a query allowance for its billing period, and trial keys include a fixed trial allowance. When you exhaust it, the API returns a `429` with a structured body:
```json
{
"error": "usage_cap_exceeded",
"error_instance_id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
"message": "Query cap reached for this billing cycle. To restore access before it resets, upgrade to a plan with more included queries: https://www.whitepages.com/billing/manage-plan/pro-api",
"limit": 1000,
"used": 1000,
"reset_at": "2026-09-01T00:00:00+00:00",
"upgrade_url": "https://www.whitepages.com/billing/manage-plan/pro-api"
}
```
| Field | Meaning |
| ------------- | ------------------------------------------------------------- |
| `limit` | Billable queries your allowance covers for the current period |
| `used` | Billable queries consumed so far in the period |
| `reset_at` | When the allowance resets |
| `upgrade_url` | Where to restore access without waiting for the reset |
`upgrade_url` differs by account type: paid subscribers are sent to their plan management page to move to a larger plan, and trials are sent to the pricing page to choose their first one.
Retrying will not clear a usage cap. Your allowance is spent until `reset_at`,
or until you move to a plan with more included queries.
### Response headers
`usage_cap_exceeded` responses carry the same numbers as headers, so you can react without parsing the body. The two gateway 429s do not set them:
| Header | Meaning |
| ------------------- | -------------------------------------- |
| `Retry-After` | Seconds until it is worth trying again |
| `X-RateLimit-Limit` | Same as `limit` |
| `X-RateLimit-Used` | Same as `used` |
| `X-RateLimit-Reset` | Same as `reset_at` |
`Retry-After` is a re-check interval, not the time until your allowance
returns. Access resumes once you have credit again — because the period reset,
because you upgraded, or because support granted extra queries — and
re-checking at that interval is how your key picks that up.
## Best Practices
* **Implement retry logic** with exponential backoff for rate-limit 429s
* **Branch on `error`** so your integration does not retry a usage cap in a loop
* **Cache responses** when appropriate to reduce API calls
* **Monitor usage** via the [Account Usage](/references/account/get_account_usage_data) endpoint
* **Batch requests** where possible to optimize your quota
## Rate Limit Increases
For rate limit increases or quota adjustments, please contact our team at [api@whitepages.com](mailto:api@whitepages.com).
# Support & Incident Response
import { Callout } from "fumadocs-ui/components/callout";
We are committed to keeping the Whitepages Pro API reliable and transparent. This page covers how to get help, what to expect during incidents, and how we handle changes to the API.
## Support Channels
For any questions, issues, or feature requests, reach out through the following channels:
| Channel | Contact | Use For |
| ------- | ----------------------------------------------- | -------------------------------------------------------------------------- |
| Email | [api@whitepages.com](mailto:api@whitepages.com) | General inquiries, account issues, billing questions, API integration help |
For urgent production issues, email [api@whitepages.com](mailto:api@whitepages.com) with the subject line
prefixed by **\[URGENT]** to ensure priority routing.
## Incident Response Times
We classify incidents by severity. The following are our typical response and resolution times based on current operational metrics. These are not formal SLAs.
Incidents are typically detected and responded to within **30 seconds**, with resolution within **15-30 minutes** depending on the nature of the issue.
Our automated monitoring systems detect incidents within seconds, enabling
rapid response across all severity levels.
### During an Incident
When an incident occurs, we follow this process:
1. **Detection** — Our automated monitoring systems detect anomalies and trigger alerts within seconds
2. **Acknowledgment** — The engineering team is immediately engaged
3. **Investigation** — The team identifies root cause and works toward resolution
4. **Resolution** — The issue is resolved and services are verified as operational
5. **Post-mortem** — For Critical and High severity incidents, an internal post-mortem is conducted to prevent recurrence
## Getting Help During an Outage
If you suspect an outage or are experiencing unexpected errors:
1. Email [api@whitepages.com](mailto:api@whitepages.com) with:
* Your API key identifier (first 8 characters only, never send the full key)
* The endpoint(s) affected
* Error responses you are receiving
* Approximate time the issue started
## Versioning & Breaking Changes
Our versioning approach, what we count as a breaking change, and how we announce changes now live in their own reference section:
* [Breaking Changes Policy](/references/versioning/breaking-changes-policy) — what counts as breaking, our commitments, and how the policy applies to REST endpoints and the MCP server
* [Change Notifications](/references/versioning/change-notifications) — notification types, lead times, and how to stay informed
# Capability Map
import { Callout } from "fumadocs-ui/components/callout";
Start here. This table maps what you are trying to do to the endpoint and parameters that do it. Match the intent, copy the parameters, then read the [type document](/references) for that endpoint before writing your types.
**Person search is one endpoint.** Reverse phone lookup, address lookup, and
name search are all the same `GET /v2/person/` call with different parameters.
There is no separate "phone lookup" endpoint — pass `phone=` to person search.
## People
| You want to… | Endpoint | Key parameters |
| ---------------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------- |
| Reverse phone lookup (who owns a number) | `GET /v2/person/` | `phone=` |
| Find who lives at an address | `GET /v2/person/` | `street`, `city`, `state_code`, `zipcode` |
| Find a person by name | `GET /v2/person/` | `name`, or `first_name` / `middle_name` / `last_name` (+ location) |
| Narrow a person search | `GET /v2/person/` | `min_age` / `max_age`, `include_fuzzy_matching`, `strict_match`, `include_historical_locations`, `radius` |
| Page through person results | `GET /v2/person/` | `page`, `page_size` |
| Get full detail for a known person | `GET /v2/person/{id}` | path `id` (the `id` from any person object) |
A person search returns results scored by `match_score` (1–99). See [Entity Shapes](/documentation/agentic-guidance/entity-shapes) for how a person's shape differs by context.
## Property
| You want to… | Endpoint | Key parameters |
| ------------------------------------ | ----------------------- | ----------------------------------------------------------------- |
| Find who owns a property | `GET /v2/property/` | `street`, `city`, `state_code`, `zipcode` → read `ownership_info` |
| Find current residents of a property | `GET /v2/property/` | same address params → read `residents` |
| Get property detail by id | `GET /v2/property/{id}` | path id (`R`-prefixed property id or `A`-prefixed address id) |
Owners and residents come back as **summary** person objects that carry an
`id`. To get full detail (date of birth, relatives, historic addresses), call
`GET /v2/person/{id}` with that `id` — see [Entity
Shapes](/documentation/agentic-guidance/entity-shapes).
## Events and account
| You want to… | Endpoint | Key parameters |
| ---------------------------------------- | ------------------------ | ------------------------------------------ |
| Find deed events / property transactions | `GET /v1/events/deed` | see [Events reference](/references/events) |
| Check usage / remaining quota | `GET /v1/account/usage/` | date range |
## What's next
* [Integration Guide](/documentation/agentic-guidance/integration-guide) — the workflow to follow before writing integration code.
* [Entity Shapes](/documentation/agentic-guidance/entity-shapes) — the shapes you get back and how to hydrate summaries.
* [FAQ](/documentation/faq) — trial limits, rate limits, and breaking changes.
# Entity Shapes by Context
import { Callout } from "fumadocs-ui/components/callout";
The same entity does not come back the same way everywhere. A person from one endpoint and a person from another are **different shapes** — and so are addresses. This page exists to make that one caveat unmistakable; for the exact fields, read the [type document](/references) for the endpoint you are calling.
**Do not assume one shape.** A type you build from one endpoint's response
will not fit another's. Always read the endpoint's type document for the shape
it actually returns.
## A person comes back in three kinds
* **Fetched by id** — `GET /v2/person/{id}` returns the full person record.
* **As a search result** — `GET /v2/person/` returns persons as scored, paginated results. Same entity, presented with relevance and list context.
* **Embedded in a property** — owners and residents inside a property response are a **reduced** form of a person, not the full record.
These are not interchangeable. The embedded form in particular carries far less than the full record.
**Reduced forms carry an `id`.** When you get a person embedded in a property
response and need the full record, hydrate it with `GET /v2/person/{id}`.
## Addresses also differ by context
An address is not one shape either: a person's address and a property's own address carry different fields. As with persons, do not reuse one address type across endpoints — check the type document for the endpoint you are calling.
# Integration Guide
import { Callout } from "fumadocs-ui/components/callout";
This is the prescribed workflow for integrating the API. Follow it in order; each step removes a mistake we have seen integrations make.
## The workflow
1. **Map the intent first.** Use the [Capability Map](/documentation/agentic-guidance/capability-map) to turn what you want ("reverse phone lookup", "who owns this property") into the endpoint and parameters. Do not guess at endpoints — person search is also phone search and address search.
2. **Read the type document before writing types.** Each endpoint has a [reference](/references) carrying its request and response schema. That schema is the authoritative source for the shapes you integrate against.
3. **Never infer types from sample responses.** Example payloads omit `null` and optional fields and show only one variant. A type built from an example will be wrong. Build types from the schema, not the sample.
4. **Ignore unknown fields.** Adding a new field to a response is [not a breaking change](/references/versioning/breaking-changes-policy). Parse the fields you need and tolerate fields you do not, so new fields never break you.
5. **Hydrate summaries by id.** Nested person objects (property owners, residents) are summaries that carry an `id`. Fetch full detail with `GET /v2/person/{id}`. See [Entity Shapes](/documentation/agentic-guidance/entity-shapes).
## What costs money
**Documentation is free; data costs money.** Reading these docs and the
capability map never bills your key. Data calls (person search, property
lookup, account usage) are billed identically whether made over REST or the
MCP server.
Billing follows the response status: successful (`2xx`) and client-error (`4xx`) responses are billed; throttling (`429`) and server errors (`5xx`) are not. A `404` on a property lookup by address id is **not** billed, so you can optimistically resolve any address id you encounter. See [Billing](/references/billing).
## Authentication
Pass your key in the `X-Api-Key` header on every data call. The key is a bearer secret: never log it, echo it back, or place it in a URL.
## Breaking changes, in one line
Breaking changes ship only in a new API version, with at least 30 days' notice; within a version, response shapes only grow. Read the full [Breaking Changes Policy](/references/versioning/breaking-changes-policy) before you depend on a shape.
## Gotchas
* **Person search is one endpoint** — phone, address, and name search are all `GET /v2/person/` with different parameters.
* **Addresses differ by context** — a person's addresses and a property's address are not the same shape. See [Entity Shapes](/documentation/agentic-guidance/entity-shapes).
* **Property addresses are not CASS-standardized** — they come from county assessor records as-received.
* **Trial keys exhaust** — when usage runs out you get `Limit Exceeded`, distinct from a `429`. See the [FAQ](/documentation/faq).
# Event Payload
When you retrieve an event using the [Events API](/documentation/events/get-event), the response is wrapped in a `result` envelope containing the full event object described below.
Webhook deliveries do **not** include the full event payload. Instead, your
endpoint receives a lightweight notification with the event type and a link to
fetch the complete details:
```json
{
"event_id": "evt_abc123",
"event_type": "deed.transfer",
"links": [
{
"version": "1",
"url": "https://api.whitepages.com/v1/events/evt_abc123"
}
]
}
```
Use the `url` in the `links` array to call the Events API and retrieve the
full event object shown below.
## Top-Level Fields
| Field | Type | Description |
| ------------ | ------ | ----------------------------------------------------------------------------- |
| `id` | string | Unique event identifier (UUID) |
| `object` | string | Always `"event"` |
| `event_type` | string | The type of deed event (see [Event Types](/documentation/events/event-types)) |
| `data` | object | Type-specific event data (see sections below) |
## Data
The `data` object contains all event-specific information: jurisdiction, property, parties, and deed detail.
| Field | Type | Required | Description |
| -------------- | ------ | -------- | --------------------------------------------------- |
| `jurisdiction` | object | Yes | Geographic jurisdiction where the deed was recorded |
| `property` | object | No | Property involved in the event |
| `parties` | array | Yes | Individuals or entities involved |
| `detail` | object | No | Deed-specific transaction detail |
## Jurisdiction
The `jurisdiction` object identifies the county and state where the deed was recorded.
| Field | Type | Required | Description |
| ----------- | ------ | -------- | --------------------------------------------- |
| `county` | string | No | County name |
| `state` | string | Yes | Two-letter state abbreviation |
| `fips_code` | string | No | Federal Information Processing Standards code |
```json title="Example"
{
"jurisdiction": {
"county": "King",
"state": "WA",
"fips_code": "53033"
}
}
```
## Property
The `property` object contains details about the property involved in the deed event. All fields are nullable.
| Field | Type | Description |
| ------------------- | ------- | ---------------------------------- |
| `property_id` | string | Whitepages property identifier |
| `property_address` | object | Structured address of the property |
| `apn` | string | Assessor's Parcel Number |
| `parcel_id` | string | Parcel identifier |
| `geolocation` | object | Geographic coordinates |
| `legal_description` | object | Legal description of the property |
| `bedrooms` | integer | Number of bedrooms |
| `bathrooms` | number | Number of bathrooms |
| `living_sqft` | integer | Living area in square feet |
| `lot_sqft` | integer | Lot size in square feet |
| `property_purpose` | string | Property type |
### Address Fields
| Field | Type | Description |
| -------- | ------ | --------------------- |
| `line1` | string | Street address |
| `city` | string | City name |
| `state` | string | Two-letter state code |
| `zip` | string | ZIP code |
| `county` | string | County name |
### Geolocation Fields
| Field | Type | Description |
| ----- | ------ | ----------- |
| `lat` | number | Latitude |
| `lng` | number | Longitude |
### Legal Description Fields
| Field | Type | Description |
| ------ | ------ | ---------------------------------- |
| `text` | string | Full legal description as raw text |
```json title="Example"
{
"property": {
"property_id": "prop_123",
"property_address": {
"line1": "123 Main St",
"city": "Seattle",
"state": "WA",
"zip": "98101",
"county": "King"
},
"apn": "123456-7890",
"parcel_id": "P-7890",
"geolocation": {
"lat": 47.6062,
"lng": -122.3321
},
"legal_description": {
"text": "LOT 1 BLK 2 SEATTLE LAND CO ADD"
},
"bedrooms": 3,
"bathrooms": 2.5,
"living_sqft": 1850,
"lot_sqft": 5000,
"property_purpose": "single_family"
}
}
```
## Parties
The `parties` array lists individuals or entities involved in the deed transaction.
| Field | Type | Required | Description |
| ----------- | ------ | -------- | ----------------------------------------------------- |
| `role` | string | Yes | Party's role: `grantor` (seller) or `grantee` (buyer) |
| `name` | string | No | Full name of the individual or entity |
| `type` | string | No | `individual` or `entity` |
| `person_id` | string | No | Whitepages person ID, if resolved |
| `addresses` | array | No | Associated addresses |
### Party Address Fields
| Field | Type | Required | Description |
| -------------- | ------ | -------- | ---------------------- |
| `full_address` | string | Yes | Formatted full address |
```json title="Example"
{
"parties": [
{
"role": "grantor",
"name": "Jane Doe",
"type": "individual",
"person_id": "per_456",
"addresses": [{ "full_address": "123 Main St, Seattle, WA 98101" }]
},
{
"role": "grantee",
"name": "Acme Properties LLC",
"type": "entity",
"person_id": null,
"addresses": []
}
]
}
```
## Detail
The `detail` object contains transaction-specific information from the deed record.
| Field | Type | Description |
| -------------------- | ------ | ------------------------------------- |
| `document_type` | object | Document classification |
| `recorded_date` | string | Date the deed was recorded (ISO 8601) |
| `instrument_date` | string | Date the deed was executed (ISO 8601) |
| `consideration` | number | Transaction amount in USD |
| `transaction_reason` | object | Transaction classification |
### Document Type Fields
| Field | Type | Description |
| ---------- | ------ | -------------------- |
| `category` | string | Normalized category |
| `text` | string | Human-readable label |
### Transaction Reason Fields
| Field | Type | Description |
| ---------- | ------ | -------------------- |
| `category` | string | Normalized category |
| `text` | string | Human-readable label |
```json title="Example"
{
"detail": {
"document_type": {
"category": "deed",
"text": "Warranty Deed"
},
"recorded_date": "2026-02-27",
"instrument_date": "2026-02-25",
"consideration": 750000,
"transaction_reason": {
"category": "sale",
"text": "Arms-length sale"
}
}
}
```
## Full Example
```json title="Complete event response"
{
"result": {
"id": "evt_abc123",
"object": "event",
"event_type": "deed.transfer",
"data": {
"jurisdiction": {
"county": "King",
"state": "WA",
"fips_code": "53033"
},
"property": {
"property_id": "prop_123",
"property_address": {
"line1": "123 Main St",
"city": "Seattle",
"state": "WA",
"zip": "98101",
"county": "King"
},
"apn": "123456-7890",
"parcel_id": "P-7890",
"geolocation": {
"lat": 47.6062,
"lng": -122.3321
},
"legal_description": {
"text": "LOT 1 BLK 2 SEATTLE LAND CO ADD"
},
"bedrooms": 3,
"bathrooms": 2.5,
"living_sqft": 1850,
"lot_sqft": 5000,
"property_purpose": "single_family"
},
"parties": [
{
"role": "grantor",
"name": "Jane Doe",
"type": "individual",
"person_id": "per_456",
"addresses": [{ "full_address": "123 Main St, Seattle, WA 98101" }]
},
{
"role": "grantee",
"name": "John Smith",
"type": "individual",
"person_id": null,
"addresses": []
}
],
"detail": {
"document_type": {
"category": "deed",
"text": "Warranty Deed"
},
"recorded_date": "2026-02-27",
"instrument_date": "2026-02-25",
"consideration": 750000,
"transaction_reason": {
"category": "sale",
"text": "Arms-length sale"
}
}
}
}
}
```
# Event Types
Every event has an `event_type` field that describes the kind of property deed activity it represents. Event types follow a `category.action` format.
## Available Event Types
| Event Type | Description |
| ---------- | ------------------------------------------------------------------- |
| `deed.*` | All property deed events, including transfers, recordings, and more |
`deed.*` is currently the only supported event type. Additional event types
will be added as coverage expands. Subscribe to `deed.*` in your webhook
subscriptions to automatically receive all current and future event types.
## Using Event Types
### In Webhook Subscriptions
When [creating a webhook](/documentation/webhooks/create-webhook), the `event_type` parameter controls which events are delivered to your endpoint:
```bash title="Subscribe to all deed events"
curl -X POST 'https://api.whitepages.com/v1/webhooks/' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://example.com/webhooks/deeds",
"event_type": "deed.*",
"region": "county:tx.dallas"
}'
```
### In Event Payloads
The `event_type` field appears in every event object, whether retrieved directly or delivered via webhook:
```json title="Event type in payload"
{
"id": "evt_abc123",
"object": "event",
"event_type": "deed.*",
...
}
```
## Distinguishing Test Events
Events generated by the [test webhook endpoint](/documentation/webhooks/test-webhook) include a `"test": true` field. Real events do not include this field. Use it to filter test events in your processing pipeline.
# Get an Event
Use the `GET /v1/events/{event_id}` endpoint to retrieve a single event by its ID. Webhook deliveries include a link to this endpoint so you can fetch the full event details after receiving a notification.
The Events API is currently available by invite only. To request access,
contact our support team at [api@whitepages.com](mailto:api@whitepages.com) or
visit the [Support and Incident
Response](/references/support-and-incident-response) page.
## Basic Usage
Retrieve an event by its ID:
```bash title="Request"
curl 'https://api.whitepages.com/v1/events/evt_abc123' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Path Parameters
| Parameter | Type | Required | Description |
| ---------- | ------ | -------- | ------------------------------------------------------- |
| `event_id` | string | Yes | The unique identifier of the event (e.g., `evt_abc123`) |
## Response
The response returns the full event object wrapped in a `result` envelope:
```json title="Response"
{
"result": {
"id": "evt_abc123",
"object": "event",
"event_type": "deed.transfer",
"data": {
"jurisdiction": {
"county": "King",
"state": "WA",
"fips_code": "53033"
},
"property": {
"property_id": "prop_123",
"property_address": {
"line1": "123 Main St",
"city": "Seattle",
"state": "WA",
"zip": "98101",
"county": "King"
},
"apn": "123456-7890",
"parcel_id": "P-7890",
"geolocation": {
"lat": 47.6062,
"lng": -122.3321
},
"legal_description": null,
"bedrooms": 3,
"bathrooms": 2.5,
"living_sqft": 1850,
"lot_sqft": 5000,
"property_purpose": "single_family"
},
"parties": [
{
"role": "grantor",
"name": "Jane Doe",
"type": "individual",
"person_id": "per_456",
"addresses": [{ "full_address": "123 Main St, Seattle, WA 98101" }]
},
{
"role": "grantee",
"name": "John Smith",
"type": "individual",
"person_id": null,
"addresses": []
}
],
"detail": {
"document_type": {
"category": "deed",
"text": "Warranty Deed"
},
"recorded_date": "2026-02-27",
"instrument_date": "2026-02-25",
"consideration": 750000,
"transaction_reason": {
"category": "sale",
"text": "Arms-length sale"
}
}
}
}
}
```
Webhook notifications include a `links` array with the URL to this endpoint.
After receiving a notification, call the linked URL to retrieve the full event
details.
For full request and response schemas, see the [Retrieve a single event by ID](/references/events/get_event) API reference.
# Events
Events represent property deed activities — transfers, recordings, and other deed transactions — captured from county recorder offices across the United States. Each event contains structured data about the property, the parties involved, and the transaction details.
When a deed event occurs, [webhook subscriptions](/documentation/webhooks) deliver a lightweight notification containing the event type and a link to fetch the full details. Use the Events API to retrieve the complete event data.
The Events API is currently available by invite only. To request access,
contact our support team at [api@whitepages.com](mailto:api@whitepages.com) or
visit the [Support and Incident
Response](/references/support-and-incident-response) page.
## Guides
# Search Deed Events
Use `GET /v1/events/deed` to search historical property deed events. Filter by region, date range, or a specific property identifier to retrieve the events you need.
The Events API is currently available by invite only. To request access,
contact our support team at [api@whitepages.com](mailto:api@whitepages.com) or
visit the [Support and Incident
Response](/references/support-and-incident-response) page.
Texas, New York, and Florida and their counties are supported. Use `state:tx`
or `county:tx.{county}` (e.g., `county:tx.travis`) for Texas, `state:ny` or
`county:ny.{county}` (e.g., `county:ny.new_york`) for New York, or `state:fl`
or `county:fl.{county}` (e.g., `county:fl.miami_dade`) for Florida. To find
valid region values, see the [Regions API](/references/regions).
## Basic Usage
### All deed events in a county
```bash title="Request"
curl 'https://api.whitepages.com/v1/events/deed?region=county:tx.travis&event_date_from=2026-01-01&event_date_to=2026-03-15' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Deed events for a specific property
```bash title="Request"
curl 'https://api.whitepages.com/v1/events/deed?region=county:tx.travis&property_id=Rl3V9Oa1Azv' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Query Parameters
| Parameter | Type | Required | Description |
| ----------------- | ------- | -------- | ----------------------------------------------------------------------------------------------- |
| `region` | string | Yes | Geographic scope in `type:value` format (e.g., `state:tx`, `county:tx.travis`, `county:48453`). |
| `property_id` | string | No | Whitepages property ID (e.g., `Rl3V9Oa1Azv`). Narrows results to a single property. |
| `event_date_from` | string | No | Start of event date range, inclusive (ISO 8601 date, e.g., `2026-01-01`). |
| `event_date_to` | string | No | End of event date range, inclusive (ISO 8601 date, e.g., `2026-03-15`). |
| `limit` | integer | No | Results per page. Default: 20, max: 100. |
| `cursor` | string | No | Pagination cursor from a previous response. See [Pagination](#pagination). |
Every request must include a `region` parameter. Requests without a region are
rejected with a `400` error. Each request accepts exactly one region — to
search multiple counties, make one request per county.
## Response
A successful response returns a `results` array and a `pagination` object:
```json title="Response"
{
"results": [
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"object": "event",
"event_type": "deed.*",
"data": {
"jurisdiction": {
"county": "Travis",
"state": "TX",
"fips_code": "48453"
},
"property": {
"property_id": "Rl3V9Oa1Azv",
"property_address": {
"line1": "456 Oak Ave",
"city": "Austin",
"state": "TX",
"zip": "78702",
"county": "Travis"
},
"apn": "02-1234-0567",
"parcel_id": null,
"geolocation": {
"lat": 30.2612,
"lng": -97.7195
},
"legal_description": {
"text": "LOT 12, BLOCK C, OAK HILL ESTATES, TRAVIS COUNTY, TX"
},
"bedrooms": 4,
"bathrooms": 3.0,
"living_sqft": 2850,
"lot_sqft": 9200,
"property_purpose": "Single Family Home"
},
"parties": [
{
"role": "grantor",
"name": "ABC Holdings LLC",
"type": "llc",
"person_id": null,
"addresses": [
{ "full_address": "100 Commerce St Ste 200 Austin, TX 78701" }
]
},
{
"role": "grantee",
"name": "Maria Garcia",
"type": "individual",
"person_id": "PABcd12345e",
"addresses": [{ "full_address": "456 Oak Ave Austin, TX 78702" }]
}
],
"detail": {
"document_type": {
"category": "deed",
"text": "Warranty Deed"
},
"recorded_date": "2026-03-16",
"instrument_date": "2026-03-14",
"consideration": 625000,
"transaction_reason": {
"category": "sale",
"text": "Sale"
}
}
}
}
],
"pagination": {
"next_cursor": "eyJyZWNvcmRlZF9kYXRlIjoiMjAyNi0wMy0xNSJ9"
}
}
```
Each result is a full event object. For field definitions, see the [Event Payload](/documentation/events/event-payload) reference.
## Pagination
When more results are available, the response includes a `next_cursor` in the `pagination` object. Pass it as the `cursor` parameter in your next request:
```bash title="Fetching the next page"
curl 'https://api.whitepages.com/v1/events/deed?region=county:tx.travis&cursor=eyJyZWNvcmRlZF9kYXRlIjoiMjAyNi0wMy0xNSJ9' \
--header 'X-Api-Key: YOUR_API_KEY'
```
When `next_cursor` is absent from the response, you have reached the last page.
## Errors
| Status | Code | Description |
| ------ | ------------------- | ----------------------------------------------------------------------- |
| `400` | `invalid_parameter` | Missing `region`, invalid parameter value, or bad date format |
| `400` | `unknown_region` | Region not found — response includes a `lookup_url` for the regions API |
| `401` | `unauthorized` | Missing or invalid `X-Api-Key` |
| `429` | `rate_limited` | Too many requests |
| `504` | `query_timeout` | Query exceeded the maximum execution time |
For full request and response schemas, see the [Search deed events](/references/events/search_deed_events) API reference.
# MCP Server
import { Callout } from "fumadocs-ui/components/callout";
import { Tab, Tabs } from "fumadocs-ui/components/tabs";
import { Step, Steps } from "fumadocs-ui/components/steps";
The Whitepages MCP (Model Context Protocol) server allows AI assistants like Claude Desktop, Cursor, and other MCP-compatible tools to directly access Whitepages Pro API functionality.
## Quick Start
### Get Your API Key
If you don't have an API key yet, [get a trial key](/documentation/getting-trial-api-key).
### Configure Your AI Tool
Choose your AI tool below and copy the configuration.
## Configuration
Claude Desktop does not support custom headers directly for remote MCP servers. Use `mcp-remote` as a bridge to handle authentication.
Add this to your Claude Desktop configuration file:
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
```json
{
"mcpServers": {
"whitepages": {
"command": "npx",
"args": [
"mcp-remote",
"https://api.whitepages.com/mcp",
"--header",
"X-Api-Key: ${WHITEPAGES_API_KEY}"
],
"env": {
"WHITEPAGES_API_KEY": "YOUR_API_KEY_HERE"
}
}
}
}
```
Replace `YOUR_API_KEY_HERE` with your actual Whitepages Pro API key.
After saving, restart Claude Desktop for the changes to take effect.
Claude Code connects to remote HTTP servers with custom headers
directly — no bridge needed. Add the MCP server using the CLI or edit
your configuration file directly.
**Using CLI:**
```bash
claude mcp add --transport http whitepages https://api.whitepages.com/mcp \
--header "X-Api-Key: YOUR_API_KEY_HERE" --scope user
```
**Or edit** `~/.claude.json` **(macOS/Linux) or** `%USERPROFILE%\.claude.json` **(Windows):**
```json
{
"mcpServers": {
"whitepages": {
"type": "http",
"url": "https://api.whitepages.com/mcp",
"headers": {
"X-Api-Key": "YOUR_API_KEY_HERE"
}
}
}
}
```
Replace `YOUR_API_KEY_HERE` with your actual Whitepages Pro API key.
After running `claude mcp add`, reconnect with `/mcp` in an open
session. A full restart is only needed if you edited `~/.claude.json`
by hand.
Add the server with a single `codex mcp add` command. It uses
`mcp-remote` as a stdio bridge to send the `X-Api-Key` header:
```bash
codex mcp add whitepages -- npx -y mcp-remote https://api.whitepages.com/mcp \
--header "X-Api-Key: YOUR_API_KEY_HERE"
```
**Or edit** `~/.codex/config.toml` directly to connect to the remote
server natively, without the `mcp-remote` bridge:
```toml
[mcp_servers.whitepages]
url = "https://api.whitepages.com/mcp"
http_headers = { "X-Api-Key" = "YOUR_API_KEY_HERE" }
```
Replace `YOUR_API_KEY_HERE` with your actual Whitepages API key.
In the `codex` TUI, run `/mcp` to confirm the server is connected.
Gemini CLI connects to remote Streamable HTTP servers with custom
headers. Add the server with the CLI or edit your `settings.json`
directly.
**Using CLI:**
```bash
gemini mcp add whitepages https://api.whitepages.com/mcp \
--transport http --header "X-Api-Key: YOUR_API_KEY_HERE"
```
**Or edit** `~/.gemini/settings.json`**:**
```json
{
"mcpServers": {
"whitepages": {
"httpUrl": "https://api.whitepages.com/mcp",
"headers": {
"X-Api-Key": "YOUR_API_KEY_HERE"
}
}
}
}
```
Replace `YOUR_API_KEY_HERE` with your actual Whitepages API key.
Run `/mcp` inside Gemini CLI to confirm the server is connected.
Cursor supports remote HTTP servers with custom headers directly. Add
this to your Cursor MCP settings file:
**macOS/Linux**: `~/.cursor/mcp.json`
**Windows**: `%USERPROFILE%\.cursor\mcp.json`
```json
{
"mcpServers": {
"whitepages": {
"url": "https://api.whitepages.com/mcp",
"headers": {
"X-Api-Key": "YOUR_API_KEY_HERE"
}
}
}
}
```
Restart Cursor after updating the configuration.
Cline supports custom headers directly for remote MCP servers.
In VS Code with Cline extension:
1. Click the MCP Servers icon in the Cline panel
2. Select the Configure tab
3. Click "Edit MCP Settings" to open `cline_mcp_settings.json`
4. Add this configuration:
```json
{
"mcpServers": {
"whitepages": {
"url": "https://api.whitepages.com/mcp",
"headers": {
"X-Api-Key": "YOUR_API_KEY_HERE"
}
}
}
}
```
OpenCode supports custom headers directly for remote MCP servers.
Add this to your `opencode.json` configuration:
```json
{
"mcp": {
"whitepages": {
"type": "remote",
"url": "https://api.whitepages.com/mcp",
"headers": {
"X-Api-Key": "YOUR_API_KEY_HERE"
},
"enabled": true
}
}
}
```
Zed currently focuses on stdio-based MCP servers. Use `mcp-remote` to connect to remote servers.
Add this to your Zed settings (`~/.config/zed/settings.json` or via Zed → Settings):
```json
{
"context_servers": {
"whitepages": {
"command": {
"path": "npx",
"args": [
"mcp-remote",
"https://api.whitepages.com/mcp",
"--header",
"X-Api-Key: YOUR_API_KEY_HERE"
]
}
}
}
}
```
Zed's remote MCP support is still evolving. Check the [Zed MCP
documentation](https://zed.dev/docs/ai/mcp) for the latest configuration
format.
While Postman doesn't directly support MCP, you can test the underlying API:
1. Create a new request
2. Set method to `POST`
3. Set URL to `https://api.whitepages.com/mcp`
4. Add headers:
* `Content-Type`: `application/json`
* `Accept`: `text/event-stream`
* `X-Api-Key`: `YOUR_API_KEY_HERE`
5. Set body (raw JSON):
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "postman-test",
"version": "1.0.0"
}
}
}
```
Note: Postman may have limitations with Server-Sent Events (SSE) responses.
For full MCP testing, use the MCP Inspector instead.
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is the official tool for testing MCP servers:
1. Install and run:
```bash
npx @modelcontextprotocol/inspector https://api.whitepages.com/mcp
```
2. In the Inspector UI:
* Transport Type: **SSE**
* URL: `https://api.whitepages.com/mcp`
* Click **Authentication** button
* Add header: `X-Api-Key` = `YOUR_API_KEY_HERE`
* Click **Connect**
3. Once connected, you can explore available tools and test them interactively.
## Authentication
All requests to the Whitepages MCP server require authentication via the `X-Api-Key` header:
```
X-Api-Key: YOUR_API_KEY_HERE
```
If you don't have an API key:
* [Get a trial key](/documentation/getting-trial-api-key) for testing
* [Purchase a plan](/documentation/purchasing-api) for production use
## What's Available
Connecting to the MCP server gives your AI assistant two things: **tools** that call the Whitepages Pro API, and the **full corpus of documentation**.
### Data tools
These tools make live, metered calls to the Whitepages Pro API:
* **Person search** — look up people by name, phone, or address
* **Person by ID** — retrieve full detail for a specific person
* **Property search** — look up properties by address
* **Property by ID** — retrieve full detail for a specific property
* **Account usage** — report your API usage over a date range
Each tool bills identically to the equivalent REST endpoint — see [Billing](/references/billing).
### Documentation
The complete Whitepages Pro API documentation is available directly through the MCP server, in two forms that expose the same content:
* **MCP resources** — for assistants that support resources, every document is addressable as a resource that can be browsed and attached directly.
* **Documentation tools** — for assistants that don't support resources, the same corpus is reachable through the `list_documentation`, `search_documentation`, and `get_documentation` tools.
Because both forms serve the identical corpus, no assistant is left without the documentation.
Some MCP clients don't currently support MCP resources — including the
Anthropic products **Claude Code**, **Claude Desktop**, and **Co-Work**. This
is a limitation of those harnesses' MCP support, not of the Whitepages MCP
server or its resources. On these clients, the documentation tools
(`list_documentation`, `search_documentation`, `get_documentation`) provide
the same complete corpus.
The exact tool names and their parameters are shown in your AI assistant after connecting.
## Usage in AI Assistants
After configuring the MCP server, you can ask your AI assistant to use Whitepages data:
**Example prompts:**
* "Find contact information for John Smith in Seattle"
* "Look up who owns the phone number 206-555-0100"
* "Get details about the property at 123 Main St, Seattle, WA"
Your AI assistant will automatically use the appropriate Whitepages MCP tools to fulfill these requests.
## Billing
MCP requests are billed identically to direct API calls. Each tool invocation through the MCP server consumes credits from your subscription plan at the same rate as if you called the REST API directly.
For example:
* A person search via MCP = same cost as a person search via REST API
* A reverse phone lookup via MCP = same cost as a reverse phone lookup via REST API
See [Billing](/references/billing) for detailed pricing information.
## Troubleshooting
**Connection Failed**: Verify your API key is correct and has active credits.
**Rate Limits**: MCP requests count against your [API rate
limits](/references/rate-limits). Monitor your usage in the dashboard.
If you encounter issues:
1. Check that your API key is valid and has credits
2. Verify the server URL is correct: `https://api.whitepages.com/mcp`
3. Ensure the `X-Api-Key` header is properly configured
4. Restart your AI tool after configuration changes
# Confidence Scores
Person search responses include confidence scores on three levels: the person record itself, each phone number, and each email address. All scores range from **0 to 100** and represent relative confidence — a higher score means stronger evidence of association.
## Score Types
### Person Match Score
The top-level `match_score` on a person record indicates how well that record matches your search query. Higher scores reflect stronger matches across name, location, and other query parameters. A companion `matched_by` array names which of your query inputs contributed to the match.
```json
{
"id": "P1234567890",
"name": "John Smith",
"match_score": 94,
"matched_by": ["first_name", "last_name", "address"],
...
}
```
Use `match_score` to rank or filter results when multiple people match your query, and `matched_by` to understand which inputs were most decisive.
### Phone Score
Each phone number includes a `score` indicating confidence that the number is actively associated with this person.
```json
"phones": [
{ "number": "(212) 555-0198", "type": "mobile", "score": 95 },
{ "number": "(212) 555-0199", "type": "landline", "score": 41 }
]
```
A higher score means the number is more likely to be current and correctly attributed. A low score may indicate the number is outdated or only loosely associated.
### Email Score
Each email address includes a `score` indicating confidence that the address belongs to this person.
```json
"emails": [
{ "email": "john.smith@example.com", "score": 88 },
{ "email": "jsmith85@gmail.com", "score": 52 }
]
```
## Interpreting Scores
Scores are **relative**, not absolute thresholds. There is no fixed cutoff for "good" vs "bad" — the right threshold depends on your use case:
| Use case | Suggested approach |
| -------------------------------- | ------------------------------------------- |
| High-confidence verification | Filter to scores above 80 |
| Lead enrichment | Use all scores, sort by highest first |
| Showing multiple contact options | Display all, surface high-score items first |
Scores reflect the strength of association in Whitepages data. A low score
does not necessarily mean the information is wrong — it may reflect limited
data coverage for that individual.
# Filter by Age Range
Use the `min_age` and `max_age` parameters to filter person search results by age range. This is useful when you need to find individuals within a specific age bracket.
## Basic Usage
Add `min_age` and/or `max_age` to your request to filter results:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?name=John%20Smith&min_age=25&max_age=45' \
--header 'X-Api-Key: YOUR_API_KEY'
```
This returns only records for individuals between 25 and 45 years old.
## Parameters
| Parameter | Type | Description |
| --------- | ------- | -------------------------------------- |
| `min_age` | integer | Minimum age (inclusive). Must be 18-65 |
| `max_age` | integer | Maximum age (inclusive). Must be 18-65 |
Age filters are restricted to individuals between 18 and 65 years old. Values
outside this range will return an error.
## Examples
### Filter by Minimum Age
Filter for individuals 21 years or older:
```bash
curl 'https://api.whitepages.com/v2/person?name=Jane%20Doe&city=Chicago&state_code=IL&min_age=21' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Filter by Maximum Age
Filter for individuals 40 or younger:
```bash
curl 'https://api.whitepages.com/v2/person?last_name=Johnson&state_code=FL&max_age=40' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Filter by Age Range
Filter for individuals between 25 and 55:
```bash
curl 'https://api.whitepages.com/v2/person?name=Michael%20Williams&zipcode=90210&min_age=25&max_age=55' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Combining with Other Filters
Age filters work alongside all other person search parameters:
```bash
curl 'https://api.whitepages.com/v2/person?first_name=Sarah&last_name=Miller&city=Seattle&state_code=WA&min_age=30&max_age=50' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Records for which no date of birth is on file are **included** in results when
`min_age` or `max_age` is set. The filter only excludes records whose known
DOB falls outside the requested range — so a strong name-and-address match
returns even when the person's age is unknown. The `age` field on such a
record is `null`.
## Response
The response format remains the same as a standard person search. Age filters only affect which records are returned, not the structure of the response.
```json title="Response"
[
{
"id": "P1234567890",
"name": "John Smith",
"aliases": ["Johnny Smith"],
"is_dead": false,
"age": 33,
"date_of_birth": "1992-07-22",
"linkedin_url": "https://linkedin.com/in/jsmith",
"company_name": "Tech Solutions Inc",
"job_title": "Product Manager",
"match_score": 87,
"matched_by": ["first_name", "last_name"],
"phones": [{ "number": "(312) 555-0123", "type": "mobile", "score": 88 }],
"current_addresses": [
{ "id": "A9876543210", "address": "456 Oak Ave, Chicago, IL 60601" }
],
"historic_addresses": [
{ "id": "A1234567890", "address": "789 Pine St, Chicago, IL 60602" }
],
"owned_properties": [],
"emails": [{ "email": "jsmith@example.com", "score": 88 }],
"relatives": [{ "id": "P0987654321", "name": "Mary Smith" }],
"result_metadata": {
"details_url": "/v2/person/P1234567890",
"phones": { "displayed": 1, "additional": 0 },
"emails": { "displayed": 1, "additional": 0 },
"historic_addresses": { "displayed": 1, "additional": 0 },
"owned_properties": { "displayed": 0, "additional": 0 }
}
}
]
```
The `age` field on each result is derived from `date_of_birth` and reflects
the person's current age. The `min_age` / `max_age` request parameters filter
the search index by the same computed age. When only a birth year is on file,
`age` is a year-based approximation.
# Fuzzy Matching
Person search matches names in two modes: **exact match** and **fuzzy match**. Fuzzy match broadens name matching to phonetic variants, common nicknames, initials, and typos. By default the API runs an exact match first and only falls back to fuzzy match if the exact pass returns no results — you get the precision of exact match when it works and the recall of fuzzy match when it doesn't. Set `include_fuzzy_matching=true` to skip the exact pass and start with fuzzy match directly.
## Basic Usage
You do not need to set anything to benefit from fuzzy matching. If your exact-name search returns no results, the API automatically retries with fuzzy matching:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?name=Tomas%20O%27Brien&city=New%20York&state_code=NY' \
--header 'X-Api-Key: YOUR_API_KEY'
```
If no record exactly matches `Tomas O'Brien`, the API automatically retries the search as a fuzzy match, which can find records for `Thomas O'Brien`, `Tom O'Brien`, `Tomas OBrien`, and similar variants — all in a single request.
To force fuzzy matching on the first pass (skip the exact pass), set `include_fuzzy_matching=true`:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?name=John%20Doe&city=New%20York&state_code=NY&include_fuzzy_matching=true' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Parameters
| Parameter | Type | Default | Description |
| ------------------------ | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `include_fuzzy_matching` | boolean | `false` | When `true`, the search starts with fuzzy matching instead of exact matching. When `false` (the default), the search runs exact first and falls back to fuzzy only when exact returns no results. |
| `strict_match` | boolean | `false` | When `true`, the search does not fall back to fuzzy matching on a zero-result response; the exact query is authoritative. Cannot be combined with `include_fuzzy_matching=true`. |
## How It Works
Fuzzy matching expands name matching to include:
* **Phonetic variations** — names that sound similar (e.g., "Tomas" matching "Thomas")
* **Nicknames** — common name variants (e.g., "Bob" matching "Robert")
* **Initials** — first or middle initial matching against full names
* **Common misspellings** — small character transpositions or omissions
Exact name matches are still ranked higher than fuzzy matches, so precise results appear first in the response.
Fuzzy matches typically receive lower [confidence
scores](/documentation/person-search/confidence-scores) than exact matches. An
exact name match scores higher than a phonetic or nickname match for the same
record.
Most callers do not need to set `include_fuzzy_matching`. The default behavior
(exact first, fuzzy fallback on zero results) gives you the precision of exact
matching without the empty responses on typos and nicknames. Set
`include_fuzzy_matching=true` only when you know the input is likely to be a
nickname or variant and you want the exact pass skipped — for example, when
the caller is a CRM export of informal names.
## Opting Out — `strict_match=true`
If your use case treats an empty result as authoritative — for example,
verifying a name genuinely does not exist in the dataset — set
`strict_match=true` on the request. The API will not fall back to fuzzy
matching or radius expansion on a zero-result response; the exact query
runs and its result is returned as-is.
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?name=John%20Doe&city=New%20York&state_code=NY&strict_match=true' \
--header 'X-Api-Key: YOUR_API_KEY'
```
`strict_match=true` and `include_fuzzy_matching=true` are semantically
contradictory — one asks the API not to broaden at all, the other asks it to
start with the broadest name matching. Setting both on the same request
returns HTTP 400 with a message pointing at the conflict. Set at most one.
`strict_match` controls fuzzy/radius fallback only. It does not change how
`min_age` / `max_age` handles records whose date of birth is unknown (those
records continue to be included), and it does not change how
`include_historical_locations` interprets past addresses.
When the exact pass returns no results and the API falls back to fuzzy
matching, the response includes the extra matching work in a single round
trip. Requests that require the fuzzy fallback may respond slightly slower
than requests that succeed on the exact pass.
## Response
The response format is the same regardless of which match mode produced the results. Fuzzy matching only affects which records are returned and their confidence scores, not the structure of the response.
# Person Search
The Person Search API finds matching records in the Whitepages dataset based on name, location, phone number, or address. Use it to verify identities, find contact information, or enrich customer data.
## Make Your First Request
### Send a Request
Search for a person by name and location:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?name=John%20Smith&city=New%20York&state_code=NY' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Replace `YOUR_API_KEY` with your actual API key.
### Review the Response
A successful request returns matching person records:
```json title="Response"
[
{
"id": "P1234567890",
"name": "John Smith",
"aliases": ["Johnny Smith", "J. Smith"],
"is_dead": false,
"age": 40,
"date_of_birth": "1985-03-15",
"linkedin_url": "https://linkedin.com/in/johnsmith",
"company_name": "Acme Corp",
"job_title": "Software Engineer",
"match_score": 94,
"matched_by": ["name", "address"],
"phones": [{ "number": "(212) 555-0198", "type": "mobile", "score": 92 }],
"current_addresses": [
{
"address_id": "A9876543210",
"full_address": "123 Main St, New York, NY 10001",
"line1": "123 Main St",
"city": "New York",
"state": "NY",
"zip": "10001"
}
],
"historic_addresses": [
{
"address_id": "A1234567890",
"full_address": "456 Oak Ave, Brooklyn, NY 11201",
"line1": "456 Oak Ave",
"city": "Brooklyn",
"state": "NY",
"zip": "11201"
}
],
"owned_properties": [
{ "id": "R5432109876", "address": "123 Main St, New York, NY 10001" }
],
"emails": [{ "email": "john.smith@example.com", "score": 88 }],
"relatives": [{ "id": "P0987654321", "name": "Jane Smith" }],
"result_metadata": {
"details_url": "/v2/person/P1234567890",
"phones": { "displayed": 1, "additional": 3 },
"emails": { "displayed": 1, "additional": 0 },
"historic_addresses": { "displayed": 1, "additional": 5 },
"owned_properties": { "displayed": 1, "additional": 0 }
}
}
]
```
Each record includes identifiers, contact and employment fields, match signals, address and phone lists, and a `result_metadata` block summarizing each list and linking to the full Person Details record.
`result_metadata.{list}.displayed` is the count of items in the list on this
response; `additional` is the count of items linked to the person that were
not included because the list is capped (phones: 4, emails: 3, historic
addresses: 5, owned properties: 5). The full lists are always available via
`details_url` at `/v2/person/{id}`.
Person records, phone numbers, and email addresses each include a **score**
(0–100) indicating confidence of association. See [Confidence
Scores](/documentation/person-search/confidence-scores) for details.
## Request Parameters
Combine any of these parameters to refine your search:
| Parameter | Description | Example |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `name` | Full or partial name | `John Smith` |
| `first_name` | First name | `John` |
| `middle_name` | Middle name | `Robert` |
| `last_name` | Last name | `Smith` |
| `phone` | Phone number | `2125550198` |
| `street` | Street address | `123 Main St` |
| `city` | City name | `New York` |
| `state_code` | Two-letter state code | `NY` |
| `zipcode` | ZIP code | `10001` |
| `min_age` | Minimum age filter (18-65) | `25` |
| `max_age` | Maximum age filter (18-65) | `55` |
| `include_historical_locations` | Include historical addresses in search (default: `false`) | `true` |
| `include_fuzzy_matching` | Force fuzzy name matching on the first pass. When `false` (default) the API runs exact match first and falls back to fuzzy automatically if the exact pass returns no results. See [Fuzzy Matching](/documentation/person-search/fuzzy-matching). | `true` |
| `strict_match` | Suppress automatic fuzzy fallback (default: `false`). When `true`, a zero-result exact query is returned as-is instead of retrying with fuzzy matching. Cannot be combined with `include_fuzzy_matching=true`. | `true` |
The API uses **AND logic**, meaning all parameters must match. For example,
`first_name=John` will return records named John.
`first_name=John&last_name=Smith` will only return those same records that
also have the last name Smith.
**Example with multiple parameters:**
```
https://api.whitepages.com/v2/person?name=John%20Smith&zipcode=10001
```
## Response Codes
| Status | Description | Billable |
| ----------------------- | ----------------------------- | -------- |
| `200 OK` | Request successful | Yes |
| `400 Bad Request` | Missing or invalid parameters | No |
| `403 Forbidden` | Invalid API key | No |
| `404 Not Found` | No matching record (by id) | Yes |
| `429 Too Many Requests` | Rate limit exceeded | No |
| `5xx` | Server error | No |
**Note**: A `200 OK` status means the request was processed successfully, but
it doesn't guarantee results were found. Check the response body to see if any
records were returned.
## Next Steps
Learn how to look up property ownership and resident data in the [Property Search](/documentation/property-search) tutorial.
# Pagination
Person search returns up to 15 results per request by default. Use the `page` and `page_size` parameters to retrieve additional results when a query matches more records than a single page can return.
## Basic Usage
Add `page=2` to retrieve the second page of results for the same query:
```bash title="Page 1 (default)"
curl 'https://api.whitepages.com/v2/person/?name=John%20Smith&state_code=WA' \
--header 'X-Api-Key: YOUR_API_KEY'
```
```bash title="Page 2"
curl 'https://api.whitepages.com/v2/person/?name=John%20Smith&state_code=WA&page=2' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Keep all other query parameters the same across pages to retrieve consistent, ordered results.
## Parameters
| Parameter | Type | Default | Range | Description |
| ----------- | ------- | ------- | ----- | -------------------------- |
| `page` | integer | `1` | 1–10 | Page number (1-indexed) |
| `page_size` | integer | `15` | 1–15 | Number of results per page |
## Response
Each response includes a `metadata` object alongside the results:
```json
{
"results": [...],
"metadata": {
"result_count": 432,
"page": 2,
"page_size": 15
}
}
```
| Field | Description |
| -------------- | ------------------------------------------ |
| `result_count` | Total number of records matching the query |
| `page` | The current page number |
| `page_size` | The number of results per page |
Use `result_count` to determine whether additional pages are available. If `result_count` is greater than `page × page_size`, there are more results on the next page.
## Iterating Through Pages
```bash title="Iterate through all pages"
PAGE=1
while true; do
RESPONSE=$(curl -s \
"https://api.whitepages.com/v2/person/?name=John%20Smith&state_code=WA&page=$PAGE" \
--header 'X-Api-Key: YOUR_API_KEY')
RESULT_COUNT=$(echo "$RESPONSE" | jq '.metadata.result_count')
PAGE_SIZE=$(echo "$RESPONSE" | jq '.metadata.page_size')
RESULTS=$(echo "$RESPONSE" | jq '.results | length')
echo "Page $PAGE: $RESULTS results"
if [ "$((PAGE * PAGE_SIZE))" -ge "$RESULT_COUNT" ]; then
break
fi
PAGE=$((PAGE + 1))
done
```
Pagination works best with specific queries. If `result_count` is very high,
adding filters such as `state_code`, `city`, or `min_age`/`max_age` will
narrow results to the most relevant matches before paginating.
Every page request consumes an additional usage credit. Fetching pages 1
through 5 counts as five billable requests against your plan. See
[Billing](/references/billing) for details.
Results are accessible up to page 10. If your query returns more than 150
records, refine your search parameters to narrow the results.
# Search for Person by Partial Name
When you only have partial name information, use the individual name parameters (`first_name`, `middle_name`, `last_name`) to search more precisely than using the combined `name` parameter.
## When to Use Partial Name Search
Use individual name parameters when:
* You only know a person's first or last name
* You need to search across variations of a name
* You want more control over which parts of a name to match
## Search by Last Name Only
Find all people with a specific last name in a location:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?last_name=Smith&city=Seattle&state_code=WA' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Search by First and Last Name
When you know both first and last name but want to match regardless of middle name:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?first_name=John&last_name=Smith&state_code=NY' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Include Middle Name for Precision
For more precise matching when you have complete name information:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?first_name=John&middle_name=Robert&last_name=Smith&zipcode=10001' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Combining with Location Parameters
For best results, always include at least one location parameter:
| Combination | Use Case |
| -------------------------------------- | --------------------------- |
| `last_name` + `state_code` | Broad search within a state |
| `last_name` + `city` + `state_code` | City-level search |
| `first_name` + `last_name` + `zipcode` | Precise local search |
## Name Parameter vs Individual Parameters
| Parameter | Behavior |
| -------------------------- | ------------------------------------------------------ |
| `name` | Matches against the full name field, flexible ordering |
| `first_name` + `last_name` | Matches each field specifically, more precise |
Use `name` for convenience when you have a full name string. Use individual parameters when you need precise control or only have partial information.
# Reverse Phone Lookup
Use the `phone` parameter to perform a reverse phone lookup and identify who owns a phone number. This returns person records associated with the phone number, including their name, address, and other contact information.
## Basic Usage
Look up a phone number:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?phone=2065550198' \
--header 'X-Api-Key: YOUR_API_KEY'
```
This returns person records associated with the phone number.
## Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------------------- |
| `phone` | string | Phone number to look up |
## Examples
### Basic Phone Lookup
Find who owns a phone number:
```bash
curl 'https://api.whitepages.com/v2/person?phone=2125550198' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Combine with Name for Verification
Verify that a phone number belongs to a specific person:
```bash
curl 'https://api.whitepages.com/v2/person?phone=2125550198&name=John%20Smith' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Combine with Location
Narrow results by adding location filters:
```bash
curl 'https://api.whitepages.com/v2/person?phone=2125550198&state_code=NY' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Reverse phone lookup is useful for verifying caller identity, confirming
contact information accuracy, and enriching customer records with additional
details.
## Response
The response includes the phone owner's information along with all associated contact details:
```json title="Response"
[
{
"id": "P1234567890",
"name": "John Smith",
"aliases": ["Johnny Smith"],
"is_dead": false,
"age": 40,
"date_of_birth": "1985-03-15",
"linkedin_url": "https://linkedin.com/in/johnsmith",
"company_name": "Acme Corp",
"job_title": "Software Engineer",
"match_score": 95,
"matched_by": ["phone"],
"phones": [
{ "number": "(212) 555-0198", "type": "mobile", "score": 95 },
{ "number": "(212) 555-0199", "type": "landline", "score": 72 }
],
"current_addresses": [
{ "id": "A9876543210", "address": "123 Main St, New York, NY 10001" }
],
"historic_addresses": [
{ "id": "A1234567890", "address": "456 Oak Ave, Brooklyn, NY 11201" }
],
"owned_properties": [],
"emails": [{ "email": "john.smith@example.com", "score": 88 }],
"relatives": [{ "id": "P0987654321", "name": "Jane Smith" }],
"result_metadata": {
"details_url": "/v2/person/P1234567890",
"phones": { "displayed": 2, "additional": 0 },
"emails": { "displayed": 1, "additional": 0 },
"historic_addresses": { "displayed": 1, "additional": 0 },
"owned_properties": { "displayed": 0, "additional": 0 }
}
}
]
```
Because the search input was a phone number, the matching phone is pinned to
position 0 of the `phones` list even when it ranks below other phones by
confidence score. This guarantees the phone the caller queried on always
appears above the cap.
In rare cases, a phone number may be associated with multiple people. When
this occurs, the response includes all matching records sorted by relevance.
# Search by Address
Use address parameters to find people associated with a specific location. By default, searches match only current addresses. Enable `include_historical_locations` to also search historical addresses.
## Basic Usage
Search for people at a specific address:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?street=123%20Main%20St&city=Seattle&state_code=WA' \
--header 'X-Api-Key: YOUR_API_KEY'
```
This returns people whose **current address** matches the search criteria.
## Include Historical Addresses
To search both current and historical addresses, set `include_historical_locations=true`:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?street=123%20Main%20St&city=Seattle&state_code=WA&include_historical_locations=true' \
--header 'X-Api-Key: YOUR_API_KEY'
```
This returns people who currently live at the address **or** have previously lived there.
## Parameters
| Parameter | Type | Default | Description |
| ------------------------------ | ------- | ------- | -------------------------------------- |
| `street` | string | — | Street address |
| `city` | string | — | City name |
| `state_code` | string | — | Two-letter state code |
| `zipcode` | string | — | ZIP code |
| `include_historical_locations` | boolean | `false` | Include historical addresses in search |
## Examples
### Search by ZIP Code Only
Find people in a specific ZIP code:
```bash
curl 'https://api.whitepages.com/v2/person?zipcode=98101' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Search by City and State
Find people in a specific city:
```bash
curl 'https://api.whitepages.com/v2/person?city=Portland&state_code=OR' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Find Previous Residents
Find anyone who has ever lived at an address:
```bash
curl 'https://api.whitepages.com/v2/person?street=456%20Oak%20Ave&city=Denver&state_code=CO&zipcode=80202&include_historical_locations=true' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Combine with Name Search
Find a specific person at an address:
```bash
curl 'https://api.whitepages.com/v2/person?name=John%20Smith&street=789%20Pine%20St&city=Austin&state_code=TX&include_historical_locations=true' \
--header 'X-Api-Key: YOUR_API_KEY'
```
Historical address data varies by record. Some individuals may have extensive
address history while others may only have current address information
available.
## Response
The response includes both current and historical addresses for each person found:
```json title="Response"
[
{
"id": "P1234567890",
"name": "John Smith",
"aliases": ["Johnny Smith"],
"is_dead": false,
"age": 40,
"date_of_birth": "1985-03-15",
"linkedin_url": "https://linkedin.com/in/johnsmith",
"company_name": "Acme Corp",
"job_title": "Software Engineer",
"match_score": 92,
"matched_by": ["address"],
"phones": [{ "number": "(206) 555-0198", "type": "mobile", "score": 92 }],
"current_addresses": [
{ "id": "A9876543210", "address": "123 Main St, Seattle, WA 98101" }
],
"historic_addresses": [
{ "id": "A1234567890", "address": "456 Oak Ave, Portland, OR 97201" },
{ "id": "A2345678901", "address": "789 Pine St, San Francisco, CA 94102" }
],
"owned_properties": [
{ "id": "R5432109876", "address": "123 Main St, Seattle, WA 98101" }
],
"emails": [{ "email": "john.smith@example.com", "score": 88 }],
"relatives": [{ "id": "P0987654321", "name": "Jane Smith" }],
"result_metadata": {
"details_url": "/v2/person/P1234567890",
"phones": { "displayed": 1, "additional": 0 },
"emails": { "displayed": 1, "additional": 0 },
"historic_addresses": { "displayed": 2, "additional": 0 },
"owned_properties": { "displayed": 1, "additional": 0 }
}
}
]
```
When `include_historical_locations=true`, the search matches against both
`current_addresses` and `historic_addresses`. The response always includes
both fields regardless of the search setting.
## Address Standardization (CASS)
Person addresses in the Whitepages dataset are processed through **CASS certification** (Coding Accuracy Support System), the USPS address standardization program. All addresses are run through SmartyStreets to normalize formatting and assign a validity status before being stored.
This means:
* Addresses are in a **consistent format** regardless of how they were originally recorded
* Every address has a **validity status** indicating how well it was verified
### Validity Status
| Status | Description |
| ------------------- | ------------------------------------------------------------ |
| `valid` | Address fully verified and deliverable |
| `missing_secondary` | Valid street address but missing a unit or apartment number |
| `invalid_secondary` | Unit or apartment number provided but does not match records |
| `invalid_primary` | Street number could not be confirmed |
| `invalid` | Address could not be verified |
Addresses with a non-`valid` status are still included in results. For
example, `missing_secondary` addresses are real, occupied locations that
simply lack a unit identifier in the data — they are not excluded.
# Search by Radius
Use the `radius` parameter to find people within a specific distance of a location. This enables proximity-based searches, such as finding all people within 10 miles of a given address or city.
## Basic Usage
Search for people within a radius of a location:
```bash title="Request"
curl 'https://api.whitepages.com/v2/person?city=Seattle&state_code=WA&radius=10' \
--header 'X-Api-Key: YOUR_API_KEY'
```
This returns people whose **current address** is within 10 miles of Seattle, WA.
## How It Works
When you provide a `radius` parameter along with location information, the API:
1. **Geocodes the location** - Converts your address, city, or ZIP code into geographic coordinates (latitude/longitude)
2. **Searches by distance** - Finds people whose addresses fall within the specified radius
3. **Returns results** - Ordered by relevance and distance
The API automatically geocodes your location. If geocoding fails (e.g.,
invalid address), the search gracefully falls back to standard address
matching without distance filtering.
## Parameters
| Parameter | Type | Default | Description |
| ------------------------------ | ------- | ------- | --------------------------------------------- |
| `radius` | number | — | Search radius in miles (maximum: 100) |
| `street` | string | — | Street address for center point |
| `city` | string | — | City name for center point |
| `state_code` | string | — | Two-letter state code for center point |
| `zipcode` | string | — | ZIP code for center point |
| `include_historical_locations` | boolean | `false` | Include historical addresses in radius search |
The maximum allowed radius is **100 miles**. Requests with larger values will
be rejected.
## Examples
### Search by City with Radius
Find people within 5 miles of downtown Portland:
```bash
curl 'https://api.whitepages.com/v2/person?city=Portland&state_code=OR&radius=5' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Search by ZIP Code with Radius
Find people within 1 miles of a specific ZIP code:
```bash
curl 'https://api.whitepages.com/v2/person?zipcode=98101&radius=1' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Search by Full Address with Radius
Find people within 0.1 miles of a specific street address:
```bash
curl 'https://api.whitepages.com/v2/person?street=123%20Main%20St&city=Seattle&state_code=WA&zipcode=98101&radius=0.1' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Include Historical Addresses
Find people who currently live or have previously lived within 10 miles of a location:
```bash
curl 'https://api.whitepages.com/v2/person?city=Austin&state_code=TX&radius=10&include_historical_locations=true' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Combine with Name Search
Find a specific person within a radius:
```bash
curl 'https://api.whitepages.com/v2/person?name=John%20Smith&city=Denver&state_code=CO&radius=25' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Location Specification
You can specify the center point for radius searches in several ways:
### Street Address (Most Precise)
Provide a full street address for the most accurate center point:
```bash
curl 'https://api.whitepages.com/v2/person?street=456%20Oak%20Ave&city=Boston&state_code=MA&radius=5' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### City and State
Use city and state for a broader center point (typically the city center):
```bash
curl 'https://api.whitepages.com/v2/person?city=San%20Francisco&state_code=CA&radius=20' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### ZIP Code
Use a ZIP code as the center point:
```bash
curl 'https://api.whitepages.com/v2/person?zipcode=10001&radius=3' \
--header 'X-Api-Key: YOUR_API_KEY'
```
* **Street addresses** provide the most precise center point - **ZIP codes**
use the geographic center of the ZIP code area - **City/State** combinations
use the city center coordinates For best results, provide as much location
detail as possible.
## Response
The response format is identical to standard person searches, including all address, phone, and demographic information:
```json title="Response"
[
{
"id": "P1234567890",
"name": "John Smith",
"aliases": ["Johnny Smith"],
"is_dead": false,
"age": 40,
"date_of_birth": "1985-03-15",
"linkedin_url": "https://linkedin.com/in/johnsmith",
"company_name": "Acme Corp",
"job_title": "Software Engineer",
"match_score": 88,
"matched_by": ["address"],
"phones": [{ "number": "(206) 555-0198", "type": "mobile", "score": 92 }],
"current_addresses": [
{ "id": "A9876543210", "address": "789 Pine St, Seattle, WA 98102" }
],
"historic_addresses": [
{ "id": "A1234567890", "address": "456 Oak Ave, Seattle, WA 98101" }
],
"owned_properties": [
{ "id": "R5432109876", "address": "789 Pine St, Seattle, WA 98102" }
],
"emails": [{ "email": "john.smith@example.com", "score": 88 }],
"relatives": [{ "id": "P0987654321", "name": "Jane Smith" }],
"result_metadata": {
"details_url": "/v2/person/P1234567890",
"phones": { "displayed": 1, "additional": 0 },
"emails": { "displayed": 1, "additional": 0 },
"historic_addresses": { "displayed": 1, "additional": 0 },
"owned_properties": { "displayed": 1, "additional": 0 }
}
}
]
```
The response does not include the calculated distance from the center point.
Results are ordered by relevance score, which factors in distance along with
other matching criteria.
## Error Handling
### Graceful Degradation
If the location cannot be geocoded (e.g., invalid address or service unavailable), the API automatically falls back to standard address matching without distance filtering:
```bash
# If geocoding fails, this behaves like a standard city/state search
curl 'https://api.whitepages.com/v2/person?city=InvalidCity&state_code=XX&radius=10' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Radius Too Large
Requests with radius values exceeding 100 miles will return a validation error:
```json title="Error Response"
{
"error": {
"code": 400,
"message": "Bad Request",
"long_message": "Request validation failed. Validation failed for field 'query -> radius'. Please check the provided data.",
"meta": null
},
"wp_trace_id": "10860e0010134c52833b9a3cdbdacfd3"
}
```
## Best Practices
### Choose Appropriate Radius
* **Urban areas**: Use smaller radii (2-10 miles) for more targeted results
* **Suburban areas**: Use medium radii (10-25 miles) to cover broader regions
* **Rural areas**: Use larger radii (25-100 miles) to account for lower population density
### Combine with Other Filters
Radius searches work well with other parameters:
```bash
# Find people aged 30-40 within 15 miles of a location
curl 'https://api.whitepages.com/v2/person?city=Chicago&state_code=IL&radius=15&min_age=30&max_age=40' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Performance Considerations
* Larger radii return more results but will take longer to process
* Combining radius with name or other filters improves performance
* Consider whether you need to use radius or if other filters like city and state would be sufficient
For best performance, combine radius searches with additional filters like
name, age range, or phone number to narrow down results.
# Retrieve usage data for a specific time range
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Create a Webhook
Use the `POST /v1/webhooks/` endpoint to create a webhook subscription. When a matching property event occurs in your subscribed region, a notification is delivered to your HTTPS endpoint containing the event type and a link to retrieve the full event details.
## Basic Usage
Create a webhook that listens for all deed events in Dallas County, TX:
```bash title="Request"
curl -X POST 'https://api.whitepages.com/v1/webhooks/' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://example.com/webhooks/deeds",
"event_type": "deed.*",
"region": "county:tx.dallas"
}'
```
## Parameters
| Parameter | Type | Required | Description |
| ------------ | ------ | -------- | ------------------------------------------------------------- |
| `url` | string | Yes | HTTPS endpoint to receive webhook deliveries (max 2048 chars) |
| `event_type` | string | Yes | Event type to subscribe to. Use `deed.*` for all deed events |
| `region` | string | Yes | Region filter in `type:value` format |
| `name` | string | No | Human-readable label for the subscription (max 255 chars) |
The `url` must use HTTPS. HTTP endpoints are rejected.
The `region` parameter must reference a webhook-supported region. Texas, New
York, and Florida counties are currently supported. Browse available regions
and filter by webhook support on the [Regions page](/documentation/regions).
## Add a Name for Easy Identification
Assigning a name makes it easier to manage multiple subscriptions:
```bash title="Request"
curl -X POST 'https://api.whitepages.com/v1/webhooks/' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://example.com/webhooks/deeds",
"event_type": "deed.*",
"region": "county:tx.dallas",
"name": "Dallas County Deed Transfers"
}'
```
## Response
A successful request returns the created webhook subscription:
```json title="Response"
{
"result": {
"id": "wh_abc123",
"url": "https://example.com/webhooks/deeds",
"name": "Dallas County Deed Transfers",
"event_type": "deed.*",
"region": "county:tx.dallas",
"status": "active",
"created_at": "2026-02-27T12:00:00Z",
"updated_at": "2026-02-27T12:00:00Z"
}
}
```
After creating a webhook, use the [test
endpoint](/documentation/webhooks/test-webhook) to verify your server receives
and processes payloads correctly.
For full request and response schemas, see the [Create a webhook subscription](/references/webhooks/create_webhook) API reference.
# Delete a Webhook
Use the `DELETE /v1/webhooks/{webhook_id}` endpoint to permanently remove a webhook subscription. Once deleted, no further events will be delivered to the endpoint.
## Basic Usage
Delete a webhook subscription:
```bash title="Request"
curl -X DELETE 'https://api.whitepages.com/v1/webhooks/wh_abc123' \
--header 'X-Api-Key: YOUR_API_KEY'
```
A successful deletion returns a `204 No Content` response with no body.
Deleting a webhook is permanent and cannot be undone. If you need to
temporarily stop receiving events, consider updating the webhook's URL to a
staging endpoint instead.
## Verify Deletion
After deleting, you can confirm the webhook no longer exists by listing your subscriptions:
```bash title="Request"
curl 'https://api.whitepages.com/v1/webhooks/' \
--header 'X-Api-Key: YOUR_API_KEY'
```
The deleted webhook will not appear in the results.
For full request and response schemas, see the [Delete a webhook subscription](/references/webhooks/delete_webhook) API reference.
# Webhooks
The Webhooks API delivers live property deed event notifications directly to your HTTPS endpoint, eliminating the need to poll for changes. When a deed transfer, recording, or other deed event occurs in a region you subscribe to, a notification is sent to your server within minutes containing the event type and a link to retrieve the full event details.
Webhooks are currently available by invite only. To request access, contact
our support team at [api@whitepages.com](mailto:api@whitepages.com) or visit
the [Support and Incident Response](/references/support-and-incident-response)
page.
Webhooks are currently available for Texas, New York, and Florida counties.
Browse the full list of supported regions on the [Regions
page](/documentation/regions).
## Why Use Webhooks
* **Live updates** — Get notified as soon as deed events are recorded, rather than polling the API on a schedule
* **Reduced API usage** — Receive only the events you care about instead of repeatedly querying for changes
* **Regional targeting** — Subscribe to specific counties or states to focus on the markets that matter to your business. See the [Regions page](/documentation/regions) for available regions
* **Lightweight notifications** — Each delivery includes the event type and a link to fetch the full event, keeping payloads small and letting you control when to retrieve details
## Guides
# List Webhooks
Use the `GET /v1/webhooks/` endpoint to retrieve all of your webhook subscriptions. You can filter by status or event type.
## Basic Usage
List all webhook subscriptions:
```bash title="Request"
curl 'https://api.whitepages.com/v1/webhooks/' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Query Parameters
| Parameter | Type | Required | Description |
| ------------ | ------ | -------- | ---------------------------------------- |
| `status` | string | No | Filter by status: `active` or `inactive` |
| `event_type` | string | No | Filter by subscribed event type |
## Filter by Status
List only active subscriptions:
```bash title="Request"
curl 'https://api.whitepages.com/v1/webhooks/?status=active' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Filter by Event Type
List subscriptions for a specific event type:
```bash title="Request"
curl 'https://api.whitepages.com/v1/webhooks/?event_type=deed.*' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Response
The response includes an array of all matching webhook subscriptions:
```json title="Response"
{
"results": [
{
"id": "wh_abc123",
"url": "https://example.com/webhooks/deeds",
"name": "Dallas County Deed Transfers",
"event_type": "deed.*",
"region": "county:tx.dallas",
"status": "active",
"created_at": "2026-02-27T12:00:00Z",
"updated_at": "2026-02-27T12:00:00Z"
},
{
"id": "wh_def456",
"url": "https://example.com/webhooks/deeds-houston",
"name": "Harris County Deed Transfers",
"event_type": "deed.*",
"region": "county:tx.harris",
"status": "active",
"created_at": "2026-02-20T08:30:00Z",
"updated_at": "2026-02-20T08:30:00Z"
}
]
}
```
## Get a Single Webhook
Retrieve a specific subscription by its ID:
```bash title="Request"
curl 'https://api.whitepages.com/v1/webhooks/wh_abc123' \
--header 'X-Api-Key: YOUR_API_KEY'
```
```json title="Response"
{
"result": {
"id": "wh_abc123",
"url": "https://example.com/webhooks/deeds",
"name": "Dallas County Deed Transfers",
"event_type": "deed.*",
"region": "county:tx.dallas",
"status": "active",
"created_at": "2026-02-27T12:00:00Z",
"updated_at": "2026-02-27T12:00:00Z"
}
}
```
For full request and response schemas, see the [List webhook subscriptions](/references/webhooks/list_webhooks) and [Get a webhook subscription](/references/webhooks/get_webhook) API references.
# Webhook Quickstart
This interactive walkthrough guides you through the complete webhook lifecycle using your API key. You will create a webhook subscription, send a test delivery, and retrieve the resulting event — all from this page.
Webhooks are currently available by invite only. To request access, contact
our support team at [api@whitepages.com](mailto:api@whitepages.com) or visit
the [Support and Incident Response](/references/support-and-incident-response)
page.
Webhooks are currently available for Texas, New York, and Florida counties.
This walkthrough uses Dallas County, TX as the default region. Browse the full
list of supported regions on the [Regions page](/documentation/regions).
## Next Steps
* [Create a Webhook](/documentation/webhooks/create-webhook) — Full guide with all parameters and options
* [Event Payload](/documentation/events/event-payload) — Detailed breakdown of event data fields
* [Event Types](/documentation/events/event-types) — All supported event types and their meanings
* [Regions](/documentation/regions) — Browse and search available webhook regions
# Test a Webhook
Use the `POST /v1/webhooks/{webhook_id}/test` endpoint to send a mock event payload to your webhook's URL. This lets you verify that your server receives and processes deliveries correctly without waiting for a real event.
## Basic Usage
Send a test delivery to a webhook:
```bash title="Request"
curl -X POST 'https://api.whitepages.com/v1/webhooks/wh_abc123/test' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{}'
```
This sends a mock notification using the webhook's subscribed event type.
## Parameters
| Parameter | Type | Required | Description |
| ------------ | ------ | -------- | ------------------------------------------------------------------ |
| `event_type` | string | No | Event type to simulate. Defaults to the webhook's subscribed type. |
## Response
The response tells you whether your endpoint received the delivery successfully:
```json title="Response"
{
"success": true,
"delivery": {
"status_code": 200,
"response_time_ms": 150,
"timestamp": "2026-02-27T12:00:00Z"
},
"payload": {
"event_id": "evt_mock_abc123",
"event_type": "deed.transfer",
"links": [
{
"version": "1",
"url": "https://api.whitepages.com/v1/events/evt_mock_abc123"
}
]
}
}
```
The `payload` field shows what was sent to your endpoint. This is a lightweight notification containing the event type and a link to retrieve the full event details using the [Events API](/documentation/events/get-event).
## What Your Endpoint Receives
Your webhook URL receives a POST request with the following payload:
```json title="Webhook delivery payload"
{
"event_id": "evt_mock_abc123",
"event_type": "deed.transfer",
"links": [
{
"version": "1",
"url": "https://api.whitepages.com/v1/events/evt_mock_abc123"
}
]
}
```
| Field | Type | Description |
| ------------ | ------ | ---------------------------------------------------------------------------------------------------------- |
| `event_id` | string | Unique identifier for the event |
| `event_type` | string | The type of event (see [Event Types](/documentation/events/event-types)) |
| `links` | array | One or more links to retrieve the full event details via the [Events API](/documentation/events/get-event) |
Each entry in `links` contains a `version` string and a `url` pointing to the full event resource.
The event linked in a test delivery is a mock event. Use it to verify your
endpoint receives and parses the notification correctly, but note that the
linked event data is synthetic.
## Diagnosing Failures
If `success` is `false`, check the `delivery.status_code` to diagnose the issue:
| Status Code | Meaning |
| ----------- | ------------------------------------------------------- |
| `0` | Could not connect to your endpoint |
| `4xx` | Your server rejected the request (check authentication) |
| `5xx` | Your server encountered an error processing the payload |
Run a test delivery after creating a new webhook or updating the delivery URL
to confirm everything is wired up correctly.
For full request and response schemas, see the [Test a webhook delivery](/references/webhooks/test_webhook) API reference.
# Update a Webhook
Use the `PATCH /v1/webhooks/{webhook_id}` endpoint to update a webhook subscription. All fields are optional — only include the fields you want to change.
## Basic Usage
Update the delivery URL for a webhook:
```bash title="Request"
curl -X PATCH 'https://api.whitepages.com/v1/webhooks/wh_abc123' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"url": "https://example.com/webhooks/deeds-v2"
}'
```
## Parameters
| Parameter | Type | Required | Description |
| ------------ | ------ | -------- | ---------------------------------------------------------- |
| `url` | string | No | New HTTPS endpoint for webhook deliveries (max 2048 chars) |
| `event_type` | string | No | New event type to subscribe to |
| `region` | string | No | New region filter in `type:value` format |
| `name` | string | No | New human-readable label (max 255 chars) |
## Rename a Webhook
```bash title="Request"
curl -X PATCH 'https://api.whitepages.com/v1/webhooks/wh_abc123' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"name": "Dallas County Deeds - Production"
}'
```
## Change the Region
Move a subscription to a different region:
```bash title="Request"
curl -X PATCH 'https://api.whitepages.com/v1/webhooks/wh_abc123' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"region": "county:tx.harris"
}'
```
When changing the `region`, it must reference a webhook-supported region.
Texas, New York, and Florida counties are currently supported. Browse
available regions on the [Regions page](/documentation/regions).
## Response
The response returns the full updated webhook subscription:
```json title="Response"
{
"result": {
"id": "wh_abc123",
"url": "https://example.com/webhooks/deeds-v2",
"name": "Dallas County Deeds - Production",
"event_type": "deed.*",
"region": "county:tx.harris",
"status": "active",
"created_at": "2026-02-27T12:00:00Z",
"updated_at": "2026-02-27T14:30:00Z"
}
}
```
If you change the `url`, use the [test
endpoint](/documentation/webhooks/test-webhook) to confirm your new endpoint
receives payloads correctly.
For full request and response schemas, see the [Update a webhook subscription](/references/webhooks/update_webhook) API reference.
# Retrieve a single event by ID
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Search deed events
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Search all deed events
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Migration Guides
V1 of the Whitepages Pro API is being deprecated in favor of V2. V2 endpoints
deliver richer data, pagination, and forward-compatible response metadata
so customers can adapt to ongoing changes without code rewrites.
These guides walk through every input and output change between V1 and V2
so you can plan a clean migration:
* [Person V1 → V2](/references/migration/person-v1-to-v2) — `GET /v1/person/`
and `GET /v1/person/{id}` map to `GET /v2/person/` and
`GET /v2/person/{id}`.
* [Property V1 → V2](/references/migration/property-v1-to-v2) — `GET /v1/property/`
maps to `GET /v2/property/` (address-based search) and
`GET /v2/property/{property_id}` (details by ID, new in V2).
## When to migrate
The V1 endpoints continue to function during the deprecation window. We
recommend migrating as soon as practical so you can take advantage of V2
features (match scoring, pagination, result metadata, address-ID lookups
on Property) and avoid the eventual V1 removal.
See [Breaking Changes Policy](/references/versioning/breaking-changes-policy)
for our deprecation timeline guarantees, and the [Changelog](/changelog)
for the latest notable changes to V2.
## Reading these guides
Each guide is organized the same way:
1. **TL;DR** — the minimum diff to swap V1 calls for V2.
2. **Endpoint URLs** — what changed at the URL level.
3. **Request parameters** — what's the same, what's new, what's gone.
4. **Response shape** — the top-level structural changes, including
pagination wrappers and per-result metadata where applicable.
5. **Field-by-field mapping** — every V1 field's location in V2, with
notes on shape or nullability changes.
6. **V2-only features** — fields and behaviors that have no V1 analog.
7. **Behavioral differences** — sort orders, error semantics, anything
that would surprise a V1 caller.
8. **Forward compatibility notes** — what's still evolving in V2 and
how to write code that won't break when it changes.
If you spot a gap or want clarification on a specific field's behavior,
let us know via [support](/references/support-and-incident-response).
# Person V1 → V2
import { Callout } from "fumadocs-ui/components/callout";
This guide walks through every input and output change between the V1
and V2 person endpoints so you can migrate cleanly. V2 is a superset of
V1: every V1 field has the same name and meaning in V2, with three
shape changes called out below. The rest of V2's surface is purely
additive — match scoring, fuzzy matching, pagination, per-result
metadata.
## TL;DR
* Swap `/v1/person` for `/v2/person` in both your Search and Details
calls.
* Read results from `response.results` instead of the top-level array
(Search only — Details is unchanged at the envelope level).
* Update email reads from `emails[i]` (a string) to `emails[i].email`
(an object with a confidence `score`).
* Everything else just keeps working. Optional: start parsing
`age`, `match_score`, `matched_by`, and `result_metadata` to take
advantage of new V2 capabilities.
## Endpoint URLs
| Operation | V1 | V2 |
| --------- | --------------------- | --------------------- |
| Search | `GET /v1/person/?...` | `GET /v2/person/?...` |
| Details | `GET /v1/person/{id}` | `GET /v2/person/{id}` |
The Whitepages person ID format is unchanged (`P` prefix + 10
alphanumeric characters).
## Request parameters
Every V1 search parameter works unchanged in V2 with the same name,
type, and accepted values:
`phone`, `name`, `first_name`, `middle_name`, `last_name`, `street`,
`city`, `state_code`, `zipcode`, `radius`, `min_age`, `max_age`,
`include_historical_locations`, `strict_match`.
V2 adds four optional parameters:
| Parameter | Type | Default | Purpose |
| ------------------------ | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `email` | string | — | Search by email address. V1 has no email lookup. |
| `include_fuzzy_matching` | boolean | `false` | Force fuzzy name matching on the first pass. When `false`, the API runs exact first and falls back to fuzzy automatically on a zero-result response — V1 has no equivalent. |
| `page` | integer | `1` | Page number, 1–10. Pages 2+ are billable per the [billing policy](/references/billing). |
| `page_size` | integer | `15` | Results per page, 1–15. |
`GET /v2/person/{id}` continues to take the person ID in the path with
no additional parameters.
## Response shape (Search)
### V1
A V1 Search response is a JSON array of up to 15 person records:
```json title="V1 /v1/person/ response"
[
{
"id": "P1234567890",
"name": "John Smith",
"phones": [{ "number": "(212) 555-0198", "type": "mobile", "score": 92 }],
"emails": ["john.smith@example.com"],
"current_addresses": [...],
"historic_addresses": [...],
"owned_properties": [...],
"relatives": [...],
"aliases": ["Johnny Smith"],
"is_dead": false,
"date_of_birth": "1985-03-15",
"linkedin_url": "https://linkedin.com/in/johnsmith",
"company_name": "Acme Corp",
"job_title": "Software Engineer"
}
]
```
### V2
A V2 Search response wraps the results in a `results` array and adds a
top-level `metadata` block plus a per-result `result_metadata` block:
```json title="V2 /v2/person/ response"
{
"results": [
{
"id": "P1234567890",
"name": "John Smith",
"aliases": ["Johnny Smith"],
"is_dead": false,
"age": 40,
"date_of_birth": "1985-03-15",
"linkedin_url": "https://linkedin.com/in/johnsmith",
"company_name": "Acme Corp",
"job_title": "Software Engineer",
"match_score": 87,
"matched_by": ["name", "address"],
"phones": [{ "number": "(212) 555-0198", "type": "mobile", "score": 92 }],
"current_addresses": [...],
"historic_addresses": [...],
"owned_properties": [...],
"emails": [{ "email": "john.smith@example.com", "score": 88 }],
"relatives": [...],
"result_metadata": {
"details_url": "/v2/person/P1234567890",
"phones": { "displayed": 4, "additional": 3 },
"emails": { "displayed": 1, "additional": 0 },
"historic_addresses": { "displayed": 5, "additional": 2 },
"owned_properties": { "displayed": 1, "additional": 0 }
}
}
],
"metadata": {
"result_count": 432,
"page": 1,
"page_size": 15
}
}
```
## Response shape (Details)
`GET /v2/person/{id}` returns a single record wrapped in `result`,
matching the existing pattern for V2 detail endpoints:
```json title="V2 /v2/person/{id} response"
{
"result": {
"id": "P1234567890",
"name": "John Smith",
"...": "...same fields as a Search result, minus result_metadata, match_score, matched_by"
}
}
```
The `result_metadata` block is exclusive to Person Search. Person Details
continues to return the full lists with no summary block.
## Field-by-field mapping
Every V1 person-record field exists in V2 with the same name and
meaning. Three shapes changed:
| V1 | V2 | What changed |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Top-level: `[record, record, ...]` | Top-level: `{ "results": [...], "metadata": {...} }` | Search response is wrapped. Read `response.results` to get the V1-equivalent list. Pagination (`metadata.result_count`, `.page`, `.page_size`) and per-result `result_metadata` are additive. |
| `emails: ["a@example.com", "b@example.com"]` | `emails: [{ "email": "a@example.com", "score": 95 }, { "email": "b@example.com", "score": 60 }]` | Emails are now objects with a confidence `score` (0–100). Read `.email` to recover the V1 string. The list is sorted by score descending. |
| *(no `age`)* | `age: integer \| null` | New on both Search and Details. Computed from `date_of_birth`; year-only DOB returns a year-based approximation, missing or unparseable DOB returns `null`. |
| *(no `match_score`)* | `match_score: integer \| null` (1–99) | New on Search only. Higher scores indicate stronger relevance + completeness. |
| *(no `matched_by`)* | `matched_by: list[string]` | New on Search only. Names the input field types that contributed to this result (e.g., `["phone"]`, `["name", "address"]`). |
| *(no `result_metadata`)* | `result_metadata: {...}` | New on Search only. See [result\_metadata](#result_metadata) below. |
All other fields — `id`, `name`, `aliases`, `is_dead`, `phones[]`,
`current_addresses[]`, `historic_addresses[]`, `owned_properties[]`,
`relatives[]`, `date_of_birth`, `linkedin_url`, `company_name`,
`job_title` — keep their V1 type, nullability, and semantics. V2 also
sorts the response's top-level keys into a scan-friendly order
(identity → employment scalars → match signals → arrays → relatives
last); rely on key names, not position, when parsing.
## V2-only features
### Pagination
V1 returned up to 15 results per call with no way to reach beyond them.
V2 supports paging through up to 10 pages of 15 results each (150 total
ceiling).
```bash title="V2 paginated request"
curl 'https://api.whitepages.com/v2/person?last_name=Smith&page=2&page_size=15' \
--header 'X-Api-Key: YOUR_API_KEY'
```
`response.metadata.result_count` reports the total number of matching
records, and `metadata.page` / `metadata.page_size` echo the page you
fetched. See [Pagination](/documentation/person-search/pagination) for
details. Each page after the first is a separate billable request.
### Match scoring
V2 results include a `match_score` (1–99) that ranks results by how
closely they match your input across relevance and completeness, plus
a `matched_by` array that names which input field types contributed.
Use these to prioritize the most likely matches in your UI or pipeline.
```json
{ "id": "P1234567890", "match_score": 87, "matched_by": ["name", "address"] }
```
### Fuzzy / nickname matching
V2 broadens name matching to phonetic variants, common nicknames,
initials, and typos. Zero-result searches automatically fall back to
fuzzy matching on the same request — V1 has no such fallback. Set
`include_fuzzy_matching=true` explicitly to start with fuzzy matching
on the first pass instead of falling back only on empty. Useful when
input names come from human entry (CRM notes, voicemail transcripts).
### Confidence-scored emails
V2 emails are objects with a `score` (0–100) so you can prioritize the
most likely-current address for outreach.
### `result_metadata` on every Search result
Every Search result carries a `result_metadata` object summarizing each
list and linking back to the canonical Person Details URL:
```json
"result_metadata": {
"details_url": "/v2/person/P1234567890",
"phones": { "displayed": 3, "additional": 0 },
"emails": { "displayed": 1, "additional": 0 },
"historic_addresses": { "displayed": 4, "additional": 0 },
"owned_properties": { "displayed": 0, "additional": 0 }
}
```
`displayed` is the count of items in the corresponding list on this
response; `additional` is the count linked to the person but not
included because the list is capped (phones: 4, emails: 3, historic
addresses: 5, owned properties: 5). The full lists are always
available at `details_url` (`GET /v2/person/{id}`).
`details_url` is `null` for the rare result that arrives without a
canonical Whitepages person ID (e.g., an unresolved phone-owner
record). Those records are exempt from the upcoming list-narrowing —
they are returned with their full lists regardless.
See the [Changelog](/changelog) for the latest release notes on
`result_metadata` behavior.
## Behavioral differences
| Behavior | V1 | V2 |
| --------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Result cap | Hard cap at 15 per request, no pagination. | Up to 10 pages × 15 results = 150 total. |
| Result ordering | Returned in upstream Search-Layer order; no ranking signal. | Sorted by `match_score` descending where applicable. |
| Email search | Not supported. | New `email` query parameter. |
| Empty results | Empty array `[]` with HTTP 200. | `{ "results": [], "metadata": { "result_count": 0, ... } }` with HTTP 200. |
| Phone scoring | Phones include `score` (0–100). Unchanged. | Same. |
| 404 on Details | Billable in V1. | Same. (Note: V2 Property `404` on Details is *not* billable; Person Details `404` is still billable. See [Billing](/references/billing).) |
## Forward compatibility notes
V2 is the long-term home for the person endpoints. Two upcoming changes
are worth knowing about while you migrate:
1. **Search returns ranked preview lists, not full lists.** Person
Search now caps each list per result (phones: 4, emails: 3,
historic addresses: 5, owned properties: 5) and surfaces the
overflow count in `result_metadata.{list}.additional`. Lists are
sorted by confidence score so the most useful entries appear first.
Person Details (`details_url`) continues to carry the full,
uncapped lists for callers who need everything.
2. **No new V2-only required fields.** All current V2 fields preserve
V1's nullability contracts. Future additive changes will follow the
same pattern.
## Call translation examples
### Search by phone
V1:
```bash
curl 'https://api.whitepages.com/v1/person?phone=2125550198' \
--header 'X-Api-Key: YOUR_API_KEY'
```
V2:
```bash
curl 'https://api.whitepages.com/v2/person?phone=2125550198' \
--header 'X-Api-Key: YOUR_API_KEY'
```
The only required change is the URL path. The V2 response wraps results
in `{ "results": [...], "metadata": {...} }`.
### Search by name and city, page 2
V1 had no pagination — your only option was a single tighter query. V2:
```bash
curl 'https://api.whitepages.com/v2/person?last_name=Smith&city=Seattle&state_code=WA&page=2' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Pull full details for a confirmed match
V1:
```bash
curl 'https://api.whitepages.com/v1/person/P1234567890' \
--header 'X-Api-Key: YOUR_API_KEY'
```
V2:
```bash
curl 'https://api.whitepages.com/v2/person/P1234567890' \
--header 'X-Api-Key: YOUR_API_KEY'
```
V2 Details responses are wrapped in `{ "result": {...} }`. The fields
inside are a superset of V1 (no removals, no nullability changes).
## Code translation snippets
### JavaScript (Search)
```js title="V1"
const response = await fetch(
`https://api.whitepages.com/v1/person?name=${name}`,
{
headers: { "X-Api-Key": API_KEY },
},
);
const records = await response.json();
for (const person of records) {
console.log(person.name, person.emails[0]);
}
```
```js title="V2"
const response = await fetch(
`https://api.whitepages.com/v2/person?name=${name}`,
{
headers: { "X-Api-Key": API_KEY },
},
);
const { results, metadata } = await response.json();
for (const person of results) {
console.log(
person.name,
person.emails[0]?.email,
"match:",
person.match_score,
);
}
console.log(`Total matches across all pages: ${metadata.result_count}`);
```
### Python (Details)
```python title="V1 and V2"
import requests
# V1
r = requests.get(
"https://api.whitepages.com/v1/person/P1234567890",
headers={"X-Api-Key": API_KEY},
)
record = r.json() # V1 returns the record directly
# V2
r = requests.get(
"https://api.whitepages.com/v2/person/P1234567890",
headers={"X-Api-Key": API_KEY},
)
record = r.json()["result"] # V2 wraps in {"result": ...}
```
## Need help?
If you hit a field that doesn't map cleanly, or you'd like guidance on
adopting `match_score` / `result_metadata` in your pipeline, reach out
via [support](/references/support-and-incident-response).
# Property V1 → V2
This guide walks through every input and output change between the V1
and V2 property endpoints so you can migrate cleanly. V2 splits the
single V1 search endpoint into two distinct operations — address-based
search and ID-based details — and the Details response is much richer
than anything V1 exposed.
## TL;DR
* Swap `/v1/property/` for `/v2/property/` for address-based search.
The response is now wrapped in `{ "result": {...} }`.
* Use the new `GET /v2/property/{property_id}` endpoint to pull
comprehensive property details (square footage, year built, tax
assessment, mortgage history, etc.) — capabilities V1 didn't have.
* ZIP codes in V2 Search must be 5 digits exactly. V1 accepted 5 or 9.
* Address IDs (prefix `A`) are now first-class on Details lookups,
so you can traverse directly from a person's `current_addresses[].id`
to property data without a separate address-to-property resolution
step.
## Endpoint URLs
| Operation | V1 | V2 |
| ---------------------- | ----------------------- | -------------------------------- |
| Address-based search | `GET /v1/property/?...` | `GET /v2/property/?...` |
| Details by property ID | *(not available)* | `GET /v2/property/{property_id}` |
| Details by address ID | *(not available)* | `GET /v2/property/{address_id}` |
The biggest URL change is the new Details endpoint. V1 returned all
the property data it had in a single Search response. V2 returns a
lighter Search response with enough to identify the property and its
owners/residents, and a separate Details endpoint for the deep schema
(physical characteristics, tax data, mortgage history).
## Request parameters
### Search
V1 required `street` plus *(city + state\_code)* OR `zip`. V2 keeps the
same address components but treats every parameter as optional at the
schema level, with validation requiring enough to identify a property:
| Parameter | V1 | V2 |
| ------------ | -------------------------------------------------- | -------------------------------------------------- |
| `street` | required | recommended (validation enforces sufficient input) |
| `city` | required when no `zip` | recommended |
| `state_code` | required when no `zip` | recommended (2-letter) |
| `zipcode` | required when no city/state, accepts 5- or 9-digit | accepts 5-digit only |
| `zip` | *alias for `zipcode` in V1* | *removed — use `zipcode`* |
### Details
`GET /v2/property/{property_id}` accepts either:
* **Property ID** — prefix `R` + 10 alphanumeric characters (returned
on Search results as `property_id`).
* **Address ID** — prefix `A` + 10 alphanumeric characters (returned
throughout the API as `address_id` on address objects).
Address IDs are resolved to the associated property before lookup, so
you can traverse from a person record's `current_addresses[].id`
directly into Property Details without a separate resolution step.
Lookups by address ID where the property has no details return `404`
(not billable).
## Response shape (Search)
### V1
A V1 Search response is a single property record (or `null`):
```json title="V1 /v1/property/ response"
{
"id": "R5432109876",
"property_address": {
"id": "A9876543210",
"full_address": "123 Main St, Seattle, WA 98101"
},
"owners": [
{
"id": "P1234567890",
"name": "John Smith",
"current_addresses": [{ "id": "A9876543210", "full_address": "123 Main St, Seattle, WA 98101" }],
"phones": [{ "number": "(206) 555-0100", "type": "landline", "score": 70 }],
"emails": ["john.smith@example.com"]
}
],
"residents": [...]
}
```
### V2
A V2 Search response wraps the property record in `result` and uses a
richer schema for the property fields (mailing address, geolocation,
ownership info, residents) while keeping the owner/resident shape
recognizable from V1:
```json title="V2 /v2/property/ response"
{
"result": {
"property_id": "R5432109876",
"apn": "123-456-789",
"property_address": {
"address_id": "A9876543210",
"full_address": "123 Main St, Seattle, WA 98101",
"city": "Seattle",
"state": "WA",
"line1": "123 Main St",
"zip": "98101"
},
"mailing_address": null,
"geolocation": { "lat": 47.6062, "lng": -122.3321 },
"ownership_info": {
"owner_type": "individual",
"business_owners": [],
"person_owners": [
{
"id": "P1234567890",
"name": "John Smith",
"current_addresses": [...],
"phones": [{ "number": "(206) 555-0100", "type": "landline" }],
"emails": [{ "email": "john.smith@example.com" }]
}
]
},
"residents": [...]
}
}
```
## Response shape (Details — new in V2)
`GET /v2/property/{property_id}` returns everything Search returns plus
\~25 additional fields covering physical characteristics, tax assessment,
ownership history, and vacancy signals:
```json title="V2 /v2/property/{property_id} response (additional Details-only fields)"
{
"result": {
"...": "...all Search fields, kept",
"year_built": 1972,
"effective_year_built": 1998,
"property_purpose": "residential",
"living_sqft": 2400,
"lot_sqft": 7200,
"ground_floor_sqft": 1200,
"basement_sqft": 800,
"basement_type": "full",
"stories": 2,
"bedrooms": 4,
"bathrooms": 3,
"has_pool": false,
"garage_type": "attached",
"roof_covering": "asphalt-shingle",
"heating_fuel": "natural-gas",
"condition": "average",
"build_quality": "average",
"owner_occupied": "owner",
"is_vacant": false,
"assessed_info": {
"assessed_value": 950000,
"assessment_year": 2025
},
"ownership_info": {
"...": "...Search-level ownership fields, plus:",
"sale_date": "2018-05-12",
"last_sale_amount": 875000,
"mortgages": [...]
}
}
}
```
If you're a V1 customer who needs only what V1 returned, V2 Search
covers it. Reach for V2 Details when you want any of the new
physical-characteristics / tax / mortgage data.
## Field-by-field mapping
### Search
| V1 | V2 | What changed |
| ------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Top-level: `record` (or `null`) | Top-level: `{ "result": {...} }` | Search response is wrapped. Read `response.result` to get the V1-equivalent record. `null` (no match) is now expressed as `{ "result": null }`. |
| `id` | `result.property_id` | Renamed for clarity. Same prefix (`R`) + 10 alphanumeric characters. |
| `property_address.id` | `result.property_address.address_id` | Renamed. Same value. |
| `property_address.full_address` | `result.property_address.full_address` plus `.city` / `.state` / `.line1` / `.zip` | Same value, plus a structured breakdown of the components for easier downstream use. The breakdown fields are populated for any well-formed address. |
| `owners[]` | `result.ownership_info.person_owners[]` (+ `business_owners[]`) | Owners are now split into person vs. business under an `ownership_info` umbrella. The person-owner object's shape (id, name, current\_addresses, phones, emails) is the same. |
| `owners[].emails: ["a@..."]` | `result.ownership_info.person_owners[].emails: [{ "email": "a@..." }]` | Emails on owner records are now objects (no confidence score on this surface yet — just the address). |
| `owners[].phones[].score` | `result.ownership_info.person_owners[].phones[]` (no `score`) | Owner-record phone confidence is not surfaced on V2 Search owner objects. Use Person Search/Details if you need confidence-scored phones. |
| `residents[]` | `result.residents[]` | Same shape and semantics. Email shape change matches owners (string → object). |
| *(not present)* | `result.apn` | New. Assessor's Parcel Number. |
| *(not present)* | `result.mailing_address` | New. Populated when the owner's mailing address differs from the property address (absentee owners). |
| *(not present)* | `result.geolocation` | New. `{ "lat": float, "lng": float }`. |
### Details (new in V2)
Details adds the physical-characteristics / tax / mortgage fields shown
in the response shape section above. V1 had no equivalent surface; the
migration from V1 simply gains access to those fields when you call the
Details endpoint.
## V2-only features
### Details by property ID
V1 callers who wanted full property data had to take what came back
from Search. V2 splits the surface:
* `GET /v2/property/` returns enough to identify the property and its
owners / residents.
* `GET /v2/property/{property_id}` returns the comprehensive record,
including everything Search returns plus tax and mortgage data.
This split keeps Search responses lightweight and lets Details carry
the deeper schema.
### Details by address ID
The address IDs you see throughout the API (on person records,
property records, in Search results) are first-class lookup keys in V2.
`GET /v2/property/{address_id}` (any ID starting with `A`) resolves to
the associated property before lookup. You can traverse directly from
a person's `current_addresses[].id` to that property's full details
without a separate address-to-property resolution step.
Not every address has full property details. Address-ID lookups where
no property data exists return `404`. These responses are not
[billable](/references/billing).
### Owner vs business split
V2 distinguishes between individual owners (returned in
`person_owners[]`) and business / entity owners (returned in
`business_owners[]`). V1 lumped both into `owners[]` with limited
data on business entities.
### Structured address components
Every address object on V2 includes a breakdown of `city`, `state`,
`line1`, `zip` alongside the `full_address` string, so you don't need
to parse the formatted string to extract components.
## Behavioral differences
| Behavior | V1 | V2 |
| ------------------------------ | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Search response shape | Bare record or `null`. | `{ "result": record \| null }`. |
| Address-based no-match | `null` body, HTTP 200. | `{ "result": null }`, HTTP 200. Same billability. |
| Details by property ID | *(not available)* | New endpoint; `404` when the ID doesn't resolve. Property-ID `404` is billable. |
| Details by address ID | *(not available)* | Same endpoint as property-ID lookup; address IDs are resolved transparently. Address-ID `404` (no property data for that address) is **not** billable. |
| ZIP code format | 5- or 9-digit ZIP accepted. | 5-digit ZIP only. |
| Missing required parameters | `MissingLocationParameterError` (HTTP 400). | `MissingSearchParametersError` (HTTP 400). Message format and field names differ; error code shape is the same envelope. |
| `result_metadata` on responses | *(not present)* | *(not present — `result_metadata` is exclusive to Person Search).* |
## Call translation examples
### Search by full address
V1:
```bash
curl 'https://api.whitepages.com/v1/property?street=123+Main+St&city=Seattle&state_code=WA' \
--header 'X-Api-Key: YOUR_API_KEY'
```
V2:
```bash
curl 'https://api.whitepages.com/v2/property?street=123+Main+St&city=Seattle&state_code=WA' \
--header 'X-Api-Key: YOUR_API_KEY'
```
The only required change is the URL path. The V2 response wraps the
result in `{ "result": {...} }`. If you were passing a 9-digit ZIP
(e.g., `98101-1234`), truncate to the first 5 digits for V2.
### Pull full details by property ID (new in V2)
V1 had no equivalent. V2:
```bash
curl 'https://api.whitepages.com/v2/property/R5432109876' \
--header 'X-Api-Key: YOUR_API_KEY'
```
### Pull full details by address ID (new in V2)
Useful for traversing from a person record's `current_addresses[].id`
straight into property data:
```bash
curl 'https://api.whitepages.com/v2/property/A9876543210' \
--header 'X-Api-Key: YOUR_API_KEY'
```
## Code translation snippets
### JavaScript (Search)
```js title="V1"
const response = await fetch(
`https://api.whitepages.com/v1/property?street=${street}&city=${city}&state_code=${state}`,
{ headers: { "X-Api-Key": API_KEY } },
);
const property = await response.json();
if (property) {
console.log(property.id, property.owners?.[0]?.name);
}
```
```js title="V2"
const response = await fetch(
`https://api.whitepages.com/v2/property?street=${street}&city=${city}&state_code=${state}`,
{ headers: { "X-Api-Key": API_KEY } },
);
const { result } = await response.json();
if (result) {
console.log(
result.property_id,
result.ownership_info?.person_owners?.[0]?.name,
);
}
```
### Python (Details — new flow)
```python title="V2 Details by property ID"
import requests
r = requests.get(
"https://api.whitepages.com/v2/property/R5432109876",
headers={"X-Api-Key": API_KEY},
)
property_details = r.json()["result"]
print(property_details["year_built"], property_details["bedrooms"])
```
```python title="V2 Details by address ID (from a person record)"
person = requests.get(
"https://api.whitepages.com/v2/person/P1234567890",
headers={"X-Api-Key": API_KEY},
).json()["result"]
address_id = person["current_addresses"][0]["address_id"]
property_details = requests.get(
f"https://api.whitepages.com/v2/property/{address_id}",
headers={"X-Api-Key": API_KEY},
).json()["result"]
```
## Need help?
If you hit a field that doesn't map cleanly, or you have questions
about the new Details surface, reach out via
[support](/references/support-and-incident-response).
# Gets person details by id
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Search for a person by name, phone number, and address
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Get property details by ID
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Search for property by address
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# List counties for a state
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# List all US states and territories
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Breaking Changes Policy
import { Callout } from "fumadocs-ui/components/callout";
We avoid breaking changes at nearly all cost. Backward compatibility is a top priority, and our goal is to minimize disruption to your integrations.
## Our Commitments
* **Breaking changes are always introduced in a new API version.** Your existing integration continues to work on the current version.
* **No unannounced breaking changes.** Every breaking change is communicated in advance.
* **Minimum 30-day notice** before any breaking change takes effect.
* **Migration guides** — as a matter of practice, breaking changes are accompanied by a migration guide with before-and-after examples.
* **Deprecation notices** are communicated via email and changelog before anything is removed.
* **Version support** — when a new version introduces breaking changes, the previous version remains available for at least 3 months after the new version is released.
## What We Consider a Breaking Change
* Removing or renaming an endpoint or data tool you call
* Removing or renaming a field from a response body
* Changing the type of an existing response field
* Adding a new required parameter to an endpoint or data tool call
* Changing authentication or authorization behavior
* Modifying error response formats
## What We Do Not Consider a Breaking Change
* Adding a new optional request parameter
* Adding a new tool to the MCP server
* Adding a new endpoint to the API
* Adding new fields to an existing response shape we return
* Adding new values to an existing enumerated field
* Text or wording changes to error messages or descriptions
We recommend that your integration ignores unknown fields in API responses and
MCP data-tool responses. This allows us to add new fields without affecting
your application.
The same policy applies wherever we expose the API. What it means in practice depends on the surface you use.
## REST / HTTP Endpoints
Breaking changes ship in a new API version at a new path (for example, `/v2/`), so your current integration keeps working untouched. We announce the change with the notice and support windows above. Within a version, an endpoint's type signature — the parameters it accepts and the fields it returns — only grows: we may add new optional parameters and new response fields, but we do not remove, rename, or change the type of those already there.
## MCP Server & Tools
Our Breaking Changes policy covers only the [MCP server's](/documentation/mcp) **data tools**. Data tools fetch live data or change your account and **require your API key to run** — person search, property lookup, account usage, and the like.
The other tools available via the MCP server are not subject to this Breaking Changes policy, as they are advisory, documentation, or navigation assistance rather than integration points.
Data tools are agent-ready wrappers for the existing REST endpoints, and are therefore governed under the same breaking-changes policy as the rest of the API.
Clarifications for breaking and non-breaking changes within the MCP server:
* Changes to a data tool's **name, inputs, and outputs** are considered breaking changes.
* All other changes to a tool's description or tool-definition metadata are **not** breaking changes.
* Data tools are **deprecated and removed on the same schedule as their associated endpoint**, and disappear from the server when the endpoint does.
* Data tools can be **removed independently of the endpoint**; in that case the tool follows the standard deprecated → removed timeline above (minimum 30-day notice).
* **Deprecation notices name the exact tools affected**, so you know what a given change touches.
* Changes to the **server URL, transport, authentication, or supported protocol versions** are considered breaking changes.
How much any of this affects you depends on how you connect:
* **Conversational clients** — Claude Desktop, Cursor, or any freeform agent pointed at the server — re-read the tool list every session and adapt to renamed tools or changed fields on their own. Only a change to the server URL, authentication, or transport, or the removal of a tool with no replacement, needs action from you.
* **Brokered or hard-coded integrations** — a router mapping fixed tool names to actions, or code that reads specific fields out of a result — should treat a data-tool change exactly like the equivalent REST change and migrate within the announced window.
# Change Notifications
import { Callout } from "fumadocs-ui/components/callout";
We notify you about critical changes through multiple channels to ensure you never miss an important update.
## Notification Types
| Type | Channel | Lead Time |
| ------------------------- | ---------------- | ------------------- |
| **Breaking changes** | Email, changelog | 30 days minimum |
| **Deprecation notices** | Email, changelog | 30 days minimum |
| **New features** | Email, changelog | At release |
| **Scheduled maintenance** | Email | 7 days minimum |
| **Emergency maintenance** | Email | As soon as possible |
## Staying Informed
* **Changelog** — All API changes are documented in our [changelog](/changelog) with detailed descriptions
* **Email notifications** — Sent to the email address associated with your API account. Ensure your contact information is up to date.
Make sure your account email is current. Critical notifications about breaking
changes and security updates are sent exclusively to your registered email.
# Create a webhook subscription
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Delete a webhook subscription
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Get a webhook subscription
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# List webhook subscriptions
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Test a webhook delivery
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}
# Update a webhook subscription
{/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */}