In order to prevent fraud and duplicate processing, it is often necessary to match a document’s sender with the internal database of approved vendors. Master Data Hub is the default Rossum extension for this purpose. Rossum’s AI engines extract addresses from documents as a single value. It is often necessary to split those addresses into individual values such as city, street, and zip code, and compare these individual values with vendor management system database.
The Address Prefilling extension allows you to extract address data from your documents. It transforms a series of words and numbers that represent an address into values that represent the individual parts of that address. You can then map these values into the predefined fields of your schema.
At the core of this extension is the open-source NLP library called “libpostal.” This library is described in detail here. Additionally, this extension uses an API built on top of the libpostal library. The code can be found here.
It should be noted that this extension is not meant to validate or look up addresses.
Configuration example
The sample configuration below illustrates the use of configuration parameters to control transformations and mapping.
Input address:
Royal Suites, Floor 8, 81 Manchester Road NOTTINGHAM NG49 9BLLibpostal output:
{
'house': 'royal suites',
'level': 'floor 8',
'house_number': '81',
'road': 'manchester road',
'city': 'nottingham',
'postcode': 'ng49 9bl'
}/
Configuration sample:
{
"rules": [
{
"queue_ids": [
123, 124
],
"disable_user_updates" : true,
"source_address_schema_id": "sender_address",
"field_mappings": [
{
"target_schema_id": "sender_address_city",
"address_parts": [
"city"
],
"case": "first_letter"
},
{
"target_schema_id": "sender_address_state",
"address_parts": [
"state"
],
"case": "first_letters"
},
{
"target_schema_id": "sender_address_line_1",
"address_parts": [
"po_box"
]
},
{
"target_schema_id": "sender_address_line_2",
"address_parts": [
"house",
"category",
"unit",
"level"
],
"separator": ",",
"case": "first_letters"
},
{
"target_schema_id": "sender_address_street",
"address_parts": [
"road"
],
"case": "first_letter"
},
{
"target_schema_id": "sender_address_country",
"address_parts": [
"country"
],
"case": "first_letters"
},
{
"target_schema_id": "sender_address_postal_code",
"address_parts": [
"postcode"
],
"case" : "upper"
}
]
}
]
}The following is the result of applying the rule shown above (simplified to make it easier to read):
sender_address_city : "Nottingham",
sender_address_state : "",
sender_address_line_1: "",
sender_address_line_2: "Royal suites,Floor8",
sender_address_street: "Manchester road",
sender_address_country: "",
sender_address_postal_code: "NG49 9BL"These values are then stored into the relevant schema fields of the document’s annotation data.
Setting up the extension
To install and set up the extension, follow these steps:
Step 1: Prepare your queues and schemas
First, identify the queue(s) with the documents that require Address Prefilling. Next, identify the schema IDs for the fields that contain addresses and those that will be used to store the parsed address elements.
If the used schema doesn’t yet contain fields for individual address parts, create those fields. For information on schema editing refer to this guide.
Sample schema fields
Following fields definition can be used for specifying the usual address fields. Alternatively, here is a complete schema example based on the Rossum default schema for EU invoices which can be copied and pasted in the schema editor.
{
"rir_field_names": [],
"constraints": {
"required": false
},
"default_value": null,
"category": "datapoint",
"id": "sender_address_city",
"label": "Vendor City",
"hidden": false,
"type": "string",
"can_export": true
},
{
"rir_field_names": [],
"constraints": {
"required": false
},
"default_value": null,
"category": "datapoint",
"id": "sender_address_state",
"label": "Vendor State",
"hidden": false,
"type": "string",
"can_export": true
},
{
"rir_field_names": [],
"constraints": {
"required": false
},
"default_value": null,
"category": "datapoint",
"id": "sender_address_line_1",
"label": "Vendor Line 1",
"hidden": false,
"type": "string",
"can_export": true
},
{
"rir_field_names": [],
"constraints": {
"required": false
},
"default_value": null,
"category": "datapoint",
"id": "sender_address_line_2",
"label": "Vendor Line 2",
"hidden": false,
"type": "string",
"can_export": true
},
{
"rir_field_names": [],
"constraints": {
"required": false
},
"default_value": null,
"category": "datapoint",
"id": "sender_address_street",
"label": "Vendor Street",
"hidden": false,
"type": "string",
"can_export": true
},
{
"rir_field_names": [],
"constraints": {
"required": false
},
"default_value": null,
"category": "datapoint",
"id": "sender_address_country",
"label": "Vendor Country",
"hidden": false,
"type": "string",
"can_export": true
},
{
"rir_field_names": [],
"constraints": {
"required": false
},
"default_value": null,
"category": "datapoint",
"id": "sender_address_postal_code",
"label": "Vendor Postal Code",
"hidden": false,
"type": "string",
"can_export": true
},
{
"rir_field_names": [],
"constraints": {
"required": false
},
"default_value": null,
"category": "datapoint",
"id": "sender_address_house_number",
"label": "Vendor House Number",
"hidden": false,
"type": "string",
"can_export": true
},Step 2: Activate Address Prefilling in the Rossum Store
In order to activate Address Prefilling, follow these steps:
From the main menu, click Extensions to access the Rossum Store page.
Once in the Rossum Store, Address Prefilling should be visible, or you can use the search bar.
Click the Address Prefilling extension tile.
Click Add.



Step 3: Specify the queue(s) where the extension is going to be used
Once in the extension settings, scroll down to Queues and select the queue(s) for which the extension should be used.

Step 4: Set up the actions and transformations
The extension is configured through the configuration field in the UI or by using the settings attribute of the hook API object. The configuration is in JSON format (see the description of the available parameters below).
This configuration consists of rules that define a mapping and possible transformations (more on that later) between address parts and schema fields. Each rule has:
A list of queue IDs in order to use a single instance of the extension for all queues
Source/target field mappings
Letter case transformation

The full list of available parameters is shown below:
Root | Param name | Mandatory | Description |
|---|---|---|---|
rules | yes | A list of rules to be executed by the extension. Below is a description of the rules parameters. | |
rules | queue_ids | no | The queue IDs for which the rule is enabled, provided the extension is attached to the queue in the extension configuration. |
rules | source_address_schema_id | yes | Schema_id of a field containing the original address value. |
rules | disable_user_updates | no | Default false. If set to true user updates of any field_mappings.target_schema_id triggers the rule to update all of the fields again. Essentially prevents user updates of fields listed in field_mappings. |
rules | field_mappings | yes | A list of mappings of the libpostal values and annotation fields. |
field_mappings | target_schema_id | yes | The schema ID into which the individual value(s) will be placed. |
field_mappings | address_parts | yes | List of field(s) – address part(s) – to be mapped into target_schema_id. Possible values are listed below. |
field_mappings | separator | no | Default “ “. If address_parts contains multiple values, separator is used to concatenate the values. |
field_mappings | case | no | This extension does not preserve the original letter case of the address. If case is not set, lower case will be used. Options:upper – all characters are converted to upper case first_letter – the first letter of the first word is converted to upper case.first_letters – the first letter of each word is converted to upper case. |
Possible address values
The possible values of address_parts as listed in the documentation of the libpostal library can be found here. These include:
house: a venue’s name, such as the “Brooklyn Academy of Music” and a building’s name, such as the “Empire State Building”
category: for category queries such as “restaurants”.
near: phrases like “in”, “near”, etc. used after a category phrase to help with parsing queries like “restaurants in Brooklyn”
house_number: usually refers to the external (street-facing) building number. This may be a compound, hyphenated number that includes a block or apartment number (as in Japan). libpostal will just call it house_number for simplicity.
road: Street name(s).
unit: An apartment, unit, office, lot, or other secondary unit designator.
level: Expressions indicating a floor number e.g. “3rd Floor”, “Ground Floor”, etc.
staircase: Numbered/lettered staircase.
entrance: Numbered/lettered entrance.
po_box: A non-physical (mail-only) box normally found at a post office.
postcode: Postal codes used for mail sorting.
suburb: An unofficial neighbourhood name such as “Harlem”, “South Bronx”, “Crown Heights.”
city_district: These are usually districts or boroughs in a city that are intended for some official function, e.g. “Brooklyn” or “Hackney” or “Bratislava IV.”
city: Any human settlement including cities, towns, villages, hamlets, localities, etc.
island: A named island, such as “Maui.”
state_district: Usually a second-level administrative division or county.
state: The first-level administrative division. Scotland, Northern Ireland, Wales, and England in the UK are mapped to “state” as well (convention used in OSM, GeoPlanet, etc.)
country_region: A region within a country that is not a part of an organised political system.
country: Sovereign nations and their dependent territories; anything with an ISO-3166 code.
world_region: Currently only used for adding “West Indies” after the country name, a pattern commonly seen in English-speaking Caribbean countries, such as “Jamaica, West Indies”.
Address Prefilling: Cleaning Unclean Address Data
Overview
The Address Prefilling Extension works best when address data is clean and consistently formatted. In some cases, the raw address value captured by OCR (AI) extraction contains formatting artifacts (newlines, abbreviations, special characters) that prevent the extension from correctly splitting the address into its individual components:
recipient_address_roadrecipient_address_cityrecipient_address_postcode
When this happens, no technical error is raised — the hook finishes with status 200 — but the output fields are incomplete or incorrect.
Common problematic patterns include:
UK county abbreviations between the city and postcode (e.g. LEICS, CAMBS, STAFFS)
Addresses with embedded newlines (
\n)OCR artifacts: digits substituted for letters (e.g.
L0NDON,5TAFFORD)Non-address content on preceding lines (ATTN:, department names, page headers)
Address parser: Senzing libpostal models
The Address Prefilling Extension uses libpostal for address parsing. The deployed instance runs Senzing's retrained models (Senzing/libpostal-data), which are rebuilt from recent OpenStreetMap and OpenAddresses data and improve on the original openvenues models.
Overall accuracy improvement: 4.25% globally (libpostal failure rate 21.33% → Senzing 17.08%, across 12,949 addresses from 88 countries). See the full parsing comparison table for per-country detail.
Notable improvements with the Senzing models relevant to common Rossum use cases:
Netherlands — failure rate reduced to 0%
United Kingdom — improved postcode extraction, particularly for addresses with county abbreviations
Denmark, Norway — failure rate reduced to 0%
A small number of countries show reduced accuracy compared to the original models (Guatemala, Latvia, Réunion). If you are processing addresses from those regions, test carefully before relying on the parser output.
Option 1: Pre-clean with a Formula Field
Use a Formula Field to normalize the raw address value before it is consumed by the Address Prefilling Extension.
Create a formula field (e.g. sender_address_clean) that transforms the original address field. Configure the Address Prefilling Extension to use this cleaned field as its input.
Recommended for: predictable, rule-based artifacts — newlines and UK county abbreviations.
Example Formula (UK Addresses)
import re
address = field.sender_address or ''
# 1. Replace newlines with spaces
address = address.replace('\n', ' ')
# 2. Remove UK county abbreviations that appear between the city and postcode.
# These abbreviations confuse road/city field splitting even with the updated parser.
pattern = (
r'\b(STAFFS|MIDDX|WARKS|BERKS|HERTS|LANCS|YORKS|NOTTS|LEICS|LINCS|'
r'CAMBS|OXON|WILTS|WORCS|GLOS|BUCKS|BEDS|NORTHANTS|SHROPS|DERBYS)'
r'\s+([A-Z]{1,2}\d{1,2}[A-Z]?\s*\d[A-Z]{2})\s*$'
)
address = re.sub(pattern, r'\2', address, flags=re.IGNORECASE)
return address
NOTE
&in road names (e.g. Dog & Gun Lane) no longer needs to be replaced with AND. The updated Senzing parser handles ampersands correctly.
Before / After Examples
Raw value | Cleaned value |
|---|---|
|
|
|
|
|
|
|
|
Option 2: Pre-clean with a Reasoning Field
Use a Reasoning Field when the address contains artifacts that a formula cannot reliably handle — particularly OCR errors, non-address lines mixed into the address block, or ambiguous content that requires interpretation.
Recommended for: OCR-corrupted characters, ATTN/department lines, mixed content where the address boundary is unclear.
⚠️ IMPORTANT: REASONING FIELDS ARE NON-DETERMINISTICUnlike Formula Fields, Reasoning Fields use a language model and do not guarantee identical output for identical input. The same address may be cleaned differently across runs. More critically, the model may silently make incorrect "corrections" — misidentifying a valid part of the address as an OCR error, removing content it incorrectly judges as non-address, or subtly altering street names, numbers, or postcodes.
Before using a Reasoning Field for address cleaning:
Test the prompt against a representative sample of real addresses from the customer's documents
Always verify the cleaned output by testing it against the libpostal API (see Testing section below)
Keep the original AI-extracted field intact — never overwrite it with the cleaned value
Consider using a Formula Field for the predictable rules first, and only routing to a Reasoning Field for genuinely ambiguous cases
Field setup
Setting | Value |
|---|---|
Field ID |
|
Field type | Reasoning |
Relevant fields |
|
Label | Address (cleaned) |
Description | Single-line address cleaned for parsing. Remove non-address lines, fix OCR artifacts, flatten to one line. |
The Label and Description give the model context about the expected output before it reads your instructions. Keep them concise and outcome-focused.
If there are still some issues with the reasoning field output, you can use prompt like below to fine-tune you outputs.
Example Prompt
Clean the value of sender_address into a single-line address string suitable for address parsing.
Do not extract individual components — return the full address as one clean string.
Apply the following corrections:
1. Replace newlines, line breaks, or semicolons with a single space.
2. Remove any content that is clearly not part of the address: department names,
attention lines (ATTN:, C/O), document headers, page numbers, or company names
that appear on a separate line before the street address.
3. Fix obvious OCR character errors using surrounding context.
Common substitutions: digit 0 mistaken for letter O (and vice versa),
digit 1 or lowercase l mistaken for letter I, digit 5 mistaken for letter S,
digit 8 mistaken for letter B.
Only correct when the intended character is unambiguous from context
(e.g. "L0NDON" → "LONDON", "5TAFFORD" → "STAFFORD").
4. Remove UK county abbreviations that appear between the city and the postcode
(e.g. LEICS, STAFFS, CAMBS, MIDDX, WARKS, BERKS, HERTS, LANCS, YORKS, NOTTS,
LINCS, OXON, WILTS, WORCS, GLOS, BUCKS, BEDS, NORTHANTS, SHROPS, DERBYS).
5. Preserve the rest of the address exactly as-is. Do not translate, reformat,
reorder, or expand abbreviations beyond the above rules.
Examples:
sender_address: "WHETSTONE FOOD STORE\nDOG & GUN LANE\nLEICESTER\nLEICS\nLE8 6NA"
→ "WHETSTONE FOOD STORE DOG & GUN LANE LEICESTER LE8 6NA"
sender_address: "ATTN: ACCOUNTS\n132 SILKMORE LANE\nSTAFFORD\nSTAFFS\nST17 4JD"
→ "132 SILKMORE LANE STAFFORD ST17 4JD"
sender_address: "10 DOWNING STREET\nL0ND0N\nSW1A 2AA"
→ "10 DOWNING STREET LONDON SW1A 2AA"
sender_address: "Page 1 - Invoice\n123 Main Street\nNew York\nNY 10001"
→ "123 Main Street New York NY 10001"
sender_address: "Unter den Linden 1\n10117 Berlin"
→ "Unter den Linden 1 10117 Berlin"
If sender_address is empty or contains no recognisable address-like content, return an empty string.
When to use Reasoning instead of Formula
Situation | Formula | Reasoning |
|---|---|---|
Replace \n with space | ||
Remove county abbreviations via regex | ||
Fix OCR digit/letter confusion | ||
Strip ATTN/department lines | ||
Remove document headers mixed into address | ||
Ambiguous multi-line blocks (address vs. company name) |
You can also stack both: use a Formula Field to handle the deterministic rules first, then feed its output into a Reasoning Field for the remaining ambiguous cases.
Testing Address Detection with Libpostal
Before adjusting any field, verify how libpostal parses a given address string by calling the API directly:
curl -X POST -d '{"query": "100 main st buffalo ny"}' https://<CLUSTER_NAME>/ext/libpostal/api/v1/parserOutput:
[{"label":"house_number","value":"100"},{"label":"road","value":"main st"},{"label":"city","value":"buffalo"},{"label":"state","value":"ny"}]Replace the query value with your cleaned address to verify the result. If road, city, or postcode is missing or absorbed into house, the address needs further cleaning before the extension will work correctly.
Notes
Replace
field.sender_addressandrecipient_address_*with your actual field IDs.Extend the county abbreviation list in the formula/prompt as needed for your customer's region.
Both approaches keep the original AI-extracted value intact and add a clean intermediate field — making it easy to debug and adjust.
This guide focuses on UK addresses. For other locales, different normalization rules may apply.
This software and documentation uses the following third-party open source libraries and parts of the original documentation:
libpostal
The MIT License (MIT) - Copyright (c) 2015 Openvenues
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Libpostal-rest
The MIT License (MIT) - Copyright (c) 2021 John Longanecker
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
The software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non-infringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.