Security change on December 1, 2026: TLS 1.2 will become the minimum standard for 365 business Print Agent. Details and system requirements
365 business development
365 business Address Validation

Address Validation API

Codeunit 5523600 bdev.Address Validation API validates and completes a postal address. It offers two ways in:

  • a record of one of the supported standard tables. The app builds the address from the record, validates it, shows the user what changed if a dialog is allowed, and writes the result back to the record.
  • the validation buffer, a temporary bdev.Address Validation Buffer record. You fill it, you get the validated address back, and you decide what to do with it. This is the way to validate a table of your own.
Code
addressValidation: Codeunit "bdev.Address Validation API";

Validate(Record, Record)

Validates the address in the buffer and returns the validated address in a second buffer.

Code
[TryFunction] procedure Validate(address: Record "bdev.Address Validation Buffer" temporary; var validatedAddress: Record "bdev.Address Validation Buffer" temporary)
ParameterTypeDescription
addressRecord "bdev.Address Validation Buffer" temporaryThe address to validate.
validatedAddressRecord "bdev.Address Validation Buffer" temporaryThe validated and completed address.

Returns false when the validation failed; GetLastErrorText() then holds the reason. It is a [TryFunction], so nothing is raised to the user.

What goes in

Fill the address fields of the buffer. Address is mandatory, and so is City or Post Code - the app refuses to validate an address that has neither, because there is nothing to match against.

FieldTypeDescription
AddressText[100]Street and house number. Mandatory.
Address 2Text[50]Additional address information.
Post CodeCode[20]Mandatory unless City is filled.
CityText[30]Mandatory unless Post Code is filled.
CountyText[30]State, province or county.
Country/Region CodeCode[10]The country of the address.
Source TypeIntegerThe table id of the record the address belongs to. Optional; used to resolve the record in the result list.
Source System IDGuidThe SystemId of that record. Optional.

What comes back

Read the result from the fields of validatedAddress after the call - the record variable is positioned on the validated address:

FieldTypeDescription
AddressText[100]Street and house number, as the service returned them.
Post Code, City, CountyThe corrected values. County is cleared for countries that do not use one.
Country/Region CodeCode[10]The ISO alpha-2 code, cleared when no Country/Region record exists for it.
Match ScoreIntegerHow well the address matched.
Changes appliedText[100]A short summary of what the service changed.
Source Type, Source System IDCarried over from the address you passed in.

The <field> Changed flags, Status and Validation failed belong to the comparison dialog and the validation batch of the app. They are not filled by this overload - compare the values yourself to find out what changed.

Two results that look like nothing happened

When the address has already been validated on this tenant, the app answers from bdev.Address Data without calling the service: validatedAddress is then a copy of what you passed in, with no Match Score and no Changes applied. And when several candidates come back while a dialog is allowed, the user picks one - cancelling the dialog makes the call return false with an empty error text. Neither case is an error; both mean there is nothing to apply.

Address 2 is not part of the service result. When the service does not return a value for it, validatedAddress keeps the Address 2 you passed in, unchanged.

The buffer must stay temporary

bdev.Address Validation Buffer refuses to be written to the database - its insert, modify, delete and rename triggers raise an error on a non-temporary record. Declare it temporary, as in the signature.

Example: validating a table of your own

Code
procedure ValidateBrokerAddress(var broker: Record Broker) var address, validatedAddress : Record "bdev.Address Validation Buffer" temporary; addressValidation: Codeunit "bdev.Address Validation API"; begin address.Init(); address."Primary Key" := CreateGuid(); address.Address := broker.Address; address."Address 2" := broker."Address 2"; address."Post Code" := broker."Post Code"; address.City := broker.City; address.County := broker.County; address."Country/Region Code" := broker."Country/Region Code"; address."Source Type" := Database::Broker; address."Source System ID" := broker.SystemId; if (not addressValidation.Validate(address, validatedAddress)) then begin Session.LogMessage('BRK001', GetLastErrorText(), Verbosity::Warning, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', 'Broker'); exit; end; if (validatedAddress.Address = '') then exit; broker.Address := validatedAddress.Address; broker."Post Code" := validatedAddress."Post Code"; broker.City := validatedAddress.City; broker.County := validatedAddress.County; broker.Modify(true); end;

Whether to apply the result silently or to show it to the user is your decision - the buffer overload does not ask.

Validate(Record)

Validates the address of a record of a supported table and writes the result back to it.

Code
procedure Validate(var contact: Record Contact) procedure Validate(var customer: Record Customer) procedure Validate(var vendor: Record Vendor) procedure Validate(var altAddress: Record "Alternative Address") procedure Validate(var orderAddress: Record "Order Address") procedure Validate(var shipToAddress: Record "Ship-To Address")

Each overload takes the record by reference and modifies it in place. Unlike the buffer overload, these are not try functions: a failed validation raises an error unless the app suppresses it. Address 2 is not part of the service result; when the service does not return a value for it, the record keeps its own Address 2, unchanged.

When a dialog is allowed and the service returns more than one candidate, the user is asked to pick one. SetHideAddressSelection turns that off.

Employee, Resource and the documents

The app validates Resource, Employee, Sales Header and Purchase Header automatically on modify, but publishes no overload for them. Use the buffer overload if you need to validate one of those on demand.

GetValidationBuffer(Record, Record)

Fills the validation buffer from a record, so that you do not have to map the address fields yourself.

Code
procedure GetValidationBuffer(contact: Record Contact; var buffer: Record "bdev.Address Validation Buffer" temporary) procedure GetValidationBuffer(customer: Record Customer; var buffer: Record "bdev.Address Validation Buffer" temporary) procedure GetValidationBuffer(vendor: Record Vendor; var buffer: Record "bdev.Address Validation Buffer" temporary) procedure GetValidationBuffer(altAddress: Record "Alternative Address"; var buffer: Record "bdev.Address Validation Buffer" temporary)
ParameterTypeDescription
the recordRecordThe record whose address is transferred.
bufferRecord "bdev.Address Validation Buffer" temporaryThe buffer to fill.

Useful when you want the address of a standard record but want to run the validation yourself - to compare the result before applying it, for example.

AddressValidationEnabled(Integer)

States whether automatic address validation is switched on for a table.

Code
procedure AddressValidationEnabled(tableNo: Integer): Boolean
ParameterTypeDescription
tableNoIntegerThe table id to ask about.

Returns true when validation is enabled in Address Validation Setup, the current scope matches the session - UI only, Non-UI only or All - and the table is switched on.

Always false for your own table

The method answers for the tables the app validates itself and returns false for every other table id. It is not a switch you can extend: use a setup field of your own to decide whether your extension validates.

SetHideAddressSelection(Boolean)

Suppresses the dialog that lets the user pick between several candidate addresses.

Code
procedure SetHideAddressSelection(value: Boolean)
ParameterTypeDescription
valueBooleantrue hides the selection, false shows it.

Set it before calling Validate when your code runs without a user - in a job queue, in an API call, or in a test. The app sets it by itself when no GUI is allowed.

See also

Last modified on