Jurisdictions & geocoding
Every tax in TaxLens hangs off a place. Places form a tree, each has a hierarchical code, and a stay is resolved to one node — either directly by code or by reverse-geocoding coordinates. Learn how the tree is shaped and how a location becomes a tax answer.
What a jurisdiction is
A jurisdiction is any authority that can levy an accommodation tax: a country, a state or province, a county, a city, a borough, or a special district (a tourism improvement district, a convention-center zone). TaxLens stores them as a single global tree — the same tree serves every organization, because the law is the same no matter who is asking.
Each node carries a hierarchical, dash-delimited code that encodes its place in the tree:
NL— the Netherlands. A country sits at the root.US-NY-NYC— New York City, inside New York State (US-NY), inside the United States (US).ES-CT-BCN— Barcelona, inside Catalonia (ES-CT), inside Spain (ES).US-NY-NYC-MAN— Manhattan, a sub-city node below New York City.
The code is not cosmetic: it is how rates and rules target a place, and how the engine knows which nodes are ancestors of which. ES-CT-BCN is unambiguously a descendant of ES-CT and ES.
The hierarchy
Because taxes stack additively (see Layered & additive stacking), the tree is the backbone of every calculation. A stay at a leaf inherits every tax authored at any ancestor above it.
Ancestor chains
When you calculate for a leaf, the first thing the engine does is resolve its ancestor chain — the ordered path from the country down to the node you asked for. For a Barcelona stay that is [ES, ES-CT, ES-CT-BCN]. Every rate and rule attached to any node on that chain is then a candidate to fire.
You can inspect a chain yourself. This returns the ordered ancestors for a code — exactly the chain the engine walks:
The ordered ancestor chain TaxLens walks when calculating tax for Barcelona.
Sign in to run this against the live API. Read-only — nothing is saved.
And this resolves every active rate in force on that chain today — the raw layers, before any booking-specific rule fires:
Every rate effective on the Barcelona chain right now — country VAT plus regional and municipal tourist layers.
Sign in to run this against the live API. Read-only — nothing is saved.
How a location resolves
You give the engine a location in one of two ways. If you already know the node, pass jurisdiction_code directly — no geocoding, instant resolution. If you only have coordinates, pass lat and lng and TaxLens reverse-geocodes them to the most specific matching node.
{
"jurisdiction_code": "ES-CT-BCN",
"stay_date": "2026-07-01",
"nights": 3,
"nightly_rate": 200,
"currency": "EUR"
}For managed properties you rarely do either by hand — a property stores its resolved jurisdiction once at setup, and bookings reference the property. See Add your first property.
Geocoding: coordinates to a node
Reverse-geocoding is a pluggable provider chain. The primary provider is LocationIQ; an always-available open fallback (Nominatim) covers gaps. The fallback fires when the primary returns nothing or a partial answer — a response that is "truthy" but missing a country code still counts as incomplete and falls through, so a half-answer never silently wins.
Once a provider answers, TaxLens walks the result from the most specific level down — city_district → suburb → city → county → state_district → state → subdivision → country — and at each level matches against the tree, filtering by the expected jurisdiction type. That filter is what stops a state-level "New York" candidate from accidentally matching a city named the same. The first valid match wins, and resolution stops there.
Aliases and confidence
Geocoders speak their own place names, which don't always match our internal codes. Each jurisdiction can carry aliases in its metadata that bridge provider names to our tree — for example a provider's "Manhattan" maps to US-NY-NYC-MAN. Aliases are how a free-form provider label becomes a precise internal node.
Every resolved location also carries a confidence signal and a mapping status, so you can tell a clean, high-confidence match from one that landed on a coarser ancestor (e.g. resolved to the country but not the city). In the dashboard this surfaces on each property so you can review low-confidence mappings before they drive live bookings — see Properties.
jurisdiction_code instead of coordinates. A known code is always the most reliable input.Where to go next
Now that a location resolves to a chain, see how the layers on that chain combine in Layered & additive stacking, what kinds of tax each layer can be in Tax categories, and how to browse the tree visually in the Jurisdictions browser and Coverage map.