Matching, confidence & partial names
The surname anchor, name strategies, the closed match vocabulary, and how matchConfidence is built.
Base URL https://api.offendersearch.appThe surname is the anchor
These rules hold in every mode — on the cache and on a live source — because matching is applied on top of every source’s output.
lastNameis required. A query with no surname is refused with422 guard_unbounded_query. BothlastNameand the shorthandlastare accepted.- The surname must corroborate. A record whose surname neither equals nor prefix-matches your
lastNameis dropped. This is the only hard name filter. - A record missing a first name is KEPT and flagged
firstName:absentwith a small confidence penalty — we cannot disprove yourfirstName, so it is never silently dropped. - Case-insensitive.
smith,Smith,SMITHare identical.
The two surname strategies — nameStrategy
| nameStrategy | Surname matches | Default? |
|---|---|---|
prefix | the record’s surname equals your value, or starts with it | Yes |
exact | the record’s surname equals your value | no |
Smyth does not match Smith; Ross does not match Rose. In this domain a false positive is the expensive error — telling a customer that an innocent person has a criminal record is materially worse than a miss — so the matcher never introduces a surname it was not given.First-name matching and nicknames
When you supply firstName, it is scored after the surname corroborates. Both sides are folded through a small, conservative nickname table first — Bob/Bobby/Rob → Robert, Bill/Will → William, Jim → James — in both directions. A nickname hit reads as firstName:exact (the two folded names became equal). A first-name mismatch does not drop the record — it only lowers its confidence, because the surname is the only hard filter.
Prefix (partial-name) matching — prefixMatch
prefixMatch requests prefix matching on a named field explicitly, and is where the 3-character floor lives. It accepts "firstName", "lastName", "both", or a list.
{ "query": { "lastName": "hamil", "firstName": "al", "prefixMatch": "lastName" } }| You sent | 2-char surname behaviour |
|---|---|
| nothing (default) | falls back to exact — no error (so Li, Ng, Ho, Vo work) |
nameStrategy: "prefix" | 422 prefix_too_short — you asked for prefix |
prefixMatch: "lastName" | 422 prefix_too_short — you asked for prefix |
nameStrategy: "exact" | exact — no error, no floor |
The floor guards the bulk-download shape, not short surnames. A 2-character exact surname is always fine.
The match vocabulary on the wire
Every record tells you how it matched, in matchBasis (space-separated field:how tokens) and matchDetail (one plain sentence). The surname/given tokens are exact, prefix, absent, mismatch, notQueried; the dob tokens are match, year, monthYear, age, ageFromDob, absent.
{
"name": { "first": "ROBERT", "middle": "E", "last": "SMITH", "suffix": "" },
"matchConfidence": 0.95,
"matchBasis": "lastName:exact firstName:exact dob:match",
"matchDetail": "name and full date of birth agree",
"matchState": "dob_match",
"unverified": false
}How matchConfidence is built
matchConfidence is not a probability — it is a sum of fixed evidence contributions, clamped to [0.0, 0.99], so a name-only match can never present as certainty.
| Contribution | Adds |
|---|---|
| Surname exact (base) | +0.55 |
| Surname prefix (weaker than exact) | +0.42 |
| First name exact (after nickname folding) | +0.25 |
| First name prefix (either direction, Alex↔Alexander) | +0.12 |
| First name absent (record publishes none) | −0.05 |
| First name mismatch (present, does not line up) | −0.20 |
| DOB dob_match | +0.40 |
| DOB year_match | +0.30 |
| DOB age_match | +0.18 |
matchState: "dob_match" with lastName:exact and firstName:exact — and honour the FCRA restriction: this data may not be used for FCRA-covered decisions at all. See Searching by date of birth.