How the check works
Request flow
The minimum request supplies a last_name. Everything else is optional - first name, middle name, date of birth, address, up to four phone numbers, and up to four email addresses. Whichever fields you supply are evaluated against each candidate; the response tells you which ones matched.
The high-level flow is:
- Filter the universe on
last_name; supplied identifiers (DOB, address, phone, email) seed additional indexed lookups so candidates that match on a strong identifier are still considered even if their last-name spelling differs from the supplied one. - Score every candidate that comes back against the supplied fields.
- Return either the single best candidate, or every candidate ordered best-first if
return_multiple_candidates: truewas supplied.
Response shape
match_results is always an array. By default it contains the single best candidate (length 0 if no candidate was found, length 1 otherwise). Set return_multiple_candidates: true to receive multiple candidates ordered best-first.
When return_multiple_candidates: true is set, the response is capped at the top 5 candidates by score. If your search matches more than 5 records, only the strongest 5 are returned; the weaker tail is dropped. Narrow your request (add a DOB, a phone, or an address) to lift the strongest candidates above the cap.
Two universe records that produce identical per-field outcomes against your request collapse into a single row, so the count of rows in match_results reflects the number of distinct outcome maps, not the count of underlying records considered. See the Multi-candidate review use case for details.
Each candidate row only includes the fields that were actually evaluated. Fields the caller did not supply are omitted from the row entirely (they are not returned as null or any placeholder value). The address block is treated as a single unit: when no address was supplied, the address rollup and the four street_address / suburb / state / postcode components are all omitted together.
Match outcomes
First name and middle name
For first_name and middle_name the response uses a graded ladder:
| Label | Meaning |
|---|---|
match |
Exact equality after normalisation (case- and diacritic-insensitive). |
alias_match |
The two names share a known nickname / alias group (Bob/Robert, Jenny/Jennifer, Tony/Antonio). |
partial_match |
One side is exactly a single-letter initial that matches the leading letter of the other side (for example P vs Peter). Modelled on universe records that only have a first-letter initial captured for the first name. Longer-form abbreviations like Pete vs Peter are not partial matches - they are handled by the alias_match ladder instead. |
fuzzy_match |
The two names share a phonetic (metaphone) code and the same leading letter. |
no_match |
None of the above. |
no_record |
(Middle name only.) The caller supplied a middle name but the candidate has none on file. |
not_used |
The caller supplied this field but it was dropped because it failed validation and ignore_errors=true. |
Which match types are accepted is controlled per field via first_name_matching, middle_name_matching, and last_name_matching (each defaults to ["exact"]).
Last name
last_name uses a smaller subset of the ladder:
| Label | Meaning |
|---|---|
match |
Exact equality after normalisation. |
fuzzy_match |
The two last names share a metaphone code and the same leading letter. Only returned when last_name_matching: ["exact","fuzzy"] is set. |
no_match |
Neither of the above. |
not_used |
Dropped because it failed validation and ignore_errors=true. |
Date of birth
dob has its own ladder of partial outcomes for cases where the supplied date is close but not identical to the candidate's:
| Label | Meaning |
|---|---|
match |
Exact match on year, month, and day. |
match_day_month_reversal |
Year matches; the supplied day and month are the same as the candidate's month and day swapped (e.g. supplied 1989-12-08 vs candidate 1989-08-12). |
match_year |
Only the year matches; day and month differ and are not a reversal. |
no_record |
The candidate has no DOB on file. |
no_match |
Year does not match. |
not_used |
Dropped because it failed validation and ignore_errors=true. |
Address
address is a rollup summary derived from the four supplied address components (street_address, suburb, state, postcode). Each component returns match / no_match independently and they are returned alongside the rollup so you can see exactly which parts contributed.
| Label | Meaning |
|---|---|
match |
All four supplied address components match the candidate. |
match_street |
Same street number on the same street name (street-type variations like ST vs RD are allowed) but at least one of suburb / state / postcode does not match. |
match_locality |
The street did not match, but state matches (when supplied) and at least one of suburb or postcode also matches. |
no_match |
None of the above. |
not_used |
Dropped because it failed validation and ignore_errors=true. |
Whichever address input form was used (gnaf_id, full_address, or the four address parts), the address is resolved to its canonical components before evaluation, so the same rollup applies regardless of how it was supplied.
A person commonly has more than one address on file (a current address plus past addresses), but match_results only ever returns one row per person. Internally, every address on file is scored against the supplied address and the best-matching address is the one whose outcome appears in the response. So if a person has a current address that is an exact match and an older address that is only a match_locality, you will see address: match in the response - never both. Ties on rollup outcome are broken by preferring the most recently active address (largest date_end).
Phone and email
Phone and email are evaluated per slot. Each supplied slot (phone, phone2, phone3, phone4, and the same four email slots) returns its own outcome in the response. Slots that were not supplied are omitted.
| Label | Meaning |
|---|---|
match |
The supplied value for this slot matches at least one of the candidate's phones / emails on file. |
no_match |
The supplied value for this slot does not match any of the candidate's phones / emails on file. |
not_used |
Dropped because it failed validation and ignore_errors=true. |
So if a request supplies phone and phone3, the response carries two independent outcomes (phone and phone3); phone2 and phone4 are omitted. Each slot is evaluated against the candidate's full phones (or emails) list, so the slot order in the request does not matter for matching.
Best-candidate selection
Candidates are ranked in three steps, applied in order.
- Strong-discriminator hits rank first. A candidate that produces an exact match against any of
phone,email, fulldob, or the fulladdress(the rollup atmatch) outranks any candidate that does not, regardless of how well the other candidate scores on names alone.dob: match_day_month_reversalalso counts as a strong-discriminator hit, but only when the candidate also hasfirst_name: match(oralias_match) ANDlast_name: match- without name corroboration, a reversed DOB is treated as a numeric coincidence and is not enough to elevate the candidate into the strong-discriminator group. - Exact last-name wins within the strong-discriminator group. Among candidates that tied on step 1, candidates with
last_name: matchrank above candidates withlast_name: fuzzy_match- a fuzzy last-name candidate never displaces an exact last-name candidate for the top slot. - Weighted score breaks remaining ties. Per-field weights are summed and the highest sum wins.
| Field | match | partial outcomes |
|---|---|---|
first_name |
20 | alias_match 16, partial_match 10, fuzzy_match 6 |
middle_name |
1 | alias_match 1, partial_match 1 |
last_name |
12 | fuzzy_match 8 |
dob |
10 | match_day_month_reversal 7, match_year 4 |
address |
8 | match_street 5, match_locality 3 |
phone |
4 | - |
email |
2 | - |
This calibration deliberately lets multiple identifiers outrank a stronger single name match. For example, within the strong-discriminator group, a candidate with first_name: alias_match (16) + dob: match (10) + phone: match (4) = 30 will beat a candidate with first_name: match (20) + phone: match (4) = 24.