Panama Postal provides three locator classes for resolving geographic coordinates to Panama’s five-tier political division hierarchy.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/kass507/panama-postal/llms.txt
Use this file to discover all available pages before exploring further.
RemoteLocator queries the official government API over HTTP, LocalLocator performs fully offline point-in-polygon lookups against locally downloaded GeoJSON files, and HybridLocator combines both strategies — using local data when available and transparently falling back to the remote endpoint.
Shared Return Format
All threelookup() methods return the same normalized dict structure, or None if the coordinate could not be resolved at all.
Normalized political-division result, or
None when the point falls outside
all known boundaries or a network/file error occurs.LocalLocator, absent key for RemoteLocator) return None rather than raising an exception.
RemoteLocator
RemoteLocator resolves coordinates by calling Panama’s official government API endpoint. No local files are required.
The remote endpoint is the official Panama Postal Service API at
https://codigospostalespanama.gob.pa/api/location. Results depend on
network availability and the upstream service. All requests are sent with
the User-Agent: panama-postal-cli/1.0 header.Constructor
Full base URL of the location API. The
lookup() method appends
?lat={lat}&lng={lng} query parameters to this URL. Override this in tests
or when pointing at a self-hosted mirror.HTTP request timeout in seconds. Applies to both connection and read phases.
Requests that exceed this value return
None rather than raising.lookup()
GET request to {base_url}?lat={lat}&lng={lng} and return the normalized result.
Latitude in decimal degrees (WGS 84).
Longitude in decimal degrees (WGS 84).
None on any of the following conditions: URLError (including DNS failure or refused connection), JSONDecodeError (malformed response body), TimeoutError, or an HTTP error response.
LocalLocator
LocalLocator performs fully offline point-in-polygon lookups using the same ray-casting engine as EstafetaIndex. It reads five gzip-compressed GeoJSON boundary files from a local directory.
Required Data Files
Download all five files to yourdata_dir before use:
| File | Name field | Code field |
|---|---|---|
PROVINCIAS.geojson.gz | PROV_NOMB | PROV_ID |
DISTRITOS.geojson.gz | DIST_NOMB | DIST_ID |
CORREGIMIENTOS.geojson.gz | CORR_NOMB | CORR_ID |
POBLADOS.geojson.gz | LUPO_NOMB | LUPO_ID |
BARRIOS.geojson.gz | BARR_NOMB | BARR_ID |
None in the result dict.
Constructor
Directory that contains the GeoJSON boundary files listed in the table above.
The locator lazy-loads each file on first access and caches the resulting
EstafetaIndex for the lifetime of the instance.lookup()
Latitude in decimal degrees (WGS 84).
Longitude in decimal degrees (WGS 84).
None when no GeoJSON files are present in data_dir at all. When at least one file exists, missing layers appear as None entries in the dict rather than causing None to be returned for the whole result.
has_any_data()
True if at least one of the five expected GeoJSON files exists in data_dir. Use this to check whether local data has been downloaded before deciding to use a LocalLocator or fall back to RemoteLocator.
HybridLocator
HybridLocator composes a LocalLocator and a RemoteLocator into a single object with a flexible prefer strategy.
Constructor
Directory passed through to the internal
LocalLocator. See LocalLocator
for the expected GeoJSON files.HTTP timeout in seconds passed through to the internal
RemoteLocator.lookup()
Latitude in decimal degrees (WGS 84).
Longitude in decimal degrees (WGS 84).
Strategy for choosing between local and remote data:
"auto"— uses local data ifhas_local_data()returnsTrueand the local lookup returns a non-Noneresult; otherwise falls back to the remote endpoint. This is the default and recommended value."local"— performs a local-only lookup. No network request is made, even if the local lookup returnsNone."remote"— calls the remote endpoint directly, regardless of whether local files are present.
has_local_data()
LocalLocator.has_any_data(). Returns True if at least one GeoJSON boundary file exists in data_dir.