Skip to main content

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.

This guide walks you through Panama Postal’s core workflows from the Python library and the command-line interface. All examples use real postal codes and real output values from the source. Start with a simple decode and build up to full geographic enrichment.
The GeoJSON files (estafeta.geojson.gz, PROVINCIAS.geojson.gz, etc.) are entirely optional. Steps 1–4 work without them. Steps 5–6 use local GeoJSON when available and automatically fall back to the official API endpoint when not.
1
Decode a postal code to coordinates
2
Import decode from panama_postal and pass any valid code. The returned DecodedPostal dataclass contains the center coordinates of the encoded grid cell, the precision level, and the estafeta prefix extracted from the first two characters.
3
from panama_postal import decode

d = decode("ACC99-PJ42W")
print(d.lat, d.lng)          # 8.944446093749999  -79.56167109375002
print(d.level)               # PICO
print(d.precision_meters)    # 3.3
print(d.estafeta_prefix)     # AC
4
The level field reflects how many character pairs were decoded. A full ten-character code (eight-character body) decodes to PICO level — the finest precision at approximately 3.3 meters. Shorter codes resolve to NANO (~26 m), MICRO (~660 m), or MACRO (~15.8 km).
5
decode() returns None if the input cannot be parsed — for example if it contains characters outside the base-30 alphabet (23456789ABCDEFGHJKLMNPQRSTVWXZ).
6
Validate format and geography
7
validate() checks two things: that the code has a valid format, and that the decoded coordinates fall within Panama’s geographic bounding box. It returns True only when both conditions pass.
8
from panama_postal import validate

validate("ACC99-PJ42W")                # True
validate("ACCI99-PJ42W")               # False  (I is not in the base-30 alphabet)
validate("22-2222-2222", strict=True)  # False  (coordinates fall outside strict Panama bbox)
9
By default, validate() uses the official site’s permissive bounding box (lat ∈ [6, 11], lng ∈ [-86, -74]), which includes adjacent ocean and border areas. Pass strict=True (or omit the --laxo CLI flag) to use the tighter territorial bounding box (lat ∈ [7.15, 9.70], lng ∈ [-83.10, -77.10]).
10
Encode GPS coordinates to a postal code body
11
encode() converts a (lat, lng) pair into the geographic body of a postal code — the eight characters that represent the grid position. Note that the two-character estafeta prefix is not included in this output; resolving it requires a point-in-polygon lookup against estafeta.geojson.gz.
12
from panama_postal import encode

cuerpo = encode(8.305509375, -79.20167109375001)
print(cuerpo)   # 'M2C9A-F9A33'
13
You can also encode at a coarser resolution by passing a level argument: "MACRO" (2 chars), "MICRO" (4 chars), "NANO" (6 chars), or "PICO" (8 chars, default).
14
Use the CLI
15
The CLI supports both interactive and non-interactive modes. It automatically loads estafeta.geojson.gz and the political division GeoJSON files if they are present in the current directory.
16
Interactive mode
# Launches a prompt loop — type codes one at a time
python panama_postal_cli.py
Single code lookup
python panama_postal_cli.py ACC99-PJ42W
Multiple codes at once
python panama_postal_cli.py ACC99-PJ42W ACC9A-H2K2P
Skip location lookup (no network needed)
python panama_postal_cli.py --no-location ACC99-PJ42W
17
In interactive mode, type a postal code at the código> prompt. Enter salir, exit, quit, or q to exit. The CLI prints coordinates, precision, estafeta data (if available), and political division hierarchy (if available or reachable via the API), along with a Google Maps link.
18
Look up estafeta name and area (requires estafeta.geojson.gz)
19
EstafetaIndex loads the compressed GeoJSON and performs a point-in-polygon search to identify which estafeta (post office service zone) a coordinate belongs to. When multiple polygons overlap, it returns the one with the smallest area.
20
from panama_postal import decode
from panama_postal_estafeta import EstafetaIndex

idx = EstafetaIndex.from_file("estafeta.geojson.gz")
d = decode("ACC99-PJ42W")
info = idx.lookup(d.lat, d.lng)

print(info["ESTAF_NAME"])          # Estafeta de paraiso
print(info["VM_LEVEL2D"])          # AC
print(info["AREA"] / 1e6)          # area in km²
21
lookup() returns a dictionary of all properties stored in the GeoJSON feature, or None if the point does not fall within any estafeta polygon. Load the index once and reuse it across many lookups — from_file() parses the entire file into an in-memory spatial index.
22
Resolve political divisions (local GeoJSON or API fallback)
23
HybridLocator resolves a coordinate to its full political division hierarchy: province, district, corregimiento, village, and neighborhood. It checks for local GeoJSON files first and falls back to the official remote API if none are present.
24
from panama_postal_location import HybridLocator

loc = HybridLocator(".")
r = loc.lookup(8.94444609375, -79.56167109375001)

print(r["provincia"]["nombre"])      # PANAMÁ
print(r["distrito"]["nombre"])       # PANAMÁ
print(r["corregimiento"]["nombre"])  # ANCÓN
print(r["poblado"]["nombre"])        # ANCÓN
print(r["barrio"]["nombre"])         # AMADOR
25
Each key in the result dictionary maps to either a {"nombre": ..., "codigo": ...} dict or None if the data was unavailable for that level. The "." argument tells HybridLocator to look for GeoJSON files in the current directory.
26
To force one mode explicitly, pass prefer="local" or prefer="remote" to lookup():
27
# Force remote API regardless of local files
r = loc.lookup(8.94444609375, -79.56167109375001, prefer="remote")

# Force local only — returns None if no GeoJSON files present
r = loc.lookup(8.94444609375, -79.56167109375001, prefer="local")

Next Steps

Installation

Set up the repo and download optional GeoJSON data files for fully offline operation.

Postal System Guide

Deep-dive into Panama’s four-level geospatial grid and the base-30 alphabet.

decode() Reference

Full parameter and return type reference for the decode function.

HybridLocator Reference

Configure local-first or remote-only lookup behavior for political divisions.

Build docs developers (and LLMs) love