Date-of-birth matching
A date of birth narrows the search and labels every record with how the registry's birth evidence agreed. Here is how to send it and how to read it.
When to use this
Whenever you hold a date of birth — from an ID scan, an application, an admissions record — send it. Registries differ in what they publish: a full date, a birth year only, a published age only, or nothing. The API compares your date against whichever of those the record carries and reports the outcome in matchState, so a reviewer knows exactly how strong the identity evidence is. You will build a search that sends dob (or age when that is all you have) and a reader that turns matchState and dobPrecision into a confidence tier.
Before you start
- A test key on
https://sandbox.offendersearch.app. Sandbox people: Exact Match publishes a full date,1980-01-01; the three Name Only registrants publish no date, year or age at all. query.dobis an ISO date,YYYY-MM-DD.query.ageis an integer. They are alternatives;dobis stronger.- Two tuning fields on
query:ageTolerance(0–10, default 1) andonAgeMismatch(dropdefault, orflag).
dob does not require the registry to publish one. A record with no birth evidence is still returned on the name, with matchState: "no_dob_age_year" and unverified: true. Dropping those records would hide real registrants; your job is to review them, not to filter them out.Step by step
- Send the date. Search Exact Match with
dob1980-01-01. The record comes backmatchState: "dob_match",dobPrecision: "exact". - Send a contradicting date. Search Exact Match with
dob1990-05-05. Zero records: a registry that publishes a full date that disagrees with yours rules the person out, and the record is filtered rather than shown. - Send an age instead. Search Exact Match with
age46. The record comes backmatchState: "age_match": the age derived from the published date falls withinageToleranceof yours. - Search people with no birth evidence. Search Name Only with any
dob. All three come backno_dob_age_year,unverified: true,dobPrecision: "unknown".
Steps 1–3 — the same person, three ways
# 1. full date — matchState dob_match
curl -s https://sandbox.offendersearch.app/v1/search -H "X-API-Key: $OFFENDERSEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{"query": {"firstName": "Exact", "lastName": "Match", "dob": "1980-01-01"}}'
# 2. contradicting date — counts.records 0
curl -s https://sandbox.offendersearch.app/v1/search -H "X-API-Key: $OFFENDERSEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{"query": {"firstName": "Exact", "lastName": "Match", "dob": "1990-05-05"}}'
# 3. age instead of a date — matchState age_match
curl -s https://sandbox.offendersearch.app/v1/search -H "X-API-Key: $OFFENDERSEARCH_KEY" \
-H "Content-Type: application/json" \
-d '{"query": {"firstName": "Exact", "lastName": "Match", "age": 46}}'{
"recordId": "rec_28db9639d712c4c61e8e",
"matchConfidence": 0.9,
"matchBasis": ["lastName", "firstName", "dob", "lastName:exact", "firstName:exact", "name_match"],
"matchDetail": { "strategies": { "lastName": "exact", "firstName": "exact" },
"fieldsPresent": ["lastName", "firstName", "dob"], "verification": "age_match" },
"dob": "1980-01-01", "birthYear": 1980, "dobPrecision": "exact", "age": "46",
"dobVerification": "age_match",
"matchState": "age_match",
"unverified": false
}Note the bare dob token in matchBasis: it says the record has a date of birth, not how it agreed. The agreement is matchState (echoed as matchDetail.verification). dobVerification is the engine's raw token and is kept for compatibility; branch on matchState.
Step 4 — no birth evidence on file
{
"recordId": "rec_ca91307a7124dca36777",
"matchConfidence": 0.6,
"matchBasis": ["lastName", "firstName", "unverified_no_dob_or_age", "lastName:exact", "firstName:exact", "name_match"],
"matchDetail": { "strategies": { "lastName": "exact", "firstName": "exact" }, "fieldsPresent": ["lastName", "firstName"],
"signals": ["unverifiable", "matchedLegalName"], "verification": "unverified_no_dob_or_age" },
"dob": null, "birthYear": null, "dobPrecision": "unknown", "age": "",
"matchState": "no_dob_age_year",
"unverified": true
}Tuning the age comparison
{ "query": { "firstName": "Jordan", "lastName": "Rivera", "dob": "1988-04-12",
"ageTolerance": 2, "onAgeMismatch": "flag" } }Eleven registries publish an age and no date. ageTolerance is how many years of slack that comparison allows (default 1, because a published age with an unpublished birthday is consistent with two birth years). onAgeMismatch: "flag" returns a name match whose published age contradicts your date as matchState: "age_mismatch", always unverified: true, instead of dropping it — useful when "we checked and the age disagrees" is a fact you want to show. A contradicting full date is always filtered; the sandbox confirms this: Exact Match with dob 1990-05-05 and onAgeMismatch: "flag" still returns zero records.
Reading the result
| `matchState` | The registry published… | Meaning for this job |
|---|---|---|
dob_match | a full date, equal to yours | Strongest confirmation. Lifts every name-strategy cap on the score. |
year_match | a birth year only (some states), equal to your year | Good evidence, not a confirmed date. Raises the score floor to 0.80. Review. |
age_match | an age (or a date you compared by age), within ageTolerance | Consistent, not confirmed. Review. |
no_dob_age_year | nothing to compare | Name is the only evidence; unverified: true. Review against photo, address, age range. |
age_mismatch | an age that contradicts your date | Only with onAgeMismatch: "flag"; always unverified. Usually noise. |
null | — | You sent no dob or age. Not a failed check — nothing was checked. |
| Field | Values | Read it as |
|---|---|---|
dobPrecision | exact, year, year_month, unknown | How much birth date the source published. Never compare a year record as a full date. |
dob | YYYY-MM-DD or null | Only a full date; null for year-only and age-only records. |
birthYear | integer or null | Present whenever a year is known, including year-only records. |
age | string, "" when unknown | Published, or derived from an exact date. A string on the record; query.age is an integer. |
unverified | boolean | true when your identifiers could not be checked against the record. |
Edge cases and pitfalls
- `"dob": "1980"` is a `422` with a list-shaped
detail(loc: ["body", "query", "dob"]). Send a full ISO date, or sendagewhen the year is all you know. - A `dob_mismatch` record is never shown; it is filtered. If a reviewer insists a person "should have come back", the usual reason is a wrong date on your side — re-run without
doband compare. - `matchState: null` is not `no_dob_age_year`.
nullmeans you sent nothing to check;no_dob_age_yearmeans you did and the registry had nothing. The sandbox shows both: Exact Match withoutdobisnullat 0.9; Name Only withdobisno_dob_age_yearat 0.6. - Truncation protects dated records. When a query carrying a
dobhits a registry's candidate cap (incompleteReason: "truncated"), records whose birth year matches are examined first; what gets cut is from the unknown-birth-date group. - Year-only states. A registrant in a year-only registry can never be
dob_match;year_matchwithdobPrecision: "year"is the best that registry can say. Do not hold it to the full-date tier. - Age drift. A published age is anchored to the date the registry page was read, not today; that is what the default
ageToleranceof 1 absorbs. Raise it for a high-recall pass and expect more same-name strangers.
Production checklist
dobsent whenever you hold one, asYYYY-MM-DD;ageonly as a fallback.- Review tiers keyed on
matchState;dob_matchis the only tier eligible for an automatic path. no_dob_age_yearrecords are reviewed, not dropped.ageToleranceandonAgeMismatchset deliberately and documented in your own runbook.
Related products
Product overview
- Sex offender search API
- Sex offender registry API
- Offender search API
- Background check API
- Bulk sex offender search
- Background check API pricing
- Background check API integration
- Integrations
- Free background check API
- Pay-as-you-go background check API
- Background check API in Python
- Background check API in Node.js
- NSOPW API