Address Verification
Check that a person lives at an address, with a score, a corrected address and an OK, REVIEW or NOK decision
What it does
POST /address/verify checks a person (first name, last name, date of birth) against a postal
address. It returns a match level, a score from 0 to 100, the address in its confirmed form and a
decision: OK, REVIEW or NOK.
It answers "does this person live at this address", not "does this address exist". A valid address with the wrong person on it scores low.
Coverage. The service verifies addresses internationally. DE and AT are handled by the
primary postal source, which also corrects addresses. All other countries are handled by the
international source. Switzerland (CH) is a current limitation, see
Which source answers.
Base URL: see Environments. Authenticate as described in Authentication. The full schema is in the Umbrella API reference.
Request
{
"country": "DE",
"address": {
"street": "Musterstrasse",
"number": "12",
"zip": "10115",
"city": "Berlin"
},
"identity": {
"firstname": "Erika",
"lastname": "Mustermann",
"dob": "1985-04-12"
}
}| Field | Required | Description |
|---|---|---|
country | yes | Country code, two or three letters. Case and surrounding spaces do not matter. |
address.street | yes | Street name, without the number. |
address.number | yes | House or building number, as a string. Keep suffixes and flat numbers, for example 39/16. |
address.zip | yes | Post code, as a string. |
address.city | yes | Town or city. |
address.province | no | Accepted and ignored. |
identity.firstname | yes | First name. |
identity.lastname | yes | Last name. |
identity.dob | yes | Date of birth, YYYY-MM-DD. Do not send an empty value. |
Country handling. DE, AT and CH are recognised in both forms (DEU, AUT, CHE are
converted). Any other value is passed on as sent, so send a valid ISO 3166-1 code.
A key repeated anywhere in the JSON body is rejected with 400.
Known issue. The service does not check the body for missing fields. A request without a required field ends in a
500instead of a400. Send every required field.
Which source answers
Each request is answered by exactly one source, chosen by country. The routing is fixed and not configurable per account.
| Country | Source | Corrects the address | What you get |
|---|---|---|---|
DE, AT | Primary postal source (postal reference data with person records) | yes | addressStatus can be corrected; addressComponents holds the confirmed address |
CH | none | n/a | Current limitation: always NOK, score 0, noMatch. Switzerland is not verified at present. |
| every other country | International source (commercial identity and address data) | no | addressStatus is always unchanged; finalAddress and addressComponents repeat your input |
There is no fallback: if the selected source cannot be reached or fails, the call ends in a 500
and no second source is tried. Retry later; a failed call is not a NOK and says nothing about the
person.
Access is per account: an account without the service gets 403, and an account with a transaction
limit gets 429 once the limit is used.
Response
{
"inputAddress": "Musterstrasse 12, 10115, Berlin, DEU",
"correctedAddress": "Musterstraße 12, 10115, Berlin, DEU",
"finalAddress": "Musterstraße 12, 10115, Berlin, DEU",
"addressStatus": "corrected",
"addressComponents": {
"street": "Musterstraße",
"number": "12",
"zip": "10115",
"city": "Berlin",
"country": "DEU"
},
"matchQuality": "EXACT",
"score": 95,
"globalResult": { "overall": "OK", "totalScore": 95 },
"identity": { "fullName": "Erika Mustermann", "dob": "1985-04-12" },
"extendedMessage": "addressCorrected"
}| Field | Type | Meaning |
|---|---|---|
inputAddress | string | Your address as one line: street number, zip, city, country. For DE and AT the country is the three-letter code. |
correctedAddress | string | Same value as finalAddress. |
finalAddress | string | The address to store. For DE and AT it is the confirmed address from the source, which can differ from your input. Otherwise it equals inputAddress. Treat it as display text and use addressComponents for fields. |
addressStatus | string | corrected if the source changed any part of the address, else unchanged. |
addressComponents | object | street, number, zip, city, country. province is never returned. For DE and AT these are the confirmed values, and empty strings when no address could be confirmed. Otherwise they repeat your input. Pending verification: the country format in the confirmed address. |
matchQuality | string | See the table below. |
score | integer | 0 to 100. |
globalResult.overall | string | The decision: OK, REVIEW or NOK. |
globalResult.totalScore | integer | The same value as score. |
identity.fullName | string | firstname lastname as you sent it. |
identity.dob | string | Date of birth as you sent it. |
extendedMessage | string | Detail for the result, see Reason codes. Often an empty string. Do not branch on it. |
ERROR is listed in the schema as a value of globalResult.overall but the service never returns
it. Failures are HTTP errors.
matchQuality
| Value | Meaning |
|---|---|
EXACT | Person confirmed at the address (with or without a spelling correction) |
HOUSEHOLD_MATCH | Someone with the same surname lives at the address (DE, AT) |
STREET_MATCH | Person confirmed on the street, house number missing or different |
PARTIAL_MATCH | Person and address match, but the street is not confirmed (international source) |
CITY_MATCH | Person known in the city or post code, not at the address |
IDENTITY_MISMATCH | Address matches but the name or date of birth only partly does (international source) |
NO_MATCH | Not confirmed |
HOUSENUMBER_MATCH is in the schema and appears only in the sandbox test cases.
Decision logic
The decision is a fixed mapping from the source's result to a score, a matchQuality and
overall. There is no threshold you can configure, and no weighting of fields you can change.
overall | Score | What to do |
|---|---|---|
OK | 80 to 100 | Treat the address as verified. Store finalAddress. |
REVIEW | 50 | Send to a person, or ask the customer for a proof of address. Do not decline on this alone. |
NOK | 0 to 25 | Not verified. Decline the address, or ask for another proof. deceased and addressFakeSuspicion deserve a closer look than a plain noMatch. |
Scores are not continuous. Use overall for the decision and score to rank or report.
DE and AT: score by source result
| Source result | Score | matchQuality | overall | extendedMessage |
|---|---|---|---|---|
| Person confirmed at the address, nothing changed | 100 | EXACT | OK | empty |
| Person confirmed, address spelling or format corrected | 95 | EXACT | OK | addressCorrected |
| Same surname at the address | 80 | HOUSEHOLD_MATCH | OK | empty |
Person confirmed on the street (AT) | 80 | STREET_MATCH | OK | empty |
Address correct, building not found (DE) | 50 | CITY_MATCH | REVIEW | empty |
Person confirmed in the city (AT) | 50 | CITY_MATCH | REVIEW | cityMatch |
Person known in the data, not at this address (AT) | 25 | NO_MATCH | NOK | incorrectAddress |
Address wrong or ambiguous (DE) | 25 | NO_MATCH | NOK | noMatch |
Person lived here before (DE) | 25 | NO_MATCH | NOK | previousAddress |
Only the address found, person not found (AT) | 0 | NO_MATCH | NOK | identityNotFound |
Person not found (DE) | 0 | NO_MATCH | NOK | NoMatch |
Suspected fake address (DE) | 0 | NO_MATCH | NOK | addressFakeSuspicion |
| Person deceased | 0 | NO_MATCH | NOK | deceased |
| Address structurally defective, or no result | 0 | NO_MATCH | NOK | noMatch |
Source timed out (DE) | 0 | NO_MATCH | NOK | empty |
A timeout reported by the source is returned as a NOK with an empty extendedMessage and is not
distinguishable from a real non-match except by that empty message. Pending verification: whether
the source also fails the HTTP call in that case.
Other countries: name score times address score
The international source reports which parts matched. The service turns them into two sub-scores, multiplies them and maps the result.
Address score
| Matched | Address score | Message |
|---|---|---|
| Street, number, post code and city | 100 | |
| Street and number, post code, no city | 90 | NoCity |
| Street and number, city, no post code | 90 | NoPostCode |
| Street and city or post code, no number | 80 | |
| Number, city and post code, no street | 70 | NoStreet |
| City and post code only | 50 | cityMatch |
| Post code only | 50 | postcodeMatch |
| District only | 20 | districtMatch |
| County only, or province only | 15, 10 | |
| Nothing but a failed locality | 10 | localityMatch |
| Every address part failed | 0 |
Name score
| Matched | Name score | Message |
|---|---|---|
| First and last name, date of birth not contradicted | 100 | |
| First and last name, date of birth partly matches | 50 | dobPartial |
| First and last name, date of birth contradicted | 20 | dobFailedFull |
| Last name only, date of birth confirmed | 50 | lastNameOnly |
| Last name only, date of birth contradicted | 20 | dobFailedFull |
| First name only, date of birth confirmed | 50 | firstNameOnly |
| First name only, date of birth partly matches | 40 | dobPartial |
| First name only, date of birth contradicted | 0 | dobFailedFull |
| Neither name matched | 0 |
Combination. address score × name score ÷ 100 is rounded to the nearest ten (a value of exactly
100, 95 or 25 is kept), anything below 25 becomes 0, and anything between 25 and 50 becomes 25. The
result maps as follows.
| Result | Score returned | matchQuality | overall | extendedMessage |
|---|---|---|---|---|
| 100 | 100 | EXACT | OK | Exact Match |
| 90 | 90 | EXACT | OK | NoCity or NoPostCode |
| 80 | 80 | STREET_MATCH | OK | empty |
| 70 | 50 | PARTIAL_MATCH | REVIEW | NoStreet |
| 50, from a name message | 50 | IDENTITY_MISMATCH | REVIEW | the name message |
| 50, from the address | 50 | CITY_MATCH | REVIEW | cityMatch or postcodeMatch |
| 25 | 25 | NO_MATCH | NOK | see below |
| 0 | 0 | NO_MATCH | NOK | the name message, else noMatch |
On a 25 the message is an address-level label and can be one of the address messages above or a
plain word such as Full. Read it as informational. A full name match with a wrong date of birth
scores 20 on the name, which brings the result to 0 or 25 whatever the address: a verified address
does not rescue a contradicted date of birth.
Reason codes
extendedMessage explains a result. The code is stable enough to log and show to an agent. It is not
a contract for automation: new codes can appear and an empty string is normal, so branch on
globalResult.overall.
| Code | Seen on | Meaning | What to do |
|---|---|---|---|
| empty | all | No extra detail | Nothing |
addressCorrected | DE, AT, others | Spelling or format of the address was corrected | Store finalAddress |
Exact Match | others | Everything matched | Nothing |
NoCity, NoPostCode, NoStreet | others | That address part was not confirmed | Accept per overall; show to an agent on REVIEW |
cityMatch, postcodeMatch, districtMatch, localityMatch | AT, others | Match only at that level | Review |
incorrectAddress | AT, others | Person known, address does not fit | Ask for the current address |
previousAddress | DE | Person lived at this address before | Ask for the current address |
identityNotFound | AT | Address found, person not found | Review the name and date of birth, ask for proof |
noMatch, NoMatch | all | Nothing usable found | Decline or ask for another proof |
addressFakeSuspicion | DE | Address suspected to be invented | Decline and escalate |
deceased | DE, AT | Person recorded as deceased | Decline and escalate |
dobPartial | others | Date of birth matches only in part | Review; check for a typo |
dobFailedFull | others | Date of birth contradicts the record | Check the date, then decline |
lastNameOnly, firstNameOnly | others | Only one name part matched | Review |
The schema also lists skippedDOB; the service never sets it.
Errors
Error bodies are JSON. Their shape varies by cause.
| Status | When | Body |
|---|---|---|
400 | A key is repeated in the JSON body | {"status": false, "message": "Duplicate keys found: ..."} |
401 | No bearer token | {"status": false, "message": "Missing AuthorizationToken"} |
403 | Account not enabled for the service | {"status": false, "message": "Access denied: You cannot access this product. Please contact support."} |
429 | Transaction limit used up | {"status": false, "message": "Transaction limit exceeded", "limit": n, "remaining": 0} |
500 | Source failed, or a required field is missing | {"status": false, "error": "..."} |
Pending verification: how an invalid or expired token is reported. The service can answer 500 with
the token library's message instead of 401.
Sandbox
The sandbox does not call any source. It answers from nine fixed test cases and returns the same response shape. It is authenticated like production.
A request is matched on all of country, street, number, zip, city, the full name and dob,
exactly as written. DEU, AUT and CHE are accepted for the country.
| # | Country | Street and number | Post code, city | Name | Date of birth | Result |
|---|---|---|---|---|---|---|
| 1 | AT | Kampgasse 9 | 3492 Etsdorf | Joe Cardholder | 1970-12-01 | OK, 100, EXACT, unchanged |
| 2 | AT | Billrothstr. 39/16 | 1190 Wien | Wilma Wohndtort | 1998-03-05 | OK, 95, EXACT, corrected to Billrothstraße 39/16 |
| 3 | AT | Billrothstraße 39 | 1190 Wien | Wilma Wohndtort | 1998-03-05 | OK, 80, HOUSENUMBER_MATCH |
| 4 | AT | Billrothstraße 3/16 | 1190 Wien | Wilma Wohndtort | 1998-03-05 | REVIEW, 50, CITY_MATCH |
| 5 | AT | Döblinger Hauptstraße 4/1 | 1190 Wien | Wilma Wohndtort | 1998-03-05 | REVIEW, 50, CITY_MATCH |
| 6 | DE | Edlinger Hauptstraße 12/7 | 12345 Berlin | Hans Dampf | 1998-03-05 | NOK, 25, NO_MATCH |
| 7 | CH | Seegasse 1 | 1000 Lachen/Zürich | Hubert Spion | 1901-01-01 | NOK, 0, NO_MATCH |
| 8 | AT | Kampgasse 9 | 3496 Etsdorf | Joe Cardholder | 1970-12-01 | OK, 95, EXACT, post code corrected to 3492 |
| 9 | AT | Kampgasse 9 | 3492 Etsdorf | Jane Cardholder | 1970-12-01 | OK, 80, HOUSEHOLD_MATCH |
These are test records, not real customers. Send firstname and lastname as the two words of the
name.
Differences from production:
extendedMessageholds the case description, for exampleFull matchorNo match, not a reason code.addressStatusand the address lines come from the test case. The country in them is two letters (AT), not three.- A request that matches no case still returns
200, with{"success": false, "message": "Test Case Mismatch (Case ID: ...)"}listing which fields differ from the closest case. The message is a string, not the response shape above. Check forsuccessbefore reading the fields. If nothing is close, the message starts withCritical Failure. - Only
AT,DEandCHhave test cases. There is no case for other countries, and none that returnsHOUSEHOLD_MATCHorNO_MATCHthrough the international source.
Mock
This portal serves canned answers that need no token and no account, so you can build a client first. They are not the sandbox: the body is not computed from your request.
POST /mock/api/services/address/verify returns the OK example above. Add ?scenario=review for
a REVIEW and ?scenario=no-match for a NOK. ?scenario=bad-request and
?scenario=unauthorized return the error shapes from the schema. See Environments.
Worked examples
OK
The request and response at the top of this page: Germany, address corrected, score 95.
REVIEW
Spain, answered by the international source. City and post code match, the street does not.
{
"inputAddress": "Calle Ejemplo 5, 28001, Madrid, ES",
"correctedAddress": "Calle Ejemplo 5, 28001, Madrid, ES",
"finalAddress": "Calle Ejemplo 5, 28001, Madrid, ES",
"addressStatus": "unchanged",
"addressComponents": {
"street": "Calle Ejemplo",
"number": "5",
"zip": "28001",
"city": "Madrid",
"country": "ES"
},
"matchQuality": "CITY_MATCH",
"score": 50,
"globalResult": { "overall": "REVIEW", "totalScore": 50 },
"identity": { "fullName": "Juan Ejemplo", "dob": "1990-07-23" },
"extendedMessage": "cityMatch"
}NOK
Same request, but nothing matched.
{
"inputAddress": "Calle Ejemplo 5, 28001, Madrid, ES",
"correctedAddress": "Calle Ejemplo 5, 28001, Madrid, ES",
"finalAddress": "Calle Ejemplo 5, 28001, Madrid, ES",
"addressStatus": "unchanged",
"addressComponents": {
"street": "Calle Ejemplo",
"number": "5",
"zip": "28001",
"city": "Madrid",
"country": "ES"
},
"matchQuality": "NO_MATCH",
"score": 0,
"globalResult": { "overall": "NOK", "totalScore": 0 },
"identity": { "fullName": "Juan Ejemplo", "dob": "1990-07-23" },
"extendedMessage": "noMatch"
}For a NOK from DE or AT, addressComponents can hold empty strings and finalAddress can be
made of separators only, because no address was confirmed. Fall back to inputAddress.
Limits
- Per-account choice of source and a second-source fallback are not available at present.
- Pending verification: behaviour of the production routes against a live source. This page is written from the service code, not from live calls.