Postal Code & Geocoding API
The Geo & Postal API returns administrative-region and postal reference data as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary eu_regions endpoint returns NUTS regions and LAU for a query, and you can pull TR and US regions, Indian postal data, US census areas, admin boundaries and a general postal_lookup. It is built for logistics, address validation and geo analytics that need authoritative region data. One ReefAPI key, one shared credit pool, the standard envelope.
Which action covers which geography, and what codes it hands back
This is not one global lookup — each region has its own official coding system and its own action. Picking the wrong one is the usual reason a code comes back missing. Every response also carries match_type, confidence, low_confidence, source and dataset_version so you can tell an exact hit from a fuzzy one.
| Action | Geography | Codes it returns |
|---|---|---|
| us_regions | United States — ZIP or lat/lon | state code + 2-digit FIPS, county name + 5-digit FIPS, ZIP centroid |
| us_census | United States — street address, ZIP or lat/lon | census tract GEOID (11 digits), block GEOID (15 digits), ZCTA, county FIPS |
| eu_regions | EU / EFTA / candidate countries | NUTS 0–3 hierarchy, LAU commune with GISCO id |
| tr_regions | Türkiye | il + plaka, ilçe, mahalle/köy, posta kodu, NUTS-TR 1–3 |
| in_postal | India | PIN code, post offices with type and delivery status, district, state |
| admin_boundary | Global — lat/lon only | ADM0 / ADM1 / ADM2 names + ISO3, each with its own confidence |
| postal_lookup | ~100 countries — country + postal code | admin1/admin2/admin3 names and codes, lat/lon, accuracy, NUTS3 for EU |
| postal_search | country + city, or country + state, or country alone | the postal codes for a place, or that country's region list |
| postal_distance / postal_radius | any two postal codes / one code + radius | great-circle distance between postal centroids |
US FIPS lengths are fixed and zero-padded: state is 2 characters ('06' for California), county is 5 ('06037' for Los Angeles, which embeds the state), tract GEOID is 11 and block GEOID is 15. Store them as strings — parsing them as integers destroys the leading zero for every state below 10.
Real request and response JSON
Captured from the indexed primary action, eu_regions, on .
{
"method": "POST",
"url": "https://api.reefapi.com/geo-postal/v1/eu_regions",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"lat": 52.52,
"lon": 13.405
}
}{
"ok": true,
"meta": {
"api": "geo-postal",
"endpoint": "eu_regions",
"mode": "live",
"latency_ms": 383.2,
"record_count": 1,
"bytes": 0,
"cache_hit": false,
"attribution": "© EuroGeographics (NUTS/LAU) · © European Union - GISCO TERCET (CC-BY-SA 4.0) · geoBoundaries CGAZ www.geoboundaries.org (CC-BY 4.0) · GeoNames www.geonames.org (CC-BY 4.0) · TurkiyeAPI (MIT) · India Post pincode directory (GODL-India)"
},
"data": {
"normalized_input": {
"lat": 52.52,
"lon": 13.405
},
"match_type": "exact",
"confidence": 0.98,
"low_confidence": false,
"source": "gisco_nuts_2024",
"dataset_version": "nuts2024-01m|lau2024-01m|cgaz-cc-by-4.0|pcode2025-v2.0|geonames-2026-06|turkiyeapi-2025|inpin-godl-2026",
"found": true,
"nuts0": {
"code": "DE",
"name": "Deutschland"
},
"nuts1": {
"code": "DE3",
"name": "Berlin"
},
"nuts2": {
"code": "DE30",
"name": "Berlin"
},
"nuts3": {
"code": "DE300",
"name": "Berlin"
},
"country": {
"code": "DE",
"name": "Deutschland"
},
"lau": {
"gisco_id": "DE_11000000",
"lau_id": null,
"name": "[redacted-name]",
"match_type": "exact"
}
}
}What the Postal Code & Geocoding API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| eu_regions | Coordinates OR postal code → EU/EFTA/candidate statistical regions: country, NUTS 0-3 hierarchy, LAU commune (GISCO NUTS-2024 + LAU-2024 + TERCET pc2025). | Ops teams call eu_regions to get coordinates OR postal code → EU/EFTA/candidate statistical regions. | lat, lon, postal_code, country, include_geometry |
| tr_regions | Türkiye: koordinat, posta kodu VEYA il/ilçe/mahalle adı → resmî idari hiyerarşi (il+plaka, ilçe, mahalle/köy, posta kodları) + NUTS-TR istatistik kodları. | Developer tools call tr_regions to get türkiye. | lat, lon, postal_code, province, district, ... |
| in_postal | India: PIN code OR post-office name → post offices, district, state, lat/lon centroid (official All-India Pincode Directory). | Validation workflows call in_postal to get india. | pincode, office, state, district |
| us_regions | United States: ZIP code OR coordinates → state, county + 5-digit county FIPS, place, ZIP centroid, and the CGAZ state/county boundary. Built WITHOUT census.gov (GeoNames ZIP directory carries county FIPS; ANSI state-FIPS is a public-domain constant). For census-grade ZCTA + tract/block GEOIDs use the `us_census` action (TIGER/ZCTA polygons + Census Geocoder, gov-pending/91). | Data-quality teams call us_regions to get united States. | postal_code, lat, lon, include_geometry |
| us_census | United States census-grade geocode: street ADDRESS, ZIP, or coordinates → state, county (+5-digit FIPS), census TRACT GEOID, census BLOCK GEOID, ZCTA, and tract/ZCTA land-area — with match_type + confidence. Coordinates/ZIP resolve the ZCTA offline from pinned TIGER/ZCTA-2024 polygons (zero egress); the authoritative tract/block GEOID + address geocoding come from the US Census Geocoder, cached. US-Gov public domain (Title 17 §105). | Ops teams call us_census to get united States census-grade geocode. | address, postal_code, lat, lon, include_geometry, ... |
| admin_boundary | GLOBAL coordinates → administrative boundary hierarchy ADM0/ADM1/ADM2 (geoBoundaries CGAZ composite, CC-BY 4.0). | Developer tools call admin_boundary to get gLOBAL coordinates → administrative boundary hierarchy ADM0/ADM1/ADM2 (geoBoundaries CGAZ com…. | lat, lon, levels, include_geometry |
| postal_lookup | country + postal code → region metadata for ~100 countries (GeoNames postal directory) with country-specific enrichment (EU→NUTS3, TR→mahalle, IN→offices). | Validation workflows call postal_lookup to get country + postal code → region metadata for ~100 countries (GeoNames postal directory) with c…. | country, postal_code |
| postal_search | country + city/place → its postal codes (zip-by-city); country + admin1 only → that state's codes (zip-by-state); country only → the country's states/regions list (GeoNames directory). | Data-quality teams call postal_search to get country + city/place → its postal codes (zip-by-city); country + admin1 only → that state's c…. | country, place, admin1, limit |
| postal_distance | Great-circle distance between two postal codes (same or different countries). | Ops teams call postal_distance to get great-circle distance between two postal codes (same or different countries).. | country, from, to, to_country, unit |
| postal_radius | All postal codes within a radius of a postal code (centroid-based). | Developer tools call postal_radius to get all postal codes within a radius of a postal code (centroid-based).. | country, postal_code, radius_km, limit |
| batch | Resolve up to 50 mixed lookups in one call (cheap local queries). | Validation workflows call batch to resolve up to 50 mixed lookups in one call (cheap local queries).. | items |
Call eu_regions from your stack
curl -X POST https://api.reefapi.com/geo-postal/v1/eu_regions \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"lat":52.52,"lon":13.405}'import requests
r = requests.post(
"https://api.reefapi.com/geo-postal/v1/eu_regions",
headers={"x-api-key": REEF_KEY},
json={
"lat": 52.52,
"lon": 13.405
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/geo-postal/v1/eu_regions", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"lat": 52.52,
"lon": 13.405
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.geo-postal.eu_regions with {"lat":52.52,"lon":13.405}.Who uses this API and why
- Logistics tools call postal_lookup to map a postal code to a region.
- Address validation uses eu_regions and us_regions to normalize locations.
- Analytics use us_census and admin_boundary to aggregate by area.
Questions developers ask before integrating
Why does us_regions give me census_pending instead of a tract GEOID?
Because tract, block and ZCTA polygons come from a different dataset than the ZIP directory us_regions reads. When that extension is not loaded the response returns a census_pending object whose keys are literally marked gov_pending, while state, county, FIPS and centroid come back complete. The fix is not to retry — call us_census, which is the action built for tract and block geoids. A measured us_census lookup on ZIP 02139 returned tract GEOID 25017353101 and block GEOID 250173531012002.
Can found be true while a field inside is null?
Yes, and it happens routinely — treat found as 'we resolved the input', not 'every field is populated'. Measured examples: us_census on ZIP 02139 returned found true, a full tract and block, and zcta null. admin_boundary on Paris coordinates returned adm0.id null while adm1.id and adm2.id both carried ids, because the global boundary dataset does not assign ids at country level. Check the specific field, not the flag.
Are the coordinates rooftop-accurate?
No, and the response says so. us_regions returns centroid with an explicit centroid_note that it is the ZIP centroid from the postal directory, not a rooftop geocode, and postal_distance reports method 'haversine_centroid' for the same reason: it measures between two postal-code centroids. The one path that can be rooftop-grade is us_census in address mode, which returns matched_address and a match_type of census_geocoder_exact. Distances between two adjacent ZIPs will read as a few kilometres even for neighbouring buildings.
What do match_type and confidence actually mean?
match_type names how the input was resolved and confidence scores it from 0 to 1, with low_confidence set as a boolean so you do not have to pick a threshold. Measured values: postal_exact scored 0.95 for a direct ZIP hit, census_geocoder_exact scored 0.97, and a coordinate hit against the global boundary set scored 0.98. A fuzzy place-name match scores materially lower — read low_confidence before you write the result into a customer record.
How do I know the reference data has not gone stale?
Every response carries dataset_version listing each underlying dataset and its vintage — NUTS 2024, LAU 2024, the CGAZ boundary composite, the TERCET postcode table, the GeoNames postal snapshot, the Türkiye dataset and the India PIN directory. Log it alongside the result. When a boundary changes, that string is what tells you whether a stored answer was computed before or after the revision.
Can I resolve a batch of postal codes in one call?
Yes. batch accepts up to 50 mixed lookups per call and returns each result tagged with the action that produced it, so you can mix a US ZIP, a German postcode and a Turkish il in one request. These are local dataset queries rather than remote fetches — a postal_lookup measured at 7.6 ms against a US ZIP lookup that hits the geocoder at roughly 900 ms — so batching mainly saves round trips, not upstream cost.
Which Turkish fields does tr_regions return that a generic postal lookup misses?
The full official hierarchy rather than a flattened place name: province with its id, plaka number, NUTS-TR 1–3 codes, region, population, coordinates, phone area codes and an is_metropolitan flag; district with id and population; and the mahalle/köy matches carrying their own postal_code, population and kind. You can enter it from any direction — coordinates, posta kodu, or il/ilçe/mahalle names — because one Turkish postal code frequently spans several mahalle.
What is the Postal Code & Geocoding API?
Postal Code & Geocoding API is a ReefAPI endpoint group for postal code & geocoding It returns live JSON through POST requests under /geo-postal/v1.
Is the Postal Code & Geocoding API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Postal Code & Geocoding calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Postal Code & Geocoding login or account?
No login to Postal Code & Geocoding is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Postal Code & Geocoding data?
The page example is captured from a live eu_regions call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Postal Code & Geocoding API use?
Postal Code & Geocoding actions currently cost 1-3 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.
Can I call Postal Code & Geocoding from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call geo-postal actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the Postal Code & Geocoding API a Postal Code & Geocoding scraper?
It is the managed alternative to a DIY Postal Code & Geocoding scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same postal code & geocoding back as clean JSON.