+For smaller scripts there is also a synchronous wrapper around the API. By
+using `NominatimAPI`, you get exactly the same interface using classic functions.
+
+The examples in this chapter will always show-case both
+implementations. The documentation itself will usually refer only to
+'Nominatim API class' when both flavours are meant. If a functionality is
+available only for the synchronous or asynchronous version, this will be
+explicitly mentioned.
+
+## Defining which database to use
+
+The [Configuration](../admin/Import.md#configuration-setup-in-env)
+section explains how Nominatim is configured using the
+[dotenv](https://github.com/theskumar/python-dotenv) library.
+The same configuration mechanism is used with the
+Nominatim API library. You should therefore be sure you are familiar with
+the section.
+
+There are three different ways, how configuration options can be set for
+a 'Nominatim API class'. When you have set up your Nominatim database, you
+have normally created a [project directory](../admin/Import.md#creating-the-project-directory)
+which stores the various configuration and customization files that Nominatim
+needs. You may pass the location of the project directory to your
+'Nominatim API class' constructor and it will read the .env file in the
+directory and set the configuration accordingly. Here is the simple search
+example, using the configuration from a pre-defined project directory in
+`/srv/nominatim-project`:
+
+!!! example
+ === "NominatimAPIAsync"
+ ``` python
+ import asyncio
+
+ import nominatim_api as napi
+
+ async def search(query):
+ async with napi.NominatimAPIAsync('/srv/nominatim-project') as api:
+ return await api.search(query)
+
+ results = asyncio.run(search('Brugge'))
+ if not results:
+ print('Cannot find Brugge')
+ else:
+ print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}')
+ ```
+
+ === "NominatimAPI"
+ ``` python
+ import nominatim_api as napi
+
+ with napi.NominatimAPI('/srv/nominatim-project') as api:
+ results = api.search('Brugge')
+
+ if not results:
+ print('Cannot find Brugge')
+ else:
+ print(f'Found a place at {results[0].centroid.x},{results[0].centroid.y}')
+ ```
+
+
+You may also configure Nominatim by setting environment variables.
+Normally Nominatim will check the operating system environment. Lets
+say you want to look up 'Brugge' in the special database named 'belgium' instead of the
+standard 'nominatim' database. You can run the example script above like this:
+
+```
+NOMINATIM_DATABASE_DSN=pgsql:dbname=belgium python3 example.py
+```
+
+The third option to configure the library is to hand in the configuration
+parameters into the 'Nominatim API class'. Changing the database would look
+like this:
+
+!!! example
+ === "NominatimAPIAsync"
+ ``` python
+ import asyncio
+ import nominatim_api as napi
+
+ config_params = {
+ 'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium'
+ }
+
+ async def search(query):
+ async with napi.NominatimAPIAsync(environ=config_params) as api:
+ return await api.search(query)
+
+ results = asyncio.run(search('Brugge'))
+ ```
+
+ === "NominatimAPI"
+ ``` python
+ import nominatim_api as napi
+
+ config_params = {
+ 'NOMINATIM_DATABASE_DSN': 'pgsql:dbname=belgium'
+ }
+
+ with napi.NominatimAPI(environ=config_params) as api:
+ results = api.search('Brugge')
+ ```
+
+When the `environ` parameter is given, then only configuration variables
+from this dictionary will be used. The operating system's environment
+variables will be ignored.
+
+## Presenting results to humans
+
+All search functions return full result objects from the database. Such a
+result object contains lots of details: names, address information, OSM tags etc.
+This gives you lots of flexibility what to do with the results.
+
+One of the most common things to get is some kind of human-readable label
+that describes the result in a compact form. Usually this would be the name
+of the object and some parts of the address to explain where in the world
+it is. To create such a label, you need two things:
+
+* the address details of the place
+* all names for the label adapted to the language you wish to use for display
+
+Again searching for 'Brugge', this time with a nicely formatted result:
+
+!!! example
+ === "NominatimAPIAsync"
+ ``` python
+ import asyncio
+
+ import nominatim_api as napi
+
+ async def search(query):
+ async with napi.NominatimAPIAsync() as api:
+ return await api.search(query, address_details=True)
+
+ results = asyncio.run(search('Brugge'))
+
+ locale = napi.Locales(['fr', 'en'])
+ for i, result in enumerate(results):
+ address_parts = result.address_rows.localize(locale)
+ print(f"{i + 1}. {', '.join(address_parts)}")
+ ```
+
+ === "NominatimAPI"
+ ``` python
+ import nominatim_api as napi
+
+ with napi.NominatimAPI() as api:
+ results = api.search('Brugge', address_details=True)
+
+ locale = napi.Locales(['fr', 'en'])
+ for i, result in enumerate(results):
+ address_parts = result.address_rows.localize(locale)
+ print(f"{i + 1}. {', '.join(address_parts)}")
+ ```
+
+To request information about the address of a result, add the optional
+parameter 'address_details' to your search:
+
+``` python
+>>> results = api.search('Brugge', address_details=True)
+```
+
+An additional field `address_rows` will set in results that are returned.
+It contains a list of all places that make up the address of the place. For
+simplicity, this includes name and house number of the place itself. With
+the names in this list it is possible to create a human-readable description
+of the result. To do that, you first need to decide in which language the
+results should be presented. As with the names in the result itself, the
+places in `address_rows` contain all possible name translation for each row.
+
+The library has a helper class `Locale` which helps extracting a name of a
+place in the preferred language. It takes a single parameter with a list
+of language codes in the order of preference. So
+
+``` python
+locale = napi.Locale(['fr', 'en'])
+```
+
+creates a helper class that returns the name preferably in French. If that is
+not possible, it tries English and eventually falls back to the default `name`
+or `ref`.
+
+The `Locale` object can be applied to a name dictionary to return the best-matching
+name out of it:
+
+``` python
+>>> print(locale.display_name(results[0].names))
+'Brugges'
+```
+
+The `address_row` field has a helper function to apply the function to all
+its members and save the result in the `local_name` field. It also returns
+all the localized names as a convenient simple list. This list can be used
+to create a human-readable output: