Browse guides

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:

  1. 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.
  2. Score every candidate that comes back against the supplied fields.
  3. Return either the single best candidate, or every candidate ordered best-first if return_multiple_candidates: true was 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.

  1. Strong-discriminator hits rank first. A candidate that produces an exact match against any of phone, email, full dob, or the full address (the rollup at match) outranks any candidate that does not, regardless of how well the other candidate scores on names alone. dob: match_day_month_reversal also counts as a strong-discriminator hit, but only when the candidate also has first_name: match (or alias_match) AND last_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.
  2. Exact last-name wins within the strong-discriminator group. Among candidates that tied on step 1, candidates with last_name: match rank above candidates with last_name: fuzzy_match - a fuzzy last-name candidate never displaces an exact last-name candidate for the top slot.
  3. 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.