Offendersearch
API Reference · v1.0.0

Matching, confidence & partial names

Match modes, the closed strategy vocabulary, confidence ceilings, and partial-name search.

Base URL https://api.offendersearch.appThis page as Markdown/docs/matching.md

Match modes

The match field sets the fuzzy-match tolerance, applied uniformly across every jurisdiction, so behaviour is consistent no matter which states you hit. Whatever mode you choose, supplying a dob or age is the strongest lever on accuracy — it verifies identity and pushes matchConfidence toward 1.0.

ModeFirst nameLast nameUse it for
strictExact onlyExact onlyLowest false positives; pair with a DOB.
balancedNicknames, variants, initials, typos (edit-distance 1)ExactThe default — good recall with controlled noise.
broadAll balanced rulesAlso prefix + typo toleranceMaximum recall; expect more low-confidence rows to triage.

Read matchDetail to see exactly why a record matched — it splits the match into strategies (for example {"lastName":"exact"} vs {"firstName":"nickname"}), the fieldsPresent on the record, and any signals. The flat matchBasis array carries the same information mixed together (for example ["lastName", "firstName", "dob", "lastName:exact", "name_match"]) so you can set your own confidence threshold for auto-accept versus manual review.

Nickname-aware name search

Under balanced (and broad), a firstName is expanded to its common nicknames and variants before matching — so a search for John also surfaces Johnny and Jack, and a search for Jonathan matches records filed as John. The expansion used is echoed back on every record in the output-only nicknames[] array (parity with a legacy firstName_nicknames field). It is computed at serialize time and is never presented as data published by a jurisdiction.

The match-strategy vocabulary — the complete list

Every record tells you how it matched, per field, in matchDetail.strategies (and, in the older flat form, as the field:strategy tokens of matchBasis). This is the whole vocabulary — the list is closed. Any token the engine emits that this mapping does not define arrives under matchDetail.other rather than appearing here, so a new token can never quietly pass for one of these.

StrategyCan appear onMeaningRankCeilingTurned on by
exactlastName, firstName, aliasThe field equals what you sent — or equals one whole token of a compound surname, so a Smith query matches Hamilton-Smith.1noneEvery mode. Cannot be switched off.
nicknamefirstName onlyA known given-name equivalence. Never appears on a surname — there is no surname nickname table, and asking for one is a 422.20.75balanced, broad
initialfirstName onlyA single letter against a full given name, in either direction.20.60balanced, broad. Not requestable via nameMatch.
prefixlastName, firstName, aliasThe field starts with what you sent. Minimum 3 characters, anchored at a token start — never a mid-word substring.30.60firstName: balanced, broad · lastName: broad only
fuzzylastName, firstName, aliasA spelling variant or typo within an edit-distance budget that scales with name length.40.60firstName: balanced, broad · lastName: broad only
middlefirstName onlyThe given name you sent is the person’s MIDDLE name, matched as a whole token of the registered legal name — 81% of records carry one, and many people go by theirs. Whole token and exact only: minimum 2 characters, never a prefix, never fuzzy, and an initial is not a name in either direction. Tried only after the registered first name and every alias have failed, so a stronger basis is always the one reported. matchedNameType stays "legal"; signals also carries matchedMiddleName.50.60balanced, broad
absentfirstName onlyThe record publishes no first name at all, so your query could not be DISPROVED. The record is kept and flagged — it is never a confirmation.60.60Every mode. Not requestable via nameMatch.

Rank is the ordering contract, not a score: 1 is the strongest evidence, and results sort by surname rank then given-name rank, with legal-name hits ahead of alias-only hits. Ceiling is the cap the strategy puts on matchConfidence, applied automatically so a widened hit is never reported as certainty. The cap is lifted in exactly one case: you supplied a dob and the record’s full date of birth matched it.

The alias key appears only when an alias, rather than the registered name, produced the hit — and it carries only exact, prefix and fuzzy. Aliases are published unstructured and in mixed word order, so every token is tested and the response does not assert which one was the given name; that is also why the given-name-only strategies are not offered on it. An alias-only hit caps at 0.55, the lowest value the engine produces.

Choosing an auto-accept threshold. Gate on matchDetail.strategies, not on matchConfidence alone — several strategies share one ceiling. Auto-accept only exact on every field you queried with matchedNameType: "legal", and for anything consequential require a confirmed date of birth as well. Send nickname, initial, prefix and fuzzy hits to human review: they are real people whose name is near the one you sent. Never auto-accept an alias-only hit or firstName: "absent" — the latter means this person could not be ruled out, which is not the same fact as this is your person. In this domain a false positive is far more damaging than a miss.

Partial name search

When you only know part of a name, set prefixMatch and the name you send is treated as the start of a name. Searching thom returns Thomas, Thompson and Thomason — on the first name, the last name, or both — and it is matched against every recorded alias as well as the registered name.

POST /v1/search
{
  "query": {
    "firstName": "thom",
    "lastName": "and",
    "prefixMatch": "both"
  }
}

// → Thomas Anderson, Thompson Andrews, ...

prefixMatch accepts "firstName", "lastName", "both", or a list. When both fields are prefix-matched, a record must satisfy both.

The rules

RuleWhat it means
Prefix, not substringthom matches Thompson but not Bothomley. We anchor at the start of a name, never mid-word.
Minimum 3 charactersA shorter prefix is rejected with 422. One or two letters is a bulk download, not a search.
Every name partA compound or hyphenated surname matches on any of its parts: thom finds Hamilton-Thompson.
Aliases includedPrefixes are matched against every recorded alias as well as the registered name, so a variation of a first name still finds the person. matchedName tells you which one matched.
A superset of exactTurning prefix matching on never loses a record that an exact search would have returned.
Exact ranks firstAn exact surname match always appears above a prefix match, and the order is deterministic — paging never reshuffles results.
Scope it when you canA prefix search scoped with an explicit jurisdictions list returns in roughly 30 ms; an unscoped nationwide prefix search on a very common stem returns in around 0.6 s. Note that query.state does NOT scope the search — it is a residence filter, and every jurisdiction is still queried.

Per-field control with nameMatch

prefixMatch is the shorthand. When you want to drive matching yourself, send nameMatch and list exactly the strategies you want for each field. Anything you leave out is off for that field, and nameMatch overrides both prefixMatch and match.

Per-field control
{
  "query": {
    "firstName": "Robert",
    "lastName": "thom",
    "nameMatch": {
      "firstName": [],
      "lastName": ["prefix"],
      "aliases": true
    }
  }
}

// firstName: []          exact only, no nickname widening
// lastName:  ["prefix"]  prefix | fuzzy
// aliases:   true        also match aliases (the default)
// → Robert Thompson  (not Bob Thompson)
StrategyApplies toMeaningExample
exactfirstName, lastNameThe name equals what you sent. Always on — it cannot be switched off.Thomas → Thomas
prefixfirstName, lastNameThe name starts with what you sent. Minimum 3 characters.thom → Thomas, Thompson, Thomason
nicknamefirstNameA known given-name equivalence.bob → Robert
fuzzyfirstName, lastNameA spelling variant or typo within edit distance.smyth → Smith

Which name matched — legal or alias

A prefix is matched against every recorded alias as well as the registered name, so a variation of a first name still finds the person. Every record tells you which name did it, so an alias hit never reads as “you returned the wrong person”:

A record returned via an alias
{
  "name":        { "first": "Ryan", "last": "Lloyd" },
  "aliases":     ["BRANDON THOMPSON"],
  "matchedName": { "value": "BRANDON THOMPSON", "type": "alias" },
  "matchBasis":  ["lastName:prefix", "alias:prefix", "alias_match"],
  "matchConfidence": 0.55
}

matchedName.type is "legal" when the registered name matched and "alias" when an alias did. Send "nameMatch": { "aliases": false } to search registered names only.

How results are ordered

The ordering is deterministic, so a customer paging through results never sees them shuffle. An exact surname match always outranks a prefix match. In order:

  1. Surname match strength — exact, then nickname, then prefix, then fuzzy
  2. First-name match strength, on the same scale
  3. Legal-name matches before alias-only matches
  4. matchConfidence, highest first
  5. Last name, first name, then date of birth
  6. Record id — the final tie-break, so the ordering is total and repeatable

A partial match is a candidate, not a confirmation

Widening a search widens the risk of returning the wrong person, so a partial-name hit is never presented as certainty. matchConfidence is capped by how the name matched:

How the name matchedmatchConfidence ceiling
Exact match on the registered nameNo cap
Nickname0.75
Prefix, fuzzy, or no first name published0.60
Alias only0.55

The one exception: if you supplied a dob and the record’s full date of birth matches it, the cap is lifted — a confirmed date of birth is identity evidence that a partial name match is not. Supplying a dob or age alongside a prefix search is the single best way to keep precision while widening recall. See Searching by date of birth.

Every result is a candidate match, not identity verification. That is true of any search here and it is doubly true of a partial-name search: read matchBasis, matchedName and matchConfidence, and confirm identity against the linked official record before acting on a result.