Introduction
The ZIP Codes API v2 provides comprehensive postal code data for the United States and Canada. Look up ZIP codes, calculate distances, search by radius, and enrich results with census demographics, political districts, school districts, and more.
All API endpoints live under the /v2/ prefix. Responses use a consistent JSON envelope with built-in error handling and credit tracking.
Key Features
- US ZIP & ZIP+4 lookups with demographics, delivery points, and business data
- Canadian FSA & postal code lookups with province-level data
- Radius search with cross-border support (US + Canada)
- Distance calculation between any combination of ZIP codes, FSAs, postal codes, and coordinates
- 11 opt-in enrichments including ACS demographics, census boundaries, political districts, school districts, timezone, and more
- Batch processing up to 100 items per request
Authentication
All API requests require a valid API key. You can pass it in two ways:
Option 1: HTTP Header (recommended)
X-Api-Key: your_api_key
Option 2: Query Parameter
GET /v2/quick-zip?code=90210&key=your_api_key
Request & Response Format
| Aspect | Details |
|---|---|
| Content-Type | All responses are application/json; charset=utf-8. POST requests must send Content-Type: application/json. |
| POST Body | Non-batch endpoints accept GET query parameters or POST with a JSON body containing the same parameter names. Batch endpoints are POST-only. |
| Compression | The API supports Brotli and Gzip response compression. Send Accept-Encoding: br or Accept-Encoding: gzip for smaller payloads. |
| Caching | All API responses include Cache-Control: no-store. Implement your own caching layer if needed. |
| CORS | The API allows cross-origin requests from all origins by default. Account holders can configure allowed CORS origins per API key through the API Admin panel. IP whitelisting and domain restrictions are planned. |
| Request ID | Every response includes an X-Request-Id header and meta.request_id field. Include this in support requests for faster troubleshooting. |
include Parameter | Controls what data appears in the response. On /zip and /radius, it adds enrichment data (e.g. include=timezone,census). On /suggest, it filters which entity types are returned (e.g. include=zip,place) — all types are included by default. |
Quick Start
Make your first API call in seconds:
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/quick-zip?code=90210"
import requests
resp = requests.get(
"https://api.zip-codes.com/v2/quick-zip",
params={"code": "90210"},
headers={"X-Api-Key": "YOUR_API_KEY"}
)
data = resp.json()
print(data["results"][0]["city"]) # Beverly Hills
const resp = await fetch(
"https://api.zip-codes.com/v2/quick-zip?code=90210",
{ headers: { "X-Api-Key": "YOUR_API_KEY" } }
);
const data = await resp.json();
console.log(data.results[0].city); // Beverly Hills
Your Dashboard
The API Portal dashboard gives you full control over your account:
- API Keys — Create, rotate, and configure keys with per-key IP whitelisting and CORS origin restrictions.
- Usage Analytics — Daily and monthly usage charts, per-key breakdowns, and CSV export for your records.
- Billing — Manage your subscription tier, purchase credit packs, and download invoices.
- Settings — Update account details and notification preferences.
Free tier accounts start with 2,500 credits/day. Sign in to get started →
Response Format
Every API response follows a consistent envelope structure:
{
"success": true,
"request": { "code": "90210", "include": ["timezone"] },
"results": ["..."],
"error": null,
"meta": {
"request_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"version": "2.0.0",
"timing_ms": 45,
"credits": { "used": 2, "remaining": 74998, "breakdown": { "base": 1, "enrichments": { "timezone": 1 } } },
"notices": []
}
}
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the request succeeded |
request | object | Echo of parsed request parameters |
results | array | Array of result objects (varies by endpoint) |
error | object|null | null on success; {"code": "...", "message": "..."} on failure |
meta.request_id | string | Unique request identifier (also in X-Request-Id header) |
meta.version | string | API version (currently "2.0.0") |
meta.timing_ms | number | Total processing time in milliseconds |
meta.credits | object | Credit usage breakdown for this request |
meta.notices | array | Informational messages (see Notices) |
Notices
The meta.notices array contains non-error informational messages about request processing:
| Code | Description |
|---|---|
INPUT_NORMALIZED | Input was reformatted (e.g., whitespace trimmed, case corrected) |
FALLBACK_USED | Canadian postal code not found; FSA-level data returned instead |
ENRICHMENT_UNAVAILABLE | Requested enrichment not available for this country (no credit charged) |
COORDINATES_USED | Latitude/longitude coordinates used as the search center |
REVERSE_GEOCODE | Coordinate was reverse-geocoded to a postal code |
BATCH_DUPLICATES_DETECTED | Duplicate items in batch were deduplicated |
Address Matching BETA
Parse and validate a raw US street address against USPS ZIP+4 delivery-point data. Returns the standardized address, ZIP+4 code, address components, and delivery metadata. Handles partial input — city and state are optional when unambiguous.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
address | string | Required | Raw street address to match. Accepts full or partial addresses (e.g., 1600 Pennsylvania Ave NW, Washington DC 20500 or 350 5th Ave, New York). |
Credit Cost
Fixed 1 credit per request, whether or not a match is found.
Calculate your costExample Request
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/address?address=350+5th+Ave%2C+New+York+NY+10118"
Example Response
{
"success": true,
"request": { "address": "350 5th Ave, New York NY 10118" },
"results": [{
"input": "350 5th Ave, New York NY 10118",
"success": true,
"matches": [{
"formatted_address": "350 5TH AVE, NEW YORK, NY 10118-0110",
"address_line1": "350 5TH AVE",
"address_line2": "NEW YORK, NY 10118-0110",
"address_components": {
"number": "350",
"pre_directional": null,
"street": "5TH",
"street_pre_type": null,
"suffix": "AVE",
"post_directional": null,
"secondary_type": null,
"secondary_number": null,
"city": "NEW YORK",
"state": "NY",
"zip": "10118",
"plus4": "0110",
"country": "US"
},
"match_info": {
"confidence": "high",
"match_path": "zip_street",
"candidates_evaluated": 4
},
"details": {
"record_type": "H",
"record_type_description": "Highrise",
"carrier_route": "C049",
"county_fips": "36061",
"congressional_district": "12",
"building_name": "EMPIRE STATE BUILDING",
"government_building": false
}
}]
}],
"meta": { "version": "2.0.0", "timing_ms": 3, "credits": { "used": 1, "remaining": 74999 }, "notices": [] }
}
Result Fields
| Field | Type | Description |
|---|---|---|
input | string | The raw address string you submitted |
success | boolean | true if at least one match was found |
matches | array | Array of matched addresses (typically 1) |
Match Object
| Field | Type | Description |
|---|---|---|
formatted_address | string | USPS-standardized full address with ZIP+4 |
address_line1 | string | Street line (number, directional, street, suffix, secondary) |
address_line2 | string | Last line (city, state, ZIP+4) |
address_components | object | Parsed address components (see table below) |
match_info | object | Match quality metadata |
details | object | USPS delivery-point metadata |
Address Components
| Field | Type | Description |
|---|---|---|
number | string|null | House/building number |
pre_directional | string|null | Prefix directional (e.g., N, SW) |
street | string|null | Street name |
street_pre_type | string|null | Street pre-type (e.g., AVE in AVE OF THE AMERICAS) |
suffix | string|null | Street suffix (e.g., ST, AVE, BLVD) |
post_directional | string|null | Postfix directional (e.g., NW) |
secondary_type | string|null | Secondary address type (e.g., APT, STE, UNIT) |
secondary_number | string|null | Secondary address number (e.g., 4B, 200) |
city | string | Matched city name |
state | string | Two-letter state abbreviation |
zip | string | 5-digit ZIP code |
plus4 | string | 4-digit ZIP+4 suffix |
country | string | Country code (US) |
Match Info
| Field | Type | Description |
|---|---|---|
confidence | string | Match confidence level: high, medium, or low |
match_path | string | Internal resolution path (e.g., zip_street, city_state_street, city_only) |
candidates_evaluated | integer | Number of ZIP+4 candidates considered during matching |
Details (USPS Metadata)
| Field | Type | Description |
|---|---|---|
record_type | string|null | USPS record type code: S (Street), H (Highrise), P (PO Box), F (Firm), G (General Delivery), R (Rural Route) |
record_type_description | string|null | Human-readable record type name |
carrier_route | string|null | USPS carrier route code |
county_fips | string|null | 5-digit county FIPS code |
congressional_district | string|null | Congressional district number |
building_name | string|null | Building or firm name (when available) |
government_building | boolean | Whether this is a government building |
success is false and matches is an empty array. You are still charged 1 credit. Common reasons: misspelled street, address outside USPS delivery network, or a very new development not yet in the postal database.Geographic Suggest
Typeahead search for geographic entities. Returns ZIP codes, cities/places, counties, metro areas (CBSAs), states/provinces, and Canadian FSAs matching a prefix query. Results include authoritative identifiers (FIPS, GEOID), coordinates, bounding boxes, and population data.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Required | Search query (minimum 1 character). Case-insensitive. |
limit | integer | No | Max results to return. Default: 10. Free tier: max 15. Paid tiers: max 500. |
include | string | No | Comma-separated entity types to include: zip, place, county, cbsa, fsa, state. Default: all types. Unlike /zip and /radius where include adds enrichment data, here it filters which entity types are returned. |
state | string | No | US state or CA province abbreviation to filter results (e.g., CA, ON). |
country | string | No | Filter by country: US or CA. Default: both. |
proximity | string | No | Geographic bias for ranking. Accepts multiple formats: lat,lon (coordinates), auto (caller IP), IP address, 5-digit ZIP, 3-char FSA, or 2-letter state/province. Nearby results rank higher (soft bias, not a filter). |
auto or explicit IP) resolves coordinates for the response echo but does not currently influence scoring. Numeric queries (ZIP prefixes) now benefit from proximity bias.Entity Types
| Type | Count | Description | Type-Specific Fields |
|---|---|---|---|
zip | ~42K | US ZIP codes | city, classification |
place | ~30K | US Census places (cities, towns, CDPs) | fips, geoid, associated_zips |
county | ~3.2K | US counties (includes parishes, boroughs) | fips, geoid |
cbsa | ~1K | Metropolitan & micropolitan statistical areas | cbsa_code, geoid, metro_micro |
fsa | ~1.6K | Canadian Forward Sortation Areas | city, province, postal_code_count |
state | ~67 | US states/territories & CA provinces (with abbreviation aliases) | (none) |
Credit Cost
| Limit Range | Credits | Available To |
|---|---|---|
| 1–15 | 1 | All tiers (including free) |
| 16–50 | 2 | Paid only |
| 51–150 | 3 | Paid only |
| 151–500 | 5 | Paid only |
Billing based on requested limit, not results returned. Free tier requests above 15 are clamped with a FREE_TIER_LIMIT_CAPPED notice. Validation errors (missing q, invalid include) cost 0 credits.
Example Request
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/suggest?q=spring&limit=3"
Example: With proximity bias
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/suggest?q=spring&proximity=40.7128,-74.006&limit=3"
Example: Filtered by type and state
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/suggest?q=cook&include=county&state=IL"
Example Response
{
"success": true,
"request": { "q": "spring", "limit": 3 },
"results": [{ "success": true, "data": { "total_matched": 127, "matches": [
{ "type": "place", "name": "Springfield", "state": "MO", "country": "US", "population": 169176, "location": { "lat": 37.209, "lon": -93.2923 } },
{ "type": "zip", "name": "77373", "state": "TX", "country": "US", "city": "Spring", "population": 54298 },
{ "type": "cbsa", "name": "Springfield, MO", "state": "MO", "cbsa_code": "44180", "population": 478315 }
] } }],
"meta": { "version": "2.0.0", "timing_ms": 2, "credits": { "used": 1, "remaining": 74999 }, "notices": [] }
}
Match Object Fields
| Field | Type | Description |
|---|---|---|
type | string | Entity type: zip, place, county, cbsa, fsa, state |
name | string | Display name (ZIP code number, place name, county name, etc.) |
state | string | US state abbreviation (or province for FSA) |
country | string | US or CA |
population | integer | Population (ACS estimate for US, Census for CA) |
location | object | { lat, lon } — centroid coordinates |
bbox | object | { min_lat, max_lat, min_lon, max_lon } — bounding box (null for ZIPs) |
fips | string | FIPS code (places, counties only) |
geoid | string | Census GEOID (places, counties, CBSAs) |
associated_zips | array | ZIP codes within a place (places only) |
cbsa_code | string | CBSA code (CBSAs only) |
metro_micro | string | Metropolitan or Micropolitan (CBSAs only) |
city | string | Primary city name (ZIPs and FSAs only) |
classification | string | ZIP type: Standard, PO Box, Military, Unique (ZIPs only) |
province | string | CA province abbreviation (FSAs and CA states only) |
Quick ZIP Lookup
Fast postal code lookup returning basic location data with optional timezone enrichment. Supports US ZIP codes (5-digit), US ZIP+4 codes, Canadian FSAs (3-character), full Canadian postal codes (6-character), and latitude/longitude coordinates for reverse geocoding.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | Required | ZIP code, ZIP+4, FSA, Canadian postal code, or coordinates (lat,lon) |
include | string | Optional | Comma-separated enrichment flags. Only timezone is supported on this endpoint. |
Supported Code Types
| Type | Format | Example | Country | Base Cost |
|---|---|---|---|---|
| ZIP | 5 digits | 90210 | US | 1 credit |
| ZIP+4 | 9 digits (with or without dash) | 90210-1234 | US | 2 credits |
| FSA | 3 alphanumeric (A1A) | M5V | CA | 1 credit |
| Postal | 6 alphanumeric (A1A1A1) | M5V2H1 | CA | 2 credits |
| Coordinates | lat,lon (decimal degrees) | 34.1030,-118.4105 | US + CA | 2 credits |
code parameter as lat,lon.Available Enrichments
| Flag | Adds to Response | Cost | Availability |
|---|---|---|---|
timezone | IANA timezone name, UTC offsets, DST abbreviations | +1 | US + CA |
Credit Cost
ZIP and FSA = 1 base credit. ZIP+4 and Postal Code = 2 base credits. Coordinates add +1 to the resolved code’s cost. Each include flag adds +1 credit.
Response Fields
| Field | Type | Description |
|---|---|---|
country | string | "US" or "CA" |
code | string | The postal code |
code_type | string | ZIP, FSA, or Postal |
parent_code | string | null | Parent 5-digit ZIP or FSA (null for base codes) |
city | string | Primary city name |
state / state_name | string | State/province abbreviation and full name |
state_fips | string | null | 2-digit state FIPS code (US only) |
county / county_fips | string | null | County name and FIPS code (US only) |
multi_county | boolean | null | Whether ZIP spans multiple counties (US only) |
classification | string | null | ZIP type code (US only) |
classification_name | string | null | ZIP type name: General, PO Box, Military, Unique |
municipality | string | null | Municipality name (where applicable) |
location | object | {"lat": ..., "lon": ...} |
detail | object | null | Street-level detail for ZIP+4 / CA postal codes |
timezone | object | null | Present when include=timezone |
FALLBACK_USED notice. No additional credit is charged.ZIP+4 Detail Fields
When a ZIP+4 code is looked up, the detail object is populated with delivery-point data:
| Field | Type | Description |
|---|---|---|
zip4 | string | The 4-digit ZIP+4 suffix |
record_type | string | Address record type (e.g., S = Street, P = PO Box, H = Highrise, F = Firm) |
carrier_route | string | USPS carrier route code |
Street Detail Fields
Street-level address range information within the detail.street object:
| Field | Type | Description |
|---|---|---|
addr_low | string | Low end of primary address range |
addr_high | string | High end of primary address range |
prefix | string | Street name prefix directional (e.g., N, SW) |
name | string | Street name |
suffix | string | Street suffix (e.g., St, Ave, Blvd) |
postfix | string | Street name postfix directional |
odd_even | string | Address range parity: O (odd), E (even), B (both) |
sec_addr_abbr | string | Secondary address abbreviation (e.g., APT, STE, UNIT) |
sec_addr_low | string | Low end of secondary address range |
sec_addr_high | string | High end of secondary address range |
sec_addr_odd_even | string | Secondary address range parity: O, E, or B |
building_name | string | Building or firm name |
address | string | Formatted full address line |
Example Request
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/quick-zip?code=90210&include=timezone"
Example Response
{
"success": true,
"request": { "code": "90210", "include": ["timezone"] },
"results": [{
"code": "90210", "code_type": "ZIP", "country": "US",
"city": "Beverly Hills", "state": "CA", "state_name": "California",
"county": "Los Angeles", "county_fips": "06037",
"location": { "lat": 34.103131, "lon": -118.416253 },
"timezone": { "iana_name": "America/Los_Angeles", "name": "Pacific", "abbreviation": "PST", "utc_offset": -8, "observes_dst": true }
}],
"meta": { "version": "2.0.0", "timing_ms": 23, "credits": { "used": 2, "remaining": 74998 }, "notices": [] }
}
{
"success": true,
"request": { "code": "M5V", "include": ["timezone"] },
"results": [{
"code": "M5V", "code_type": "FSA", "country": "CA",
"city": "Toronto", "state": "ON", "state_name": "Ontario",
"location": { "lat": 43.638388, "lon": -79.40428 },
"timezone": { "iana_name": "America/Toronto", "name": "Eastern", "utc_offset": -5, "observes_dst": true }
}],
"meta": { "version": "2.0.0", "timing_ms": 15, "credits": { "used": 2, "remaining": 74998 }, "notices": [] }
}
{
"success": true,
"request": { "code": "99999", "include": [] },
"results": [],
"error": { "code": "NOT_FOUND_ZIP", "message": "US ZIP code 99999 not found." },
"meta": { "version": "2.0.0", "timing_ms": 8, "credits": { "used": 1, "remaining": 74999 }, "notices": [] }
}
ZIP Code Details
Comprehensive postal code lookup with rich data including demographics, business statistics, delivery points, and up to 11 optional enrichments. Returns detailed information for US ZIP codes and Canadian postal codes.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | Required | US ZIP code, Canadian postal code, or coordinates (lat,lon) |
include | string | Optional | Comma-separated enrichment flags (see Data Enrichments) |
Available Enrichments
| Flag | Adds to Response | Cost | Availability |
|---|---|---|---|
timezone | IANA timezone name, UTC offsets, DST info. Multi-zone ZIPs return array with % coverage. | +1 | US + CA |
census | County, county subdivision, place, tract, block group, CBSA overlaps with % coverage | +1 | US + CA |
cd | Congressional districts (US) / federal electoral districts (CA) with % coverage | +1 | US + CA |
state_leg | State senate (upper) and house (lower) legislative district overlaps | +1 | US only |
school_district | School districts (NCES) with office address, grade range, locale, area overlap | +1 | US only |
acs_demographic | Population, sex, age distribution, race, ethnicity, citizenship (DP05 — 108 fields) | +1 | US only |
acs_social | Households, education, language, ancestry, marital status, computers/internet (DP02 — 154 fields) | +1 | US only |
acs_economic | Employment, income, poverty, occupation, industry, health insurance, commute (DP03 — 137 fields) | +1 | US only |
acs_housing | Housing units, occupancy, tenure, home value, rent, utilities, structure age (DP04 — 143 fields) | +1 | US only |
acs_{profile}_{YYYY} | Historical ACS for any year from 2011–2024 (14 years). Append _YYYY to any ACS flag (e.g., acs_housing_2022). 528 fields in recent years, 394 in earliest. See ACS Data. | +1 each | US only |
demographics | Population, race, age, households, income, and business establishment counts | +1 | US only |
medicare | Medicare CBSA code/name/type, rating area ID, SSA state/county code | +1 | US only |
null with an ENRICHMENT_UNAVAILABLE notice. No credit is charged.Credit Cost
ZIP and FSA = 1 base credit. ZIP+4 and Postal Code = 2 base credits. Coordinates add +1 to the resolved code’s cost. Each include flag adds +1 credit. Example: include=timezone,census,cd on a ZIP = 4 credits.
Example Request
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/zip?code=90210&include=timezone,demographics"
Example Response
{
"success": true,
"request": { "code": "90210", "include": ["timezone", "demographics"] },
"results": [{
"country": "US", "code": "90210", "code_type": "ZIP",
"city": "Beverly Hills", "state": "CA", "state_name": "California",
"county": "Los Angeles", "county_fips": "06037",
"location": { "lat": 34.102823, "lon": -118.414661 },
"area_codes": ["310", "323", "424", "738"],
"elevation": { "ft": 719, "m": 219 },
"metro": { "region": "West", "division": "Pacific", "msa": "31080", "msa_name": "Los Angeles-Long Beach-Anaheim, CA" },
"zip_info": { "classification": "G", "classification_name": "General", "land_area_sq_mi": 10.9748, "delivery_points": { "total_active": 10634 } },
"demographics": { "population": { "total": 21134 }, "households": { "median_income": 190382 } },
"timezone": { "zones": [{ "iana_name": "America/Los_Angeles", "name": "Pacific", "utc_offset": -8, "pct_of_zip": 100.0 }] }
}],
"meta": { "version": "2.0.0", "timing_ms": 87, "credits": { "used": 3, "remaining": 74997 }, "notices": [] }
}
Base Fields (always included)
| Field | Type | Description |
|---|---|---|
country | string | "US" or "CA" |
code | string | The postal code |
code_type | string | ZIP, FSA, or Postal |
parent_code | string | null | Parent 5-digit ZIP (for ZIP+4 queries) or parent FSA (for CA postal queries). null for base codes. |
city | string | Primary city name |
state / state_name | string | State/province abbreviation and full name |
state_fips | string | null | 2-digit state FIPS code (US only) |
county / county_fips | string | County name and FIPS code (US only) |
multi_county | boolean | null | Whether the ZIP spans multiple counties (US only) |
municipality | string | null | Municipality name (where applicable) |
location | object | {"lat": 34.10, "lon": -118.41} |
area_codes | string[] | null | Telephone area codes overlapping this postal code |
elevation | object | null | {"ft": 719, "m": 219} — centroid elevation in feet and meters |
metro | object | null | MSA/CBSA statistical area info (US only, see sub-fields below) |
zip_info | object | null | ZIP classification, facility code, land/water area, delivery points (US only) |
postal_info | object | null | Canadian postal metadata: record type, address type, FSA stats (CA only) |
city_aliases | array | null | Alternative city names with mailing status and intro date |
detail | object | null | ZIP+4 / CA postal street-level overlay (null for 5-digit ZIP / FSA queries) |
metro Sub-Fields (US only)
| Field | Type | Description |
|---|---|---|
region | string | null | Census region (e.g., West, Northeast) |
division | string | null | Census division (e.g., Pacific, Middle Atlantic) |
csa / csa_name | string | null | Combined Statistical Area code and name |
msa / msa_name | string | null | Metropolitan Statistical Area code and name |
pmsa / pmsa_name | string | null | Primary MSA code and name (where applicable) |
postal_info Sub-Fields (CA only)
| Field | Type | Description |
|---|---|---|
record_type | string | Record type code |
address_type | string | Address type classification |
fsa | string | Parent FSA (3-character) |
delivery_postal_code | string | Delivery postal code |
fsa_population | number | FSA population |
fsa_dwellings | number | Total dwellings in FSA |
fsa_dwellings_occupied | number | Occupied dwellings in FSA |
fsa_postal_code_count | number | Number of postal codes in the FSA |
Radius Search
Find all postal codes within a given radius of a center point. Specify the center via a single code parameter (ZIP, FSA, Postal Code, or lat,lon coordinates). Cross-border searches automatically include Canadian FSAs. Supports donut searches (min radius) and result limiting.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
code | string | Required | Center point — US ZIP (5-digit), ZIP+4, Canadian FSA, Canadian Postal Code, or lat,lon coordinates (e.g. 41.878,-87.629) |
max | number or string | Required | Maximum radius in miles (e.g. 25), or "auto" (density-based) / "auto-commute" (commute-behavior-based). Numeric limits: centroid up to 500, spatial up to 250. See Auto Radius. |
min | number | Optional | Minimum radius in miles for donut search. Default: 0 |
include | string | Optional | Comma-separated enrichment flags (see table below) |
mode | string | Optional | centroid (default) — fast haversine on centroids, returns US ZIP + CA Postal. spatial — precise boundary analysis with pct_inside, returns US ZIP + CA FSA. |
limit | number | Optional | Maximum results to return |
Available Enrichments
| Flag | Adds to Response | Cost | Availability |
|---|---|---|---|
timezone | IANA timezone name, UTC offsets, DST abbreviations for each result | +1 | US + CA |
acs_demographic | Population-weighted aggregate: population, sex, age, race, ethnicity (DP05) | +1 | US only |
acs_social | Population-weighted aggregate: households, education, language, ancestry (DP02) | +1 | US only |
acs_economic | Population-weighted aggregate: employment, income, poverty, commute (DP03) | +1 | US only |
acs_housing | Population-weighted aggregate: occupancy, tenure, home value, rent (DP04) | +1 | US only |
acs_{profile}_{YYYY} | Historical ACS aggregate for any year from 2011–2024. Append _YYYY to any ACS flag (e.g., acs_economic_2019). See ACS Data for year-by-year coverage. | +1 each | US only |
census, cd, state_leg, school_district) are currently only available on /v2/zip. If requested on /v2/radius, these flags are silently ignored — no credit is charged and an ENRICHMENT_UNAVAILABLE notice is included in the response. Use /v2/zip for territory enrichments on individual codes.Every radius search starts with a base cost determined by how far you're searching — bigger search = more work for the server.
Each enrichment you add (timezone, demographics, etc.) multiplies that base cost, because the API has to gather that data for every result in your radius.
Think of it as: “search cost × number of data layers”
Quick worked example
Searching 25 miles with timezone: base cost is 1 (short search) × 2 data layers (the search itself + timezone) = 2 credits.
Credit Cost
Centroid mode (default, faster): Wider bands — the first 100 miles costs 1 base credit, the next 100 costs 2, and so on up to 500 miles.
Spatial mode (precise boundaries): Narrower bands — the first 50 miles costs 1 base credit, the next 50 costs 2, and so on up to 250 miles.
Each enrichment flag you add multiplies the base.
Calculate your costAuto Radius
Instead of specifying a numeric radius, pass max=auto or max=auto-commute to let the API calculate an appropriate search radius for the center point. This requires a ZIP, FSA, or Postal code center (not lat/lon coordinates).
| Mode | Based On | Range | Best For |
|---|---|---|---|
auto | Population density: 341 ÷ density0.42 | 3–150 miles | General-purpose searches scaled to urbanity |
auto-commute | ACS commuting patterns: mean travel time × transport-weighted speed × 1.5 | 3–100 miles | Service-area and labor-market analysis |
auto-commute automatically falls back to density-based auto and includes an AUTO_COMMUTE_FALLBACK notice in the response. The resolved radius appears in results[].search.max and the resolution method in results[].search.auto_mode ("density" or "commute").Credit cost: Using auto-radius counts as one additional data layer in the cost calculation. Example: max=auto with include=timezone = base × 3 data layers = 3 credits for a short-range search.
Example Request
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/radius?code=48226&max=25&include=timezone"
Example Response
{
"success": true,
"request": { "code": "48226", "max": 25, "min": 0, "include": ["timezone"], "mode": "centroid" },
"results": [{ "search": { "center": { "code": "48226", "city": "DETROIT", "state": "MI", "location": { "lat": 42.33, "lon": -83.05 } }, "max": 25, "mode": "centroid" },
"matches": [
{ "country": "US", "code": "48226", "city": "Detroit", "state": "MI", "distance_miles": 0.0, "timezone": { "iana_name": "America/Detroit" } },
{ "country": "US", "code": "48233", "city": "Detroit", "state": "MI", "distance_miles": 0.47 },
{ "country": "CA", "code": "N9A", "city": "Windsor", "state": "ON", "distance_miles": 1.6 }
] }],
"meta": { "version": "2.0.0", "timing_ms": 312, "credits": { "used": 2, "remaining": 74998 }, "notices": [] }
}
Search Fields
| Field | Type | Description |
|---|---|---|
search.center.code | string | Resolved center postal code |
search.center.code_type | string | ZIP, FSA, or Postal |
search.center.city | string | Center city name |
search.center.state | string | Center state/province abbreviation |
search.center.location | object | {"lat": ..., "lon": ...} — center coordinates |
search.max | number | Resolved maximum radius in miles (numeric value, even when auto was requested) |
search.min | number | Minimum radius in miles (donut inner ring) |
search.mode | string | "centroid" or "spatial" |
search.auto_mode | string | null | "density" when max=auto, "commute" when max=auto-commute, null for numeric radius |
Match Fields
| Field | Type | Description |
|---|---|---|
country | string | "US" or "CA" |
code | string | Postal code |
code_type | string | ZIP, FSA, or Postal |
city | string | City name |
state | string | State/province abbreviation |
county | string | null | County name (US only) |
county_fips | string | null | County FIPS code (US only) |
classification | string | null | ZIP type code (US only, e.g., G, P, M, U) |
classification_name | string | null | ZIP type name (e.g., General, PO Box, Military, Unique) |
location | object | {"lat": ..., "lon": ...} |
distance_miles | number | Distance from center point in miles |
pct_inside | number | null | Percentage of the postal code area inside the search radius (spatial mode only; null in centroid mode) |
area_sq_mi | number | null | Total area of the postal code in square miles (null for point-only codes) |
Distance Calculation
Calculate the great-circle distance between two points. Supports any combination of ZIP codes, ZIP+4 codes, FSAs, full Canadian postal codes, and lat/lon coordinates. Timezone data is always included at no extra cost. Each endpoint in the response includes an input_type field ("code" or "coordinates") indicating how the point was resolved.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
from | string | Required | Origin point. Accepts: US ZIP (90210), ZIP+4 (90210-1234), Canadian FSA (M5V), Canadian postal code (M5V2H1), or lat,lon coordinates (34.103,-118.410) |
to | string | Required | Destination point. Accepts: US ZIP (90210), ZIP+4 (90210-1234), Canadian FSA (M5V), Canadian postal code (M5V2H1), or lat,lon coordinates (40.758,-73.986) |
from=90210-1234&to=40.758,-73.9855Credit Cost
Fixed 1 credit per pair. Timezone is always included at no extra cost.
Calculate your costExample Request
curl -H "X-Api-Key: YOUR_API_KEY" \ "https://api.zip-codes.com/v2/distance?from=90210&to=10001"
Example Response
{
"success": true,
"request": { "from": "90210", "to": "10001" },
"results": [{
"from": { "country": "US", "code": "90210", "city": "BEVERLY HILLS", "state": "CA", "location": { "lat": 34.1028, "lon": -118.4147 }, "timezone": { "iana_name": "America/Los_Angeles" } },
"to": { "country": "US", "code": "10001", "city": "NEW YORK", "state": "NY", "location": { "lat": 40.7502, "lon": -73.9971 }, "timezone": { "iana_name": "America/New_York" } },
"distance": { "miles": 2453.39, "km": 3948.3 },
"bearing": 65.9
}],
"meta": { "version": "2.0.0", "timing_ms": 31, "credits": { "used": 1, "remaining": 74999 }, "notices": [] }
}
Health Check
Returns API and database health status. No authentication required.
Three-state health: healthy (normal), degraded (DB latency >500ms), unhealthy (DB unreachable, returns HTTP 503).
{
"success": true,
"data": { "status": "healthy", "database": { "connected": true, "latency_ms": 3 }, "version": "2.0.0" },
"meta": { "version": "2.0.0", "timing_ms": 5, "notices": [] }
}
Batch Requests
All four lookup endpoints support batch processing via POST. Send up to 100 items per request. Individual items can succeed or fail independently (the overall HTTP status is 200 even if some items fail).
AUTH_BATCH_REQUIRES_SUBSCRIPTION error.Batch Response Meta
{
"meta": {
"batch": { "requested": 3, "succeeded": 2, "failed": 1 },
"credits": { "used": 3, "remaining": 74997 },
"notices": []
}
}
BATCH_DUPLICATES_DETECTED notice is included. You are only charged once per unique code. For distance batches, deduplication operates on the full from/to pair.Batch Endpoints
| Endpoint | URL | Body Format |
|---|---|---|
| Quick ZIP | POST /v2/quick-zip/batch |
{"codes": ["90210", "M5V"], "include": "timezone"} |
| ZIP Details | POST /v2/zip/batch |
{"codes": ["90210", "10001"], "include": "timezone,census"} |
| Radius | POST /v2/radius/batch |
{"searches": [{"code": "90210", "max": 25}]} |
| Distance | POST /v2/distance/batch |
{"pairs": [{"from": "90210", "to": "10001"}]} |
Example: Quick ZIP Batch
curl -X POST "https://api.zip-codes.com/v2/quick-zip/batch" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"codes": ["90210", "M5V", "99999"], "include": "timezone"}'
Partial Failure
When some items fail, the overall HTTP status is still 200. Failed items appear in the results array with success: false and a per-item error object. The meta.batch summary tells you how many succeeded and failed:
{
"success": true,
"results": [
{ "success": true, "code": "90210", "city": "Beverly Hills", "state": "CA", "..." : "..." },
{ "success": true, "code": "M5V", "city": "Toronto", "state": "ON", "...": "..." },
{ "success": false, "code": "99999", "error": { "code": "NOT_FOUND_ZIP", "message": "US ZIP code not found" } }
],
"meta": { "batch": { "requested": 3, "succeeded": 2, "failed": 1 }, "credits": { "used": 3, "remaining": 74997 }, "notices": [] }
}
Data Enrichments
All enrichments are opt-in. Add them to the include parameter as a comma-separated list. Each enrichment adds 1 credit to the cost. Without any enrichment flags, you get base data only (1 credit).
US ZIP code boundaries come from a commercial boundary provider, updated quarterly. The dataset includes ~33,400 polygon boundaries plus ~7,600 point-only entries (PO Box, Military, and Unique ZIP types that have no geographic area).
Census geographies (counties, tracts, places, etc.) are drawn independently of ZIP codes and almost never align. Where they overlap, each result includes two percentages: pct_of_zip and pct_of_area.
Understanding pct_of_zip vs. pct_of_area
pct_of_zip = intersection area ÷ ZIP area — "What percentage of this ZIP does the geography cover?" Use this for demographic weighting: if a county covers 60% of a ZIP, roughly 60% of that ZIP's population lives in that county.
pct_of_area = intersection area ÷ geography area — "What percentage of the geography falls within this ZIP?" Use this to gauge significance: a large county may overlap a ZIP but that ZIP is only a tiny sliver of the county.
Example: A county covers 40% of a ZIP (pct_of_zip = 40.0), but that overlap is only 2% of the county's total area (pct_of_area = 2.0). The county is meaningful to the ZIP, but the ZIP is insignificant to the county.
Canadian FSAs (Forward Sortation Areas, ~1,643): The first 3 characters of a postal code. Polygon boundaries from Statistics Canada, updated with each census cycle (every 5 years).
Full Canadian postal codes (~876,000): All 6 characters. Point coordinates only — Canada Post provides centroids but postal code polygon boundaries are not publicly available. Included in /v2/radius centroid mode (default). Not available in spatial mode.
US ZIP+4 (~40M codes): Uses the parent 5-digit ZIP centroid. ZIP+4 areas change monthly with carrier route reassignment and have no stable polygon boundary.
| Flag | Description | Endpoints | Cost | Availability |
|---|---|---|---|---|
timezone | IANA timezone with DST info | Quick ZIP, ZIP, Radius | +1 | US + CA |
census | Census boundary overlaps | ZIP | +1 | US + CA |
cd | Congressional districts | ZIP | +1 | US only |
state_leg | State legislature districts | ZIP | +1 | US only |
school_district | School district boundaries (NCES) | ZIP | +1 | US only |
acs_demographic | Population, age, sex, race (DP05) | ZIP, Radius | +1 | US only |
acs_social | Households, education, language (DP02) | ZIP, Radius | +1 | US only |
acs_economic | Employment, income, industry (DP03) | ZIP, Radius | +1 | US only |
acs_housing | Housing units, occupancy, value (DP04) | ZIP, Radius | +1 | US only |
acs_{profile}_{YYYY} | Historical ACS for years 2011–2024. Append year to any ACS flag (e.g., acs_housing_2022). 4 profiles × 14 years = 56 flags. See ACS Data for year-by-year coverage. | ZIP, Radius | +1 each | US only |
demographics | Population, race, age, households, income, business | ZIP | +1 | US only |
medicare | Medicare CBSA, rating area, SSA code | ZIP | +1 | US only |
null with an ENRICHMENT_UNAVAILABLE notice. No credit is charged for unavailable enrichments.Timezone
Returns IANA timezone data including standard and daylight saving abbreviations and UTC offsets. In the /v2/zip endpoint, returns an object with source and a zones array with percentage overlap when a ZIP code spans multiple timezones. On other endpoints, timezone is a flat object per result.
Fields Returned
| Field | Type | Description |
|---|---|---|
source | string | Data source attribution |
iana_name | string | IANA timezone identifier (e.g., America/Los_Angeles) |
name | string | Display name (e.g., Pacific Standard Time) |
abbreviation | string | Standard time abbreviation (e.g., PST) |
abbreviation_dst | string | Daylight saving abbreviation (e.g., PDT) |
utc_offset | string | Standard UTC offset (e.g., -08:00) |
utc_offset_dst | string | DST UTC offset (e.g., -07:00) |
observes_dst | boolean | Whether this timezone observes daylight saving time |
pct_coverage | number | /v2/zip only — percentage of ZIP area in this timezone |
/v2/zip, the timezone object contains a zones[] array (sorted by coverage descending) and a primary shortcut. On other endpoints, a single timezone object is returned based on centroid point-in-polygon.{
"source": "IANA Time Zone Database / timezone-boundary-builder",
"zones": [{
"iana_name": "America/Los_Angeles", "name": "Pacific",
"abbreviation": "PST", "abbreviation_dst": "PDT",
"utc_offset": -8, "utc_offset_dst": -7, "observes_dst": true, "pct_of_zip": 100.0
}]
}
Census Boundaries
Returns all census geographic boundaries that overlap the ZIP code with percentage overlap calculations. Data sourced from Census Bureau TIGER/Line Cartographic Boundaries.
Census boundaries are hierarchical areas defined for statistical reporting — they are not drawn to follow ZIP code boundaries. A single ZIP almost always overlaps multiple tracts, places, and other geographies.
FIPS code structure and geography details
| Geography | FIPS Length | Example |
|---|---|---|
| State | 2 digits | 06 (California) |
| County | 5 digits | 06037 (Los Angeles Co.) |
| County Subdivision | 10 digits | 0603765000 |
| Place | 7 digits | 0644000 (Los Angeles city) |
| Census Tract | 11 digits | 06037264000 |
| Block Group | 12 digits | 060372640001 |
| Congressional District | 4 digits | 0634 |
Counties (~3,200): Primary legal division of every state. Connecticut replaced its 8 counties with 9 Planning Regions in 2022 (Census Bureau adopted these starting with 2024 data). Louisiana has parishes, Alaska has boroughs, and some cities in Virginia and Maryland are independent of any county.
County Subdivisions: Minor Civil Divisions (MCDs) in ~29 states represent legal townships and towns. In other states, Census-defined County Divisions (CCDs) serve as statistical equivalents.
Places: Incorporated places (cities, towns, villages with legal boundaries) and Census Designated Places (CDPs — statistical areas for unincorporated communities).
Census Tracts (~85,000): Designed for 2,500–8,000 people with socioeconomic homogeneity. The tract code has an implied decimal: 046300 = tract 463.00.
Block Groups: The smallest geography with ACS data, containing 600–3,000 people. GEOID = parent tract code + 1 digit.
CBSAs: Metropolitan Statistical Areas (core city 50K+ population) or Micropolitan (10K–50K). Rural areas have no CBSA. Metropolitan Divisions subdivide the largest metros into component areas.
Included Boundary Types
| Boundary | Description |
|---|---|
county | County boundaries with FIPS codes |
county_subdivision | County subdivisions (CCDs, MCDs) |
place | Census-designated places and incorporated cities |
tract | Census tracts with GEOID |
block_group | Census block groups |
metro_micro_cbsa_statistical_area | Metropolitan/Micropolitan statistical areas |
metropolitan_cbsa_division | Metro divisions (where applicable) |
Each boundary includes: geoid, name, land_area_sq_mi, water_area_sq_mi, pct_of_zip (% of ZIP this boundary covers), and pct_of_area (% of boundary this ZIP covers).
{
"census": {
"county": [{ "geoid": "06037", "name": "Los Angeles County", "pct_of_zip": 100.0, "pct_of_area": 0.3 }],
"place": [{ "geoid": "0606000", "name": "Beverly Hills city", "pct_of_zip": 49.3, "pct_of_area": 95.1 }],
"tract": [{ "geoid": "06037700900", "name": "Census Tract 7009", "pct_of_zip": 10.2 }],
"metro_micro_cbsa_statistical_area": [{ "geoid": "31080", "name": "Los Angeles-Long Beach-Anaheim, CA Metro Area", "pct_of_zip": 100.0 }]
}
}
Congressional Districts
Returns congressional district overlaps for the current Congress session, with primary district identification and area percentages.
Fields Returned (US)
| Field | Type | Description |
|---|---|---|
congress | number | Congressional session number (e.g., 119) |
primary.geoid | string | GEOID of the primary (highest overlap) district |
primary.state | string | State abbreviation |
primary.district_number | string | District number |
districts[] | array | All overlapping districts with geoid, name, state, district_number, land_area_sq_mi, water_area_sq_mi, pct_of_zip, pct_of_area |
Fields Returned (CA)
Canadian codes return federal_electoral_district with uid, name, and pct_of_zip.
{
"congressional_district": {
"congress": 119,
"districts": [
{ "geoid": "0632", "state": "CA", "district_number": 32, "name": "Congressional District 32", "pct_of_zip": 62.9 },
{ "geoid": "0636", "state": "CA", "district_number": 36, "name": "Congressional District 36", "pct_of_zip": 37.1 }
],
"primary": { "geoid": "0632", "state": "CA", "district_number": 32 }
}
}
State Legislature
Returns state senate (upper chamber) and assembly/house (lower chamber) district overlaps with area percentages. US only
Fields Returned
| Field | Type | Description |
|---|---|---|
state_legislative_upper[] | array | State Senate district overlaps |
state_legislative_lower[] | array | State House/Assembly district overlaps |
Each district includes: geoid, name, district_code, state, state_fips, legislative_session_year, land_area_sq_mi, water_area_sq_mi, pct_of_zip, pct_of_area.
{
"state_legislative_upper": [{ "geoid": "06024", "name": "24", "name_full": "State Senate District 24", "state": "CA", "pct_of_zip": 92.9 }],
"state_legislative_lower": [{ "geoid": "06051", "name": "51", "name_full": "Assembly District 51", "state": "CA", "pct_of_zip": 63.5 }]
}
School Districts
Returns NCES school district data with boundary overlaps. US only
District boundaries are from the National Center for Education Statistics (NCES). A single ZIP can overlap multiple school districts because different district types serve the same geographic area at different grade levels.
District type breakdown
Unified: Serves all grades K–12. The most common type nationwide.
Elementary / Secondary: Grade-banded districts that overlap geographically. Elementary districts cover lower grades (K–6 or K–8), while secondary districts cover upper grades (7–12 or 9–12).
Administrative: Supervisory unions (52 records, all in Vermont). The leaid field is a 7-character NCES Local Education Agency ID.
Locale codes: Range from 11 (City—Large) to 43 (Rural—Remote). Returned in the locale object as both a numeric code and description.
Fields Returned per District
| Field | Type | Description |
|---|---|---|
leaid | string | NCES Local Education Agency ID |
name | string | District name |
type | string | District type: unified, elementary, secondary, administrative, other |
grade_low / grade_high | string | Grade range served (e.g., PK to 12) |
office | object | Office address, city, state, ZIP, county, lat/lon |
locale | object | Locale classification code and description (city/suburb/town/rural) |
pct_of_zip / pct_of_area | number | Overlap percentages |
land_area_sq_mi | number | District land area |
{
"school_district": {
"source": "National Center for Education Statistics (NCES)", "school_year": "2024-2025",
"districts": [{
"leaid": "0604830", "name": "Beverly Hills Unified School District",
"type": "unified", "grade_low": "KG", "grade_high": "12",
"pct_of_zip": 39.9, "pct_of_area": 72.8,
"office": { "address": "624 N. Rexford Dr.", "city": "Beverly Hills", "state": "CA", "zip": "90210" },
"locale": { "code": "21", "description": "Suburb - Large" }
}]
}
}
ACS Data
American Community Survey 5-year estimates from the Census Bureau. Four separate data profiles available, each activated by its own flag. US only
All ACS fields include an estimate (est) and margin of error (moe). Percentage fields also include pct and pct_moe. Suppressed Census values are returned as null.
year field and a vintage field indicating the exact dataset. Current ACS flags (e.g., acs_demographic) return the most recent year (2020–2024). Historical flags (e.g., acs_demographic_2022) return the specified year's dataset. You can request current and historical simultaneously — they appear under acs.current and acs["2022"] respectively. 14 years available: 2011–2024.acs_demographic — DP05 (108 fields)
| Section | Key Fields |
|---|---|
| Sex and Age | Total population, male/female counts, age brackets (under 5 through 85+), median age |
| Race | White, Black, American Indian, Asian, Pacific Islander, other, two or more races |
| Hispanic or Latino and Race | Hispanic/Latino totals, breakdown by race within Hispanic/non-Hispanic |
| Citizen, Voting Age Population | Citizens 18+, total voting age population |
| Total Housing Units | Housing unit count |
acs_social — DP02 (154 fields)
| Section | Key Fields |
|---|---|
| Households by Type | Total households, family/nonfamily, married-couple, single-parent, average size |
| Relationship | Householder, spouse, child, other relatives, nonrelatives, unmarried partner |
| Marital Status | Never married, now married, separated, widowed, divorced |
| Fertility | Women 15–50 who had a birth in the past 12 months |
| Grandparents | Grandparents living with grandchildren, responsible for care |
| School Enrollment | Nursery through graduate school, public/private breakdown |
| Educational Attainment | Less than 9th grade through doctorate, high school+, bachelor's+ |
| Veteran Status | Civilian veterans 18+ |
| Disability Status | Civilian noninstitutionalized population with a disability |
| Residence 1 Year Ago | Same house, different house (same county, state, abroad) |
| Place of Birth | Native vs. foreign-born, state of birth, world region |
| Language Spoken at Home | English only, Spanish, Asian/Pacific Island, other, English proficiency |
| Ancestry | Top ancestral origins reported |
| Computers and Internet Use | Households with computer, broadband, smartphone, no internet |
acs_economic — DP03 (137 fields)
| Section | Key Fields |
|---|---|
| Employment Status | Labor force, employed, unemployed, unemployment rate, armed forces |
| Commuting to Work | Drove alone, carpooled, public transit, walked, work from home, mean travel time |
| Occupation | Management, service, sales, construction, production, transportation |
| Industry | Agriculture, manufacturing, retail, healthcare, education, finance, tech |
| Class of Worker | Private wage, government, self-employed, unpaid family |
| Income and Benefits | Median household/family income, per capita, with earnings/Social Security/retirement |
| Health Insurance Coverage | With/without coverage, private, public, by employment status |
| Poverty Level | Families and people below poverty, by age, family type, education |
acs_housing — DP04 (143 fields)
| Section | Key Fields |
|---|---|
| Housing Occupancy | Total units, occupied, vacant, homeowner vacancy rate, rental vacancy rate |
| Units in Structure | Single-family detached/attached, 2–4 units, 5–19, 20+, mobile home, boat/RV |
| Year Structure Built | 2020+, 2010–2019, 2000–2009, through 1939 or earlier |
| Rooms / Bedrooms | 1 room through 9+, median rooms, bedroom count distribution |
| Housing Tenure | Owner-occupied, renter-occupied, average household size by tenure |
| Year Householder Moved In | 2021+, 2018–2020, 2010–2017, through 1989 or earlier |
| Vehicles Available | No vehicle, 1, 2, 3+ vehicles |
| House Heating Fuel | Gas, electric, fuel oil, coal, wood, solar, other, no fuel |
| Selected Characteristics | Lacking plumbing, lacking kitchen, no telephone service |
| Value | Owner-occupied home value distribution, median value |
| Mortgage Status | With/without mortgage, second mortgage, home equity loan |
| Monthly Owner Costs | Cost distribution, median, as percentage of household income |
| Gross Rent | Rent distribution, median rent, as percentage of household income |
Historical ACS Data (2011–2024)
Append _YYYY to any ACS profile flag to request a specific year. Example: include=acs_housing_2022 returns the 2018–2022 5-Year Estimates for housing. You can request multiple years simultaneously (e.g., include=acs_economic,acs_economic_2019). Each flag costs +1 credit.
| Year | ACS 5-Year Estimates | Fields | Coverage |
|---|---|---|---|
| 2024 (current) | 2020–2024 | 528 | 97.4% |
| 2023 | 2019–2023 | 528 | 100% |
| 2022 | 2018–2022 | 521 | 98.7% |
| 2021 | 2017–2021 | 518 | 98.1% |
| 2020 | 2016–2020 | 518 | 98.1% |
| 2019 | 2015–2019 | 517 | 97.9% |
| 2018 | 2014–2018 | 486 | 92.0% |
| 2017 | 2013–2017 | 483 | 91.5% |
| 2016 | 2012–2016 | 463 | 87.7% |
| 2015 | 2011–2015 | 463 | 87.7% |
| 2014 | 2010–2014 | 441 | 83.5% |
| 2013 | 2009–2013 | 441 | 83.5% |
| 2012 | 2008–2012 | 394 | 74.6% |
| 2011 | 2007–2011 | 394 | 74.6% |
null. 394 “universal” fields are available across all 14 years./v2/zip, ACS returns per-ZIP data under acs.current.{section} (or acs["2022"].{section} for historical). On /v2/radius, returns population-weighted aggregates under stats.acs.current.{section} — the stats object appears at the top level of each radius result alongside search, matches, and summary. Current dataset: 2020–2024 5-Year Estimates. Historical: 2011–2024 (14 years total).{
"acs": {
"geo_id": "860Z200US90210", "year": 2024,
"product": "ACS 5-Year Estimates Data Profiles", "vintage": "2020-2024",
"tables": { "demographic": "DP05", "social": "DP02", "economic": "DP03", "housing": "DP04" },
"demographic": {
"total_population": { "est": 21134, "moe": 82 },
"sex_and_age": { "male": { "est": 10099, "pct": 47.8 }, "female": { "est": 11035, "pct": 52.2 }, "median_age": { "est": 49.3 } },
"race": { "white": { "est": 17130, "pct": 81.1 }, "black_or_african_american": { "est": 366, "pct": 1.7 }, "asian": { "est": 1406, "pct": 6.7 } }
}
}
}
Demographics
Returns population, race, age, household, and business establishment data. Sourced from US Census Bureau and IRS Business Master File data.
Fields Returned
| Field | Type | Description |
|---|---|---|
| population | ||
population.total | number | Total population (Census 2020) |
population.estimate | number | Current population estimate |
population.male | number | Male population |
population.female | number | Female population |
| race | ||
race.white | number | White population |
race.black | number | Black or African American population |
race.hispanic | number | Hispanic or Latino population |
race.asian | number | Asian population |
race.american_indian | number | American Indian / Alaska Native population |
race.hawaiian_pacific_islander | number | Native Hawaiian / Pacific Islander population |
race.other | number | Other race population |
| age | ||
age.median | number | Median age |
age.median_male | number | Median age (male) |
age.median_female | number | Median age (female) |
| households | ||
households.total | number | Total households |
households.persons_per_household | number | Average persons per household |
households.average_family_size | number | Average family size |
households.median_income | number | Median household income (USD) |
households.average_home_value | number | Average home value (USD) |
| business | ||
business.establishments | number | Number of business establishments |
business.employees | number | Total employees |
business.payroll_q1 | number | First quarter payroll (USD, thousands) |
business.payroll_annual | number | Annual payroll (USD, thousands) |
business.employment_flag | string | Employment range flag when exact count is suppressed |
{
"demographics": {
"population": { "total": 21134, "estimate": 22943, "male": 10099, "female": 11035 },
"race": { "white": 17130, "black": 366, "hispanic": 1296, "asian": 1406 },
"age": { "median": 49.3 },
"households": { "total": 8792, "median_income": 136490, "average_home_value": 1953100 },
"business": { "establishments": 3142, "employees": 28853 }
}
}
Medicare
Returns Medicare geographic identifiers used in healthcare pricing, insurance rating areas, and CMS administrative boundaries.
Fields Returned
| Field | Type | Description |
|---|---|---|
cbsa_code | string | Core Based Statistical Area code used by CMS for Medicare payment |
cbsa_name | string | CBSA name (e.g., “Los Angeles-Long Beach-Anaheim, CA”) |
cbsa_type | string | Metropolitan or Micropolitan (null if rural) |
rating_area_id | string | ACA marketplace rating area identifier |
ssa_state_county_code | string | SSA state/county code used in Medicare administrative systems |
multi_county_notice | string | Present only when a ZIP spans multiple counties with different Medicare assignments |
{
"medicare": {
"cbsa_code": "31080", "cbsa_name": "Los Angeles-Long Beach-Anaheim, CA",
"cbsa_type": "Metropolitan", "rating_area_id": "16", "ssa_state_county_code": "05210"
}
}
Credit Costs
Every API call uses credits from your plan. Simple credits cost 1. Adding enrichments (extra data like demographics or timezone) adds to the cost. The radius endpoint scales with search distance. This section breaks down exactly what each call costs — no surprises.
| Endpoint | Base Cost | + Enrichments | Plain English |
|---|---|---|---|
| Address BETA | 1 per request | N/A | Always 1 credit |
| Quick ZIP | 1 (ZIP/FSA), 2 (ZIP+4/Postal/Coords) | +1 per flag | 1–3 credits typical |
| ZIP Details | 1 (ZIP/FSA), 2 (ZIP+4/Postal/Coords) | +1 per flag | 1–12 credits typical |
| Distance | 1 per pair | timezone free | Always 1 credit |
| Suggest | 1–5 (by limit) | N/A | 1 credit for ≤15 results |
| Radius | 1–5 (by distance) | × (1 + flags) | 1–30 credits depending on distance + enrichments |
| Batch | Per-item cost | Same as single | Sum of individual items |
| Health | 0 | N/A | Always free |
Address Matching
Fixed 1 credit per request, regardless of whether a match is found. No enrichment flags are available on this endpoint.
Quick ZIP & ZIP Details
Base cost depends on input type: ZIP or FSA = 1 credit, ZIP+4, Postal Code, or coordinates = 2 credits. Each enrichment flag adds +1.
Examples: ZIP with timezone = 2. ZIP+4 with timezone + demographics = 4.
Radius Search
Base cost scales with distance (banded pricing). Each enrichment multiplies the base rather than adding to it. Auto-radius counts as one additional data layer.
Examples: 25mi with no flags = 1. 25mi with timezone = 2. 200mi centroid with 4 ACS flags = 10.
Distance
Fixed 1 credit per pair. Timezone data is always included at no extra cost. Mix any input types freely.
Suggest
Cost scales with the requested limit: 1–15 results = 1 credit, 16–50 = 2, 51–150 = 3, 151–500 = 5. Billed on requested limit, not results returned.
Radius Credit Costs
Formula: base × (1 + enrichment_count). Base bands differ by mode.
Centroid Mode (default) — ceil(radius / 100), max 500mi
| Band | Radius Range | Base | No Flags | + 1 flag | + 2 flags |
|---|---|---|---|---|---|
| 1 | 1–100 mi | 1 | 1 | 2 | 3 |
| 2 | 101–200 mi | 2 | 2 | 4 | 6 |
| 3 | 201–300 mi | 3 | 3 | 6 | 9 |
| 4 | 301–400 mi | 4 | 4 | 8 | 12 |
| 5 | 401–500 mi | 5 | 5 | 10 | 15 |
Spatial Mode — ceil(radius / 50), max 250mi
| Band | Radius Range | Base | No Flags | + 1 flag | + 2 flags |
|---|---|---|---|---|---|
| 1 | 1–50 mi | 1 | 1 | 2 | 3 |
| 2 | 51–100 mi | 2 | 2 | 4 | 6 |
| 3 | 101–150 mi | 3 | 3 | 6 | 9 |
| 4 | 151–200 mi | 4 | 4 | 8 | 12 |
| 5 | 201–250 mi | 5 | 5 | 10 | 15 |
Band boundaries are inclusive at the top: max=50 = band 1, max=51 = band 2. Decimal values are accepted: max=50.5 = band 2.
Formula Examples
25mi centroid, no flags→ ceil(25/100) × (1 + 0) = 1 credit25mi centroid, timezone→ 1 × (1 + 1) = 2 credits100mi centroid, acs_demographic + timezone→ 1 × (1 + 2) = 3 credits200mi centroid, 4 ACS flags→ 2 × (1 + 4) = 10 credits500mi centroid, 4 ACS + timezone→ 5 × (1 + 5) = 30 credits50mi spatial, no flags→ ceil(50/50) × (1 + 0) = 1 credit100mi spatial, 2 ACS flags→ 2 × (1 + 2) = 6 credits250mi spatial, 4 ACS + timezone→ 5 × (1 + 5) = 30 credits
Credit Estimator
Select an endpoint and configure options to see exactly how many credits your API call will cost.
Subscription Plans
| Plan | Monthly Credits | Price |
|---|---|---|
| Free | 2,500 / day | Free |
| Developer | 75,000 | $49/mo |
| Professional | 250,000 | $149/mo |
| Business | 750,000 | $399/mo |
Credit Packs
Pre-purchase credits that never expire. Works alongside any plan — free or paid. If you exceed your daily free allowance or monthly subscription, purchased credits kick in automatically.
| Pack | Credits | Price | Per 1,000 |
|---|---|---|---|
| Starter | 10,000 | $10 | $1.00 |
| Standard | 50,000 | $49 | $0.98 |
| Growth | 100,000 | $79 | $0.79 |
| Pro (best value) | 250,000 | $179 | $0.72 |
| Enterprise | 1,000,000 | $499 | $0.50 |
Purchased credits are used only after your free or subscription allowance is exhausted. Need a custom volume? Contact us.
Error Codes
Authentication Errors
| Code | HTTP | Description |
|---|---|---|
AUTH_MISSING_KEY | 401 | No API key provided |
AUTH_INVALID_KEY | 401 | API key not recognized |
AUTH_INACTIVE_KEY | 403 | API key has been deactivated |
AUTH_INACTIVE_ACCOUNT | 403 | Account is suspended |
AUTH_IP_RESTRICTED | 403 | Request IP not in key's allowlist |
AUTH_ORIGIN_RESTRICTED | 403 | Request origin not in key's domain list |
AUTH_IP_BLOCKED | 403 | IP temporarily blocked (excessive invalid key attempts) |
AUTH_TEST_KEY_RESTRICTED | 403 | Test key limited to demo codes only |
AUTH_TEST_KEY_RADIUS_EXCEEDED | 403 | Radius exceeds the limit allowed for test keys |
AUTH_FREE_TIER_RADIUS_EXCEEDED | 403 | Radius exceeds the free tier limit (centroid: 100mi, spatial: 50mi) |
AUTH_BATCH_REQUIRES_SUBSCRIPTION | 403 | Batch endpoints require a paid subscription (Developer tier or higher) |
Validation Errors
| Code | HTTP | Description |
|---|---|---|
VALIDATION_MISSING_PARAM | 400 | Required parameter is missing |
VALIDATION_INVALID_PARAM | 400 | Parameter value is invalid |
VALIDATION_INVALID_ZIP | 400 | ZIP/postal code format not recognized |
VALIDATION_INVALID_FORMAT | 400 | Input format not recognized (not a valid postal code or coordinate pair) |
VALIDATION_INVALID_COORDINATES | 400 | Coordinates are not valid (latitude must be −90 to 90, longitude −180 to 180) |
VALIDATION_INVALID_COORDINATES_FROM | 400 | The from coordinate pair is invalid (distance endpoint) |
VALIDATION_INVALID_COORDINATES_TO | 400 | The to coordinate pair is invalid (distance endpoint) |
VALIDATION_INVALID_RADIUS | 400 | Radius must be a positive number within mode limits |
VALIDATION_INVALID_RADIUS_RANGE | 400 | Min radius must be less than max radius |
VALIDATION_UNKNOWN_ENRICHMENT | 400 | Unrecognized enrichment flag in include parameter |
VALIDATION_ACS_YEAR_NOT_AVAILABLE | 400 | Requested ACS year is not available (valid range: 2011–2024) |
VALIDATION_BATCH_TOO_LARGE | 400 | Batch exceeds 100 items |
VALIDATION_BATCH_EMPTY | 400 | Batch contains no items |
VALIDATION_INVALID_REQUEST | 400 | Malformed or unreadable request body (invalid JSON, wrong field types) |
MISSING_VERSION | 400 | Request path must start with /v2/ |
Credit & Rate Limit Errors
| Code | HTTP | Description |
|---|---|---|
CREDIT_INSUFFICIENT | 402 | Not enough credits remaining |
CREDIT_DAILY_LIMIT | 402 | Free tier daily limit reached |
RATE_LIMIT_MINUTE | 429 | Per-minute rate limit exceeded |
RATE_LIMIT_HOUR | 429 | Per-hour rate limit exceeded |
Framework Errors
| Code | HTTP | Description |
|---|---|---|
METHOD_NOT_ALLOWED | 405 | HTTP method not supported for this endpoint |
REQUEST_TOO_LARGE | 413 | Request body exceeds the maximum allowed size |
UNSUPPORTED_MEDIA_TYPE | 415 | POST requests must use Content-Type: application/json |
Service Errors
| Code | HTTP | Description |
|---|---|---|
SERVICE_POOL_EXHAUSTED | 503 | All database connections are in use; retry shortly |
SERVICE_TIMEOUT | 504 | Database query exceeded the timeout threshold |
SERVICE_MAINTENANCE | 503 | Service is temporarily unavailable for maintenance |
Per-Item Not Found (HTTP 200)
| Code | Description |
|---|---|
NOT_FOUND_ZIP | US ZIP code not found |
NOT_FOUND_ZIP4 | US ZIP+4 code not found (parent ZIP exists) |
NOT_FOUND_FSA | Canadian FSA not found |
NOT_FOUND_POSTAL | Canadian postal code not found |
NOT_FOUND_CENTER | Radius search center code not found |
NOT_FOUND_COORDS_NO_BOUNDARY | Coordinates do not fall within any known postal code boundary |
Error Response Format
{
"success": false,
"results": [],
"error": { "code": "AUTH_MISSING_KEY", "message": "API key is required. Provide via X-Api-Key header or ?key= parameter." },
"meta": { "version": "2.0.0", "timing_ms": 1, "notices": [] }
}
Rate Limiting
All responses include rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
X-RateLimit-Window | Rate limit window period: always minute |
Limits by Plan
| Plan | Per Minute | Per Hour |
|---|---|---|
| Free (no subscription) | 60 | 3,600 |
| Developer ($49/mo) | 300 | 18,000 |
| Professional ($149/mo) | 300 | 18,000 |
| Business ($399/mo) | 600 | 36,000 |
| Enterprise | Custom (contact sales) | |
When rate-limited (HTTP 429), the response includes a Retry-After header with seconds to wait:
{
"success": false,
"error": { "code": "RATE_LIMIT_MINUTE", "message": "Rate limit exceeded. Try again in 45 seconds." },
"meta": { "version": "2.0.0", "timing_ms": 0, "rate_limit": { "limit": 120, "window": "1 minute", "retry_after": 45 }, "notices": [] }
}
Supported Countries
| Country | Code Types | Census Boundaries | ACS Data | Political Districts |
|---|---|---|---|---|
| United States | ZIP (5-digit), ZIP+4 (9-digit) | Full (county, tract, block group, place, CBSA) | Full (DP02–DP05) | Congressional, State Senate, State House |
| Canada | FSA (3-char), Postal (6-char) | Provincial boundaries | Not available | Not available |
HTTP Status Codes
Summary of all HTTP status codes the API can return:
| Code | Meaning | When |
|---|---|---|
| 200 | OK | Successful request. Batch requests return 200 even if individual items fail. |
| 400 | Bad Request | Missing or invalid parameters, malformed JSON body, empty batch |
| 401 | Unauthorized | Missing API key, invalid key, or disabled account |
| 402 | Payment Required | Insufficient credits or daily limit reached |
| 403 | Forbidden | API key lacks permission for the requested resource |
| 405 | Method Not Allowed | Wrong HTTP method (e.g., PUT on a GET/POST endpoint) |
| 415 | Unsupported Media Type | POST without Content-Type: application/json |
| 429 | Too Many Requests | Rate limit exceeded. Check Retry-After header. |
| 500 | Internal Server Error | Unexpected server error. Include X-Request-Id when reporting. |
| 503 | Service Unavailable | Server maintenance or temporary overload |
Versioning
The API uses path-based versioning. All current endpoints are under /v2/. The version is also returned in every response as meta.version.
- Backward-compatible changes (new fields, new enrichments, new endpoints) are added without a version bump.
- Breaking changes (removed fields, changed response structure) will only occur in a new version (e.g.,
/v3/). - The current version (
v2) is stable and actively maintained. There are no plans to deprecate it. - If a future version is released,
v2will continue to operate for a minimum of 12 months after deprecation notice. - See our Service Level Agreement and Terms of Service for uptime and usage commitments.
OpenAPI Specification
A machine-readable OpenAPI 3.0 specification is auto-generated from the API and always reflects the current endpoints, parameters, and response schemas.
| Resource | URL | Use For |
|---|---|---|
| Swagger UI | /swagger |
Interactive exploration and testing |
| OpenAPI JSON | /swagger/v2/swagger.json |
Import into Postman, generate SDKs, AI coding tools |
| Download Spec | /v2/openapi.json |
Download the OpenAPI spec file directly |
Changelog
Notable API changes, data updates, and new features.
March 2026
- New endpoint:
/v2/address— Address matching (beta). Parse and validate raw US street addresses against USPS ZIP+4 delivery-point data. Returns standardized address, ZIP+4, parsed components, and delivery metadata. Fixed 1 credit per request.
Frequently Asked Questions
Do you use ZCTA boundaries?
How often is the data updated?
Can I try the API without signing up?
Do you support Canadian postal codes?
M5V) and full postal codes (6 characters like M5V2H1) across all endpoints. Canadian codes work with timezone enrichment, and radius searches automatically include cross-border results. Some enrichments (ACS demographic data, congressional districts, school districts) are US-only and return null for Canadian codes with no credit charged.What is the difference between Quick ZIP and ZIP Details?
/v2/quick-zip) is a lightweight lookup returning core postal code info (city, state, coordinates, code type) with only timezone as an optional enrichment. It is optimized for fast, high-volume lookups like form validation or address autocomplete. ZIP Details (/v2/zip) returns comprehensive data including demographics, business statistics, delivery points, and up to 11 enrichments (census boundaries, ACS data, congressional districts, school districts, and more).How are credit costs calculated?
include parameter adds +1 credit. For radius searches, the base cost depends on the search radius (banded pricing: 1/2/3/4/5 credits per 100-mile centroid band, or per 50 mile spatial band), multiplied by (1 + enrichment_count). Distance calculations are always 1 credit per pair with timezone included free. The Suggest endpoiint is based on tiers: 1–15 = 1 credit · 16–50 = 2 · 51–150 = 3 · 151–500 = 5. See the Credit Costs section for full details.What happens if I exceed my rate limit?
Retry-After header indicating how many seconds to wait. Rate limits are enforced on a per-minute window and vary by subscription tier. Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) are included in every response so you can monitor usage proactively.Can I do reverse geocoding with coordinates?
lat,lon in the code parameter (e.g., code=34.1030,-118.4105) on any lookup endpoint. The API uses a two-step spatial search: first, it identifies which ZIP or FSA boundary polygon contains the coordinate (not just the nearest centroid — a point in rural Montana will correctly resolve to the ZIP that actually covers that location, not a distant one). Then, it finds the closest ZIP+4 or full postal code centroid within that parent boundary for precise sub-code resolution. Coordinate credits add +1 to the base cost. This works in both the US and Canada.What ACS data years are available?
acs_* flags return the most recent year (2024, covering 2020–2024 estimates). To request a specific historical year, append _YYYY to any ACS flag (e.g., include=acs_demographic_2022). You can request multiple years in the same call. Field coverage is 100% for recent years and 74.6% for the earliest years (2011–2012), as Census added new questions over time. New ACS releases are added annually, typically within weeks of the Census Bureau publication.Is there a batch/bulk endpoint?
POST. Send up to 100 items per request. The free tier excludes batch requests however. Each item succeeds or fails independently, and duplicates are automatically deduplicated (you are only charged once per unique code). See the Batch Requests section for body formats and examples.Why does one ZIP return multiple counties, tracts, or school districts?
pct_of_zip and pct_of_area fields on each overlap quantify how much of each area is shared.What is the difference between centroid and spatial mode on /radius?
pct_inside and area_sq_mi are null. Spatial uses precise polygon intersection (STBuffer/STIntersects) — slower but includes pct_inside and area_sq_mi, supports up to 250mi, returns US ZIP codes + Canadian FSAs (no full postal codes). Use mode=spatial when you need overlap precision.