Address selection guide
Baltic address catalogue (Estonia, Latvia and Lithuania):
look up an address by ID, fetch the parent object chain and browse the address tree as
cascade selections. The country is selected with c=ee|lv|lt (Estonia by default).
https://pump.elemroot.com/Gazetter. The service always returns JSON and every
response includes the success field.
Endpoints and routing
Base: https://pump.elemroot.com/Gazetter. Each sub-service has its own path:
| Path | Purpose | Parameters |
|---|---|---|
/layer/getDescription/ | Full address by ID | id |
/layer/getFillInfo/ | Parent object chain | id |
/layer/currentLayer/ | Address list at level | l, p, g, c |
All three endpoints additionally accept the country parameter c
(ee / lv / lt, default ee): see the countries chapter.
The same can be called with the layer parameter:
https://pump.elemroot.com/Gazetter/?key=docs_382d376eaaa6d004b7b93b7d&layer=getdescription&id=3069760
Values: getdescription, getfillinfo, currentlayer. Without layer the service returns {"success": false}.
/layer/currentLayer/) is case-sensitive: /layer/CURRENTLAYER/ returns 404. The parameter form (?layer=…) is case-insensitive. A trailing slash is not required in either.Both forms also accept POST (application/x-www-form-urlencoded). NB: the key must still be in the URL, not only in the form body.
Countries: Estonia, Latvia, Lithuania (parameter c)
The gazetteer covers three countries. The country is selected with the c
parameter: ee (default), lv or lt; an unknown
value behaves like ee. The parameter applies to all three endpoints and
IDs are country-scoped: the same id means a different
object in a different country, so pass c also to
getDescription / getFillInfo requests.
curl "https://pump.elemroot.com/Gazetter/layer/currentLayer/?key=docs_382d376eaaa6d004b7b93b7d&l=1&c=lv"
Response (shortened)
{
"success": true,
"addressList": [
{ "id": 1100016630, "nimi": "Aizkraukles nov." },
{ "id": 1100003028, "nimi": "Jelgava" },
{ "id": 1100003003, "nimi": "Rīga" }
]
}
Levels per country
The level scale l=1–6 is shared, but the content differs and the levels are
not equivalent across countries. The key difference: level 1 in Latvia and Lithuania is
the municipality, while in Estonia the municipality is level 2; Latvia abolished its districts
in 2009 and the Lithuanian apskritis is not part of the official address, so neither country has a county
level. The same applies at level 2: the Latvian pagasts and the Lithuanian
seniūnija are not municipalities but territorial subdivisions of one.
l | Estonia | Latvia | Lithuania |
|---|---|---|---|
1 | County | Novads / valstspilsēta | Savivaldybė |
2 | Municipality | Pagasts / town of a novads | Seniūnija (absent in cities) |
3 | Settlement | Ciems | Gyvenamoji vietovė (miestas / kaimas / miestelis / viensėdis) |
4 | Street / small place | Iela | Gatvė |
5 | House | Māja (number or name) | Namas |
6 | Flat | Dzīvoklis | Butas |
When building a form, mind the country quirks:
- The Lithuanian seniūnija is level 2: as in the official rural
address of Registrų centras. The cascade is
l=1savivaldybė →l=2seniūnija →l=3settlement. Cities have no seniūnija (Vilnius, Kaunas, Klaipėda and others: the register itself does not put one in a city address): therel=2is empty and the settlement comes straight froml=3&p=<savivaldybė>. The seniūnija comes in thegetDescriptionfieldA2_NIMI. When one seniūnija holds two settlements with the same name, the name carries the RC type abbreviation, e.g."Lapkalnis (k.)"and"Lapkalnis (vs.)". - Latvian state cities (Rīga, Jelgava, …) sit at level 1; they have neither
level 2 nor level 3: the streets come straight from the city
(
l=4&p=<pilsēta>; Rīga has 1 811 of them). A Rīga city district (priekšpilsēta / rajons) is not an address level and is not returned: VZD keeps it as an attribute of the object and the official Latvian address does not contain it. The samel=4&g=pattern works for towns of a novads (level 2). - Houses without a street (both countries, e.g. named houses in a ciems):
l=5&g=<settlement>: exactly like Estonian farms. - The general technique for skippable levels: after each pick, probe ALL
deeper levels (
l+1…6) and show the ones that answersuccess: true. Probing only the next three is not enough: a Latvian state city holds both streets (l=4) and houses directly (l=5), so the jump can span four levels. An empty deeper level is not a dead end: query them all and mark the skipped level for the user (this is what the example app does).
IDs and fields in LV/LT responses
- An Estonian
idis theAADRESS_ID(as before). A Latvian / Lithuanianidis level prefix×10⁹ + the national register code (LV: VZD kods; LT: Registrų centras); e.g. Jelgava1100003028(level 1, code 100003028). IDs are stable and safe to store; the plain register code is available in theKOODAADRESSfield. - A
getDescriptionLV/LT response uses the sameA1_NIMI…A8_NIMIcomponent frame (A4_NIMIandA6_NIMIare alwaysnullthere;A2_NIMIcarries the Latvian pagasts/pilsēta and the Lithuanian seniūnija); the Estonia-specific fields (A*_EHAK,A_STAATUS_ID,A5_NIMI_INIT) are absent. - Lists are ordered by the national alphabet (Jõgeva before Järva, Põlva before Pärnu; LV/LT diacritics sort correctly).
- Geocoder ids and gazetteer ids convert into each other. The
AADRESS_IDreturned by geocoding (jgc_rest,gl=lv/gl=lt) is the national register code without a level prefix, while the gazetteeridcarries one:id = level prefix × 10⁹ + AADRESS_ID. Prefixes: 1 = level 1 (LV novads/valstspilsēta, LT savivaldybė), 2 = level 2 (LV pagasts/pilsēta, LT seniūnija), 3 = settlement, 5 = street, 7 = building, 8 = apartment. In the other direction the fieldKOODAADRESScarries the same number. A bareAADRESS_IDwithout the prefix answerssuccess: false. Estonian ids match directly and need no prefix.
Example: geocoding returnsAADRESS_ID 101020361for a Latvian building → gazetteerid=7101020361; an apartment in the same building,110001974→id=8110001974. You never have to compute the ids of the parent chain (street, settlement, novads) yourself; they come from thegetFillInforesponse.
Parameter reference
| Param | Meaning | Allowed values / example | Default |
|---|---|---|---|
id * | Object AADRESS_ID (getDescription, getFillInfo) | 3069760 | — |
c | Country: an unknown value behaves like ee | ee, lv, lt | ee |
callback | JSONP callback | function name, e.g. cb | — |
key * | API key (403 without one) | docs_… | — |
l * | Level 1…6: at levels 5-6 p or g is required | 1 county … 4 street/small place, 5 building, 6 flat | — |
p | Parent AADRESS_ID (one level up) | 2822791 | — |
g | Grandparent AADRESS_ID: used only when p is absent | 2822791 | — |
Address by AADRESS_ID (getDescription)
Returns the full address record for the given id (= AADRESS_ID).
Use this when you already have an address ID: e.g. from geocoding output
(AADRESS_ID / <aid>; Estonian IDs go in as they are, LV/LT
IDs need the level prefix, see above).
curl "https://pump.elemroot.com/Gazetter/layer/getDescription/?key=docs_382d376eaaa6d004b7b93b7d&id=3069760"
Response
{
"object": {
"R_ID": 3069760,
"AADRESS_ID": 3069760,
"KOODAADRESS": null,
"POSTIINDEKS": "60532",
"E": 26.74628263,
"N": 58.39577394,
"AADRESS_ID_YLES": 3040077,
"A_LOOMISE_AEG": null,
"A_MUUTMISE_AEG": null,
"A_STAATUS_ID": 1,
"A_KIHT_ID": null,
"A0_NIMI": "Eesti Vabariik",
"A1_NIMI": "Tartu maakond",
"A1_EHAK": "0079",
"A2_NIMI": "Tartu linn",
"A2_EHAK": "0793",
"A3_NIMI": "Tartu linn",
"A3_EHAK": "8151",
"A4_NIMI": null,
"A5_NIMI": "Muuseumi tee",
"A5_NIMI_INIT": "Muuseumi tee",
"A6_NIMI": null,
"A7_NIMI": "2",
"A8_NIMI": null,
"A3_POP": null,
"POP": 99900
},
"success": true
}
Important fields:
| Field | Meaning |
|---|---|
AADRESS_ID | Address object ID |
AADRESS_ID_YLES | Parent object ID (one level up) |
E / N | Coordinates (longitude / latitude, EPSG:4326) |
POSTIINDEKS | Postal code |
A1_NIMI … A8_NIMI | Address components: A1 county, A2 municipality, A3 settlement, A4 small place, A5 street, A6 name (e.g. farm), A7 house number, A8 flat. Missing components are null (like A4_NIMI/A6_NIMI/A8_NIMI in the example). Values are always strings, even when they look numeric ("A7_NIMI": "2") |
A1_EHAK … A3_EHAK | EHAK codes |
A5_NIMI_INIT | Street name short form (e.g. "Anne tn"; same as full name for "Muuseumi tee") |
POP / A3_POP | Population |
A_STAATUS_ID / A_KIHT_ID | Address status / layer |
For an unknown ID the service returns {"success": false}.
AADRESS_ID → full address (with geocoding)
Geocoding does not support lookup by AADRESS_ID: this ID appears only in the output. To get a full address by ID use
gazetteer getDescription, which returns the full record
(components + coordinates). Typical workflow:
-
You have AADRESS_ID (e.g. from a previous geocoding response:
field
AADRESS_ID/<aid>, or from a database). -
Fetch full address by ID:
Response includes componentscurl "https://pump.elemroot.com/Gazetter/layer/getDescription/?key=docs_382d376eaaa6d004b7b93b7d&id=3069760"A1_NIMI…A7_NIMI,POSTIINDEKSand coordinatesE/N; the address is already complete (no geocoding needed for coordinates). -
If you still want to run it through geocoding (e.g. in another
coordinate system, or to get
json2/kmloutput), build address text fromgetDescriptionfields and send to the geocoder. Postal code (POSTIINDEKS) ensures the correct location:curl "https://pump.elemroot.com/jgc_rest/geocode?q=Muuseumi+tee+2,+60532&gl=ee_aid&output=json2&srs=EPSG:3301&key=docs_382d376eaaa6d004b7b93b7d"
getDescription(id) bridges ID and full address.
Address text from there works directly as geocoding q (see
refining with postal code).
Parent object chain (getFillInfo)
Returns the parent chain from leaf to root. Suitable for pre-filling cascade
selections when the final AADRESS_ID is known.
curl "https://pump.elemroot.com/Gazetter/layer/getFillInfo/?key=docs_382d376eaaa6d004b7b93b7d&id=3069760"
Response
{
"addressObjects": [
{ "AADRESS_ID_YLES": 3040077, "TASE": 5, "AADRESS_ID": 3069760 },
{ "AADRESS_ID_YLES": 3020414, "TASE": 4, "AADRESS_ID": 3040077 },
{ "AADRESS_ID_YLES": 3020404, "TASE": 3, "AADRESS_ID": 3020414 },
{ "AADRESS_ID_YLES": 2822791, "TASE": 2, "AADRESS_ID": 3020404 },
{ "AADRESS_ID_YLES": 1001, "TASE": 1, "AADRESS_ID": 2822791 }
],
"success": true
}
Each element: object AADRESS_ID, its parent AADRESS_ID_YLES and TASE.
TASE uses its own 1–6 scale (the same values as the
currentLayer parameter l; see the level table),
not the A1…A8 component column number: 1 = county, 2 = municipality, 3 = settlement,
4 = small place/street, 5 = building, 6 = flat. For a flat the chain is
TASE 6 → 5 → 4 → 3 → 2 → 1; a building without flats ends at level 5.
The chain pre-fills cascade menus: each element's AADRESS_ID_YLES is the
selected value of the next (higher) level.
Cascade list (currentLayer)
Lists address objects at one level (id + nimi). Use for building
dropdowns: pick a county, then list municipalities, etc.
| Param | Meaning | Allowed values / example |
|---|---|---|
l | Level (see table below) | 1–6 |
p | Parent AADRESS_ID (one level up) | e.g. 2822791 (Tartu county) |
g | Grandparent AADRESS_ID (two levels up) | integer (AADRESS_ID) |
Levels (l)
Usable values are 1–6:
p (or g) is required. Without a parent the query would scan the whole dataset, so the service answers 200 with the body {"success": false, "addressList": []}.l | Level | Example response value |
|---|---|---|
1 | County | "Tartu maakond" |
2 | Municipality (rural or urban) | "Kambja vald" |
3 | Settlement (city / town / village) | "Ilmatsalu alevik" |
4 | Street or small place | "Anne tänav", "Võsula väikekoht" |
5 | Building (house number or name) | "2", "2/1", farm name |
6 | Flat | "1", "10" |
Note: the level number is NOT the same as the getDescription
component column A1…A8; level 4 covers both A4 (small place) and A5 (street), level 5 both
A6 (name) and A7 (house number), level 6 is A8 (flat). The response nimi is
whichever of the pair is present.
When p, when g?
p is the normal cascade step: list level l objects whose direct
parent is p. g lets you skip one level: list objects by grandparent. Practical uses:
l=3&g=<county>: all settlements in the whole county (across municipalities).l=4&g=<municipality>: all streets and small places in the whole municipality (across settlements; including ones directly under the municipality).l=5&g=…exception: at building levelgbehaves likep(direct parent); usepthere.
curl "https://pump.elemroot.com/Gazetter/layer/currentLayer/?key=docs_382d376eaaa6d004b7b93b7d&l=1"
Response (truncated)
{
"success": true,
"addressList": [
{ "id": 100002, "nimi": "Harju maakond" },
{ "id": 100003, "nimi": "Hiiu maakond" },
{ "id": 2822791, "nimi": "Tartu maakond" },
{ "id": 100009, "nimi": "Saare maakond" }
]
}
Request: municipalities in Tartu county (level 2, parent = 2822791)
curl "https://pump.elemroot.com/Gazetter/layer/currentLayer/?key=docs_382d376eaaa6d004b7b93b7d&l=2&p=2822791"
Response (truncated)
{
"success": true,
"addressList": [
{ "id": 2974743, "nimi": "Elva vald" },
{ "id": 2822792, "nimi": "Kambja vald" },
{ "id": 3158291, "nimi": "Kastre vald" },
{ "id": 3302125, "nimi": "Luunja vald" }
]
}
Request: streets and small places in a settlement (level 4, parent = 3020414 "Tartu linn")
curl "https://pump.elemroot.com/Gazetter/layer/currentLayer/?key=docs_382d376eaaa6d004b7b93b7d&l=4&p=3020414"
Response (truncated)
{
"success": true,
"addressList": [
{ "id": 3039375, "nimi": "A. H. Tammsaare tänav" },
{ "id": 3039126, "nimi": "Anne tänav" }
]
}
Request: buildings on a street (level 5, parent = 3039126 "Anne tänav")
curl "https://pump.elemroot.com/Gazetter/layer/currentLayer/?key=docs_382d376eaaa6d004b7b93b7d&l=5&p=3039126"
Response (truncated)
{
"success": true,
"addressList": [
{ "id": 3047936, "nimi": "1" },
{ "id": 3083839, "nimi": "11" },
{ "id": 3066145, "nimi": "14a" }
]
}
Request: flats in a building (level 6, parent = 3047936 "Anne tänav 1")
curl "https://pump.elemroot.com/Gazetter/layer/currentLayer/?key=docs_382d376eaaa6d004b7b93b7d&l=6&p=3047936"
Response (truncated)
{
"success": true,
"addressList": [
{ "id": 3124193, "nimi": "1" },
{ "id": 3124202, "nimi": "10" }
]
}
If there are no objects at the level (e.g. a building without flats), the
response is {"success": false, "addressList": []}; in a cascade this means the
selection is complete.
Each id is an address object's AADRESS_ID, usable for the next level
as parent (p) or as getDescription input.
Which combination to use
| Task | Combination | Why |
|---|---|---|
| Dropdown cascade | l=1 → l=2&p=… → l=3&p=… | each step returns the next level's children |
| All streets in one municipality | l=4&g=<municipality> | g skips two levels at once |
| Pre-fill address fields from an id | getFillInfo?id=… | returns the whole parent chain up to the root |
| Full address record by id | getDescription?id=… | all components, coordinates, postal code |
| Latvia or Lithuania | c=lv / c=lt | ids are country-internal: pass c in every request |
l=3&p=<municipality> and l=4&g=<municipality>
in parallel and use whichever returns rows.
An empty level is not an error, it is the administrative structure.
g)
curl "https://pump.elemroot.com/Gazetter/layer/currentLayer/?l=4&g=2591894&key=docs_382d376eaaa6d004b7b93b7d"
JSONP
The service returns Access-Control-Allow-Origin: *; in a
modern browser plain fetch() is enough. JSONP remains for older clients.
For JSONP add callback: the response is wrapped in a function call:
curl "https://pump.elemroot.com/Gazetter/layer/getDescription/?key=docs_382d376eaaa6d004b7b93b7d&id=3069760&callback=cb"
cb({"object":{ ... },"success":true})
Content-Type stays application/json also for JSONP, and
callback does not affect the server cache (the unwrapped response is cached).
Cache
Responses are cached on the server for 24 hours; the cache key is the
parameter set (layer, id, l, p, g, c).
After a data update a stale response may therefore persist for up to a day; keep this
in mind when comparing a gazetteer response with a same-moment geocoding response.
Error handling
The gazetteer answers most content errors with 200 and {"success": false}; an empty result and invalid input look the same, so check your input. HTTP error codes only come for the
key, the rate limit and an overly wide query.
| Situation | Code | Response |
|---|---|---|
layer missing or unknown | 200 | {"success": false} |
Unknown or non-numeric id / p | 200 | {"success": false} |
Unknown c (country) | 200 | behaves like c=ee |
currentLayer at level l≥5 without p/g | 200 | {"success": false, "addressList": []}; the query would scan the whole dataset (see the warning above) |
| Key missing or invalid | 403 | JSON {"error":"invalid_api_key"} |
| Too many requests (demo key) | 429 | Too Many Requests |