Address suggestions
Search as a user types and display matching address records with structured fields.
Integrate address autocomplete, structured address fields, and address validation into your application using the AddressDesk REST API or JavaScript SDK.
AddressDesk provides two integration methods. Use the REST API when you want complete control over your user interface and HTTP requests. Use the JavaScript SDK when you want to attach autocomplete to an existing input or mount a complete address form into a page.
Search as a user types and display matching address records with structured fields.
Send address fields to the validation endpoint and process the returned result in your application.
Mount a ready-made address form with autocomplete, validation, feedback messages, and callbacks.
A suggestion match or address-index match does not, by itself, establish that an address is deliverable. Treat each validation status according to your backend's documented contract.
Set the API base URL and API key for your environment. The examples use shell variables so that credentials do not need to be embedded directly in every command.
Replace the example host with your deployed API URL and provide a key authorized to call the address endpoints.
API_BASE="http://localhost:8000"
ADDRESSDESK_API_KEY="YOUR_API_KEY"The suggest endpoint accepts a query, an optional country filter, and a result limit.
curl -G "$API_BASE/v1/addresses/suggest" \
--data-urlencode "q=mar" \
--data-urlencode "country=DE" \
--data-urlencode "limit=6" \
-H "Accept: application/json" \
-H "X-API-Key: $ADDRESSDESK_API_KEY"Submit the street, house number, postal code, city, and country code to the validation endpoint.
curl -X POST "$API_BASE/v1/addresses/validate" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-API-Key: $ADDRESSDESK_API_KEY" \
-d '{
"street": "Marienplatz",
"house_number": "1",
"postal_code": "80331",
"city": "München",
"region": "Bayern",
"country_code": "DE"
}'AddressDesk SDK requests send the API key using the X-API-Key request header. REST API calls should use the
same header.
X-API-Key: YOUR_API_KEY
Accept: application/json X-API-Keyapplication/json401 / 403The SDK adds Accept: application/json and X-API-Key automatically. Validation requests that use a
JSON body also set Content-Type: application/json.
/v1/addresses/suggestReturns address suggestions for the supplied query. The JavaScript SDK requests this endpoint when the configured input reaches the minimum character count.
| Parameter | Required | Description |
|---|---|---|
q | Yes | Text used to find address suggestions. |
country | No | Country filter, such as DE, US, or CA. |
limit | No | Maximum number of suggestions requested by the client. |
curl -G "$API_BASE/v1/addresses/suggest" \
--data-urlencode "q=mar" \
--data-urlencode "country=DE" \
--data-urlencode "limit=6" \
-H "Accept: application/json" \
-H "X-API-Key: $ADDRESSDESK_API_KEY" const params = new URLSearchParams({
q: 'mar',
country: 'DE',
limit: '6'
});
const response = await fetch(
API_BASE + '/v1/addresses/suggest?' + params,
{
headers: {
Accept: 'application/json',
'X-API-Key': API_KEY
}
}
);
if (!response.ok) {
throw new Error('Request failed: ' + response.status);
}
const payload = await response.json();
const addresses = payload.results || [];
console.log(addresses); The SDK reads an array from payload.results. Each result
should provide the fields needed by your UI and any configured form
field mappings.
{
"results": [
{
"id": "address-record-id",
"label": "Marienplatz 1, 80331 München, Germany",
"street": "Marienplatz",
"house_number": "1",
"postal_code": "80331",
"city": "München",
"region": "Bayern",
"country_code": "DE"
}
]
} | Field | Usage |
|---|---|
id | Identifier for an address record, if available. |
label | Human-readable address displayed in the suggestions menu. |
street | Street name. |
house_number | House or building number. |
postal_code | Postal or ZIP code. |
city | City or locality. |
region | State, province, or region, when provided. |
country_code | Country code, such as DE. |
The sample response illustrates the fields consumed by this SDK; the exact response is determined by your running API.
/v1/addresses/validateSubmit structured address data for validation. The dashboard example and the address form send a JSON object containing the address fields.
Accept: application/json
Content-Type: application/json
X-API-Key: YOUR_API_KEY {
"street": "Marienplatz",
"house_number": "1",
"postal_code": "80331",
"city": "München",
"region": "Bayern",
"country_code": "DE"
} curl -X POST "$API_BASE/v1/addresses/validate" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "X-API-Key: $ADDRESSDESK_API_KEY" \
-d '{
"street": "Marienplatz",
"house_number": "1",
"postal_code": "80331",
"city": "München",
"region": "Bayern",
"country_code": "DE"
}' const response = await fetch(
API_BASE + '/v1/addresses/validate',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-API-Key': API_KEY
},
body: JSON.stringify({
street: 'Marienplatz',
house_number: '1',
postal_code: '80331',
city: 'München',
region: 'Bayern',
country_code: 'DE'
})
}
);
if (!response.ok) {
throw new Error('Validation request failed: ' + response.status);
}
const result = await response.json();
console.log(result); The standalone SDK's generic validate() method defaults
to a body shaped like { "address": ... }. The
embedded AddressDeskAddressForm overrides this and
sends the flat address fields shown above. Configure validationBody or pass body when calling validate() if your backend requires a different schema.
Your backend determines the final validation response. The dashboard UI in this project expects a status, a message, and optional check details similar to this example.
{
"status": "matched_in_address_index",
"message": "Address matched in the address index.",
"missing_fields": [],
"checks": {
"required_fields": "passed",
"postal_code_format": "passed",
"address_index_match": "matched"
},
"postal_deliverability": "not_checked"
} | Status or field | Meaning in the dashboard |
|---|---|
matched_in_address_index | An exact address record was matched. |
not_found_in_address_index | No exact matching record was found. |
incomplete | One or more required address fields are missing. |
needs_review | The address needs further review. |
checks | Per-check outcomes, if returned by the API. |
postal_deliverability | Postal deliverability status, if your API provides it. |
The embedded form considers a result explicitly invalid only when valid === false or is_valid === false. A
response containing a different status does not automatically cause
the form to reject the address. Use onInvalidAddress and
your backend's response contract to implement stricter rules.
The SDK exports two classes: AddressAutocomplete for
attaching a suggestions menu to an existing input, and AddressDeskAddressForm for mounting a complete address
form inside a target element.
AddressAutocompleteAdds suggestions, keyboard navigation, selection, mapped fields, and validation requests to an existing input.
AddressAutocomplete.init(options)AddressDeskAddressFormMounts a complete form with autocomplete, validation, built-in feedback, configurable labels, and submission callbacks.
AddressDeskAddressForm.mount(options)Examples use ./addressdesk-sdk.js as a placeholder for
the file containing your SDK. Change the import to match your
project's actual file location or bundle output.
Provide an input for the search query and, optionally, other inputs to receive the selected address fields.
<label for="address-search">Address</label>
<input
id="address-search"
type="text"
autocomplete="off"
placeholder="Start typing an address"
/>
<label for="street">Street</label>
<input id="street" type="text" />
<label for="house-number">House number</label>
<input id="house-number" type="text" />
<label for="postal-code">Postal code</label>
<input id="postal-code" type="text" />
<label for="city">City</label>
<input id="city" type="text" />
<label for="country-code">Country code</label>
<input id="country-code" type="text" value="DE" /> import { AddressAutocomplete } from './addressdesk-sdk.js';
const autocomplete = AddressAutocomplete.init({
apiKey: 'YOUR_API_KEY',
apiUrl: 'https://your-api.example.com',
selector: '#address-search',
minChars: 2,
debounceMs: 220,
limit: 6,
fields: {
street: '#street',
house_number: '#house-number',
postal_code: '#postal-code',
city: '#city',
country: '#country-code'
},
onSelect(address) {
console.log('Selected address:', address);
},
onError(error) {
console.error('Address suggestions failed:', error);
}
}); selector or input.onSelect.destroy() when the input is removed or the integration is no longer needed.Map SDK output keys to elements with the fields option.
Each value can be a CSS selector or an element.
fields: {
street: '#street',
house_number: '#house-number',
postal_code: '#postal-code',
city: '#city',
region: '#region',
country_code: '#country-code'
} The SDK also recognizes the aliases houseNumber, postalCode, country, and countryCode when mapping a
selected record. If a field is not found or the record has no
corresponding value, that field is left unchanged.
Provide a fixed country code, a function returning the current country
code, or omit the country option and map fields.country to a country input.
country: 'DE' country: () => document.querySelector('#country-code').value When the country changes in a form, the value is read when a new suggestion request is built.
The autocomplete instance exposes validate() and validateSelected(). These methods return a Promise that
resolves with the decoded API response or rejects with an error.
const result = await autocomplete.validate(
{
street: document.querySelector('#street').value,
house_number: document.querySelector('#house-number').value,
postal_code: document.querySelector('#postal-code').value,
city: document.querySelector('#city').value,
country_code: document.querySelector('#country-code').value
},
{
body: {
street: document.querySelector('#street').value,
house_number: document.querySelector('#house-number').value,
postal_code: document.querySelector('#postal-code').value,
city: document.querySelector('#city').value,
country_code: document.querySelector('#country-code').value
}
}
);
console.log(result); const result = await autocomplete.validateSelected({
body: {
street: document.querySelector('#street').value,
house_number: document.querySelector('#house-number').value,
postal_code: document.querySelector('#postal-code').value,
city: document.querySelector('#city').value,
country_code: document.querySelector('#country-code').value
}
}); The call-level options path, method, and body override the instance defaults for that request.
The instance can also provide a reusable validationBody function.
const autocomplete = AddressAutocomplete.init({
apiKey: 'YOUR_API_KEY',
selector: '#address-search',
validationPath: '/v1/addresses/validate',
validationMethod: 'POST',
validationBody(address) {
return {
street: address.street,
house_number: address.house_number,
postal_code: address.postal_code,
city: address.city,
country_code: address.country_code
};
}
}); For a GET validation method, the SDK converts the
supplied body into query parameters. For other methods, it sends the
body as JSON. Confirm which method and body format your server
supports.
Use AddressDeskAddressForm.mount() to render a form in
an existing container. The form includes a search input, address
fields, an autocomplete menu, a submit button, feedback messages, and
AddressDesk branding.
<div id="address-form"></div> Start with the required connection settings, a target element, and an onSubmit callback. The SDK supplies the form fields,
autocomplete behavior, validation flow, and default labels.
import { AddressDeskAddressForm } from './addressdesk-sdk.js';
const API_KEY = 'YOUR_API_KEY';
const API_URL = 'https://your-api.example.com';
const addressForm = AddressDeskAddressForm.mount({
apiKey: API_KEY,
apiUrl: API_URL,
target: '#address-form',
buttonColor: '#5146E5',
onSubmit(address, validationResult) {
console.log(address);
}
}); import { AddressDeskAddressForm } from './addressdesk-sdk.js';
const addressForm = AddressDeskAddressForm.mount({
apiKey: 'YOUR_API_KEY',
apiUrl: 'https://your-api.example.com',
target: '#address-form',
country: 'DE',
title: 'Shipping address',
description: 'Find your address and confirm your details.',
submitLabel: 'Continue',
loadingLabel: 'Please wait…',
validateOnSubmit: true,
requireSelection: true,
onSelect(address) {
console.log('Address selected:', address);
},
onSubmit(address, validationResult) {
console.log('Address:', address);
console.log('Validation:', validationResult);
},
onInvalidAddress(result, address) {
console.error('Address rejected:', result, address);
},
onError(error) {
console.error('Form error:', error);
}
}); requireSelection is enabled, the user must select an item from the AddressDesk suggestions.validateOnSubmit is enabled, it sends the configured validation request.valid or is_valid to false, the form displays an error and calls onInvalidAddress.onSubmit(address, validationResult).onSubmit receives the address and null as the validation result.You can localize the form by providing your own text for the title,
description, field labels, button labels, and configurable status
messages. Set country: 'DE' to start with Germany as the
country code and filter address suggestions for Germany. The country
option does not translate the interface automatically; the strings
below provide the German wording.
import { AddressDeskAddressForm } from './addressdesk-sdk.js';
const API_KEY = 'YOUR_API_KEY';
const API_URL = 'https://your-api.example.com';
let addressForm = null;
try {
addressForm = AddressDeskAddressForm.mount({
apiKey: API_KEY,
apiUrl: API_URL,
target: '#address-form',
country: 'DE',
title: 'Lieferadresse',
description: 'Finde deine Adresse und bestätige deine Angaben.',
searchLabel: 'Adresse suchen',
searchPlaceholder: 'Tippe hier, z. B. Marienplatz',
streetLabel: 'Straße',
houseNumberLabel: 'Hausnummer',
postalCodeLabel: 'Postleitzahl',
cityLabel: 'Ort',
countryLabel: 'Ländercode',
submitLabel: 'Weiter zur Zahlung',
loadingLabel: 'Adresse wird überprüft…',
selectedMessage: 'Adresse ausgewählt. Prüfe deine Angaben, bevor du fortfährst.',
selectionRequiredMessage: 'Bitte wähle eine Adresse aus den Vorschlägen aus.',
validatingMessage: 'Adresse wird überprüft…',
successMessage: 'Adresse erfolgreich überprüft.',
buttonColor: '#734234',
minChars: 2,
debounceMs: 250,
limit: 6,
validateOnSubmit: true,
requireSelection: true,
onSelect(address) {
console.log('Ausgewählte Adresse:', address);
},
onValidation(result, address) {
console.log('Validierungsergebnis:', result);
console.log('Geprüfte Adresse:', address);
},
onInvalidAddress(result, address) {
console.warn('Adresse ist ungültig:', result, address);
},
onSubmit(address, validationResult) {
console.log('Adresse:', address);
console.log('Validierungsergebnis:', validationResult);
},
onError(error) {
console.error('AddressDesk-Fehler:', error);
},
onValidationError(error, address) {
console.error('Adressvalidierung fehlgeschlagen:', error, address);
}
});
} catch (error) {
console.error('AddressDesk konnte nicht initialisiert werden:', error);
} Set title or description to false to hide the corresponding text. The buttonColor option sets the form's --addressdesk-button-color CSS custom property.
The example localizes configurable labels and messages; built-in error
text that has no corresponding option remains in the SDK's default language.
| Option | Default | Description |
|---|---|---|
apiKey | Required | API key sent through the X-API-Key header. |
apiUrl | https://addressdesk.app | Base URL used for SDK requests. Trailing slashes are removed. Set this explicitly to use your own API deployment. |
suggestPath | /v1/addresses/suggest | Path used for autocomplete suggestions. |
validationPath | /v1/addresses/validate | Path used for validation requests. |
validationMethod | POST | Default validation HTTP method. |
validationBody | SDK default | Optional function that creates the validation request body from an address value. |
| Option | Default | Description |
|---|---|---|
selector / input | Required | CSS selector or element for the existing search input. |
fields | | Map of address keys to CSS selectors or DOM elements. |
country | From mapped field | Fixed country code or function returning the current country code. |
minChars | 2 | Minimum query length before searching. |
debounceMs | 220 | Delay after typing before making a suggestion request. |
limit | 6 | Number of suggestions requested from the API. |
onSelect | None | Called with the selected address record. |
onError | None | Called when suggestion requests fail. |
onValidation | None | Called with (result, address) after successful validation requests. |
onValidationError | onError | Called with (error, address) when validation fails. |
| Option | Default | Description |
|---|---|---|
target | Required | CSS selector or element where the form is mounted. |
country | DE | Initial country-code field value and country filter for address suggestions. For example, DE starts with Germany. This option does not translate the interface. |
validateOnSubmit | true | Validate before reporting a successful submission. |
requireSelection | true | Require the user to select a suggestion before submitting. |
title | Shipping address | Form title. Set to false to hide it. |
description | Built-in description | Introductory text. Set to false to hide it. |
buttonColor | #243d2c | Button color and form accent color. |
submitLabel | Continue | Button label when the form is not submitting. |
loadingLabel | Please wait… | Button label during submission. |
onSelect | None | Called with the selected suggestion record. |
onSubmit | None | Called with (address, validationResult) after a successful flow. |
onInvalidAddress | None | Called when the result explicitly marks the address invalid. |
onError | None | Called when form autocomplete or submission fails. |
onValidation | None | Called with the raw result and address after successful validation. |
onValidationError | Fallback behavior | Called for validation failures when configured. |
The form also accepts label and message overrides, including searchLabel, searchPlaceholder, streetLabel, houseNumberLabel, postalCodeLabel, cityLabel, countryLabel, selectedMessage, selectionRequiredMessage, validatingMessage, successMessage, and loadingLabel.
Use callbacks to update your application when an address is selected, validation completes, or a request fails.
const autocomplete = AddressAutocomplete.init({
apiKey: 'YOUR_API_KEY',
selector: '#address-search',
onSelect(address) {
console.log('Selected:', address);
},
onError(error) {
console.error('Suggestion error:', error);
},
onValidation(result, address) {
console.log('Validation result:', result);
console.log('Validated value:', address);
},
onValidationError(error, address) {
console.error('Validation failed:', error);
console.log('Submitted value:', address);
}
}); | Callback | Arguments | When it runs |
|---|---|---|
onSelect | address | A suggestion is selected. |
onError | error | A suggestion request or relevant form operation fails. |
onValidation | result, address | The validation endpoint returns a successful HTTP response. |
onValidationError | error, address | The validation request fails. |
onSubmit | address, validationResult | The embedded form's submission flow succeeds. |
onInvalidAddress | result, address | The embedded form receives valid: false or is_valid: false. |
The SDK adds DOM elements and event listeners. Destroy an instance when its input, form container, or page section is being removed.
autocomplete.destroy();
addressForm.destroy(); AddressAutocomplete.destroy() clears its timer, aborts
active requests, removes listeners, restores the original input to
its previous location, and removes the SDK wrapper. AddressDeskAddressForm.destroy() destroys its
autocomplete instance, removes the form submission listener, and
removes the mounted form.
Verify that the key is present, active, authorized for the
endpoint, and sent in the X-API-Key header.
The SDK provides a specific error for HTTP 401 and 403 responses.
Confirm that the input has the configured selector, the query
reaches minChars, the API returns a JSON object with
a results array, and the browser can reach the API.
Check the fields mappings and ensure the result
includes the relevant properties, such as house_number and postal_code.
Check the endpoint path, HTTP method, authentication, CORS configuration, and request body. Make sure the body matches the schema accepted by your backend.
With requireSelection: true, typing text alone does
not count as selecting an address. Select a suggestion from the
menu, or set requireSelection: false if your workflow
intentionally permits manual entry.
Configure the API server's CORS policy to permit the website
origin and required headers, including X-API-Key and Content-Type where
applicable.
The SDK runs in the browser and sends the API key with each request. Any key used there can be inspected by a visitor. Never use a private server-side secret as a browser key.
Use a dedicated key intended for client-side use, with the narrowest permissions and limits your backend supports. Apply server-side authentication, quotas, and monitoring as appropriate for your service.
Configure the SDK's apiUrl to your HTTPS API origin
in production. Avoid sending address data or credentials over
unencrypted HTTP.
Treat browser callbacks as user-interface integration points, not as a security boundary. Enforce authorization and server-side validation for business-critical operations.