USPS Web Tools retired January 25, 2026. secure.shippingapis.com is gone, and
every Verify / ZipCodeLookup / CityStateLookup integration that didn’t migrate is broken.
Zip-Codes.com is a JSON, single-API-key replacement for the address-and-ZIP operations
— with 2,500 free credits per day, no expiration.
2,500 credits/day · No credit card · No expiration
USPS Web Tools ran for roughly 22 years as the de facto free address-and-shipping API for US developers. It covered three families: address operations (Verify, ZipCodeLookup, CityStateLookup), rate calculation (RateV4, IntlRateV2), and tracking / labels (TrackV2, eVS, Service Standards). When USPS retired the whole platform on January 25, 2026, integrations across WooCommerce, Magento, Drupal Commerce, nopCommerce, osCommerce, custom ERPs, and one-off scripts went dark. This page is about replacing the address-and-ZIP family. For tracking and shipping, you’ll need a separate path.
| USPS Web Tools operation | Zip-Codes.com equivalent | Notes |
|---|---|---|
| Address Family — What We Replace | ||
Verify (address standardization) |
GET /v2/address |
Returns standardized address, ZIP+4, parsed components, confidence, USPS metadata |
ZipCodeLookup (address → ZIP) |
GET /v2/address |
ZIP+4 is part of the standardized output — same endpoint as Verify |
CityStateLookup (ZIP → city/state) |
GET /v2/quick-zip |
Plus 50+ optional fields if you upgrade to /v2/zip |
| Rates / Tracking / Labels — Not Covered Here | ||
RateV4, IntlRateV2 |
Not offered | Rate calculation — use a shipping-rate API (EasyPost, Shippo, etc.) |
TrackV2 |
Not offered | Package tracking — use a tracking API (AfterShip, etc.) |
ExpressMailCommitment, StandardB, SDCGetLocations |
Not offered | Service standards — USPS direct or a shipping API |
eVS, eVSCancel |
Not offered | Label printing — use a label/shipping API |
| Beyond Web Tools — Capabilities USPS Didn’t Offer | ||
| (no equivalent) | GET /v2/radius |
ZIPs within N miles of a point, centroid or spatial polygon mode |
| (no equivalent) | GET /v2/suggest |
Typeahead across cities, counties, CBSAs, ZIPs, FSAs |
| (no equivalent) | GET /v2/distance |
Point-to-point distance and bearing |
| (no equivalent) | GET /v2/zip with enrichments |
Census ACS demographics, congressional / state / school districts, timezone |
| (no Canadian support) | Canadian FSA + postal coverage on every relevant endpoint | 1,600+ FSAs and 876,000+ full postal codes, native |
Most teams report migrations measured in hours, not days. Here’s where the work concentrates.
Web Tools accepted requests as application/x-www-form-urlencoded with an
XML= parameter carrying the request body, then returned text/xml.
That format was a pain in 2026 — SAX/DOM helpers and XSLT pipelines, manual
XML-string construction, and HTTP-200-on-logical-error handling that hid real failures.
Our endpoints accept ordinary REST: GET with query parameters,
application/json response, real HTTP status codes (200 success, 4xx for
client errors, 5xx for ours), and a consistent response envelope. Every mainstream
language has JSON parsing in its stdlib — the parser code you write is shorter and
you can stop importing XML libraries for this one workflow.
Web Tools authentication was a plaintext USERID attribute on the outermost
XML element — no secret, no rotation, tied to a registration at
registration.shippingapis.com. It worked, but it wasn’t a credential
you’d want in production secret management.
Our auth is a single API key. Pass it as an X-Api-Key header or a
key= query parameter. No key-pair handshake (Smarty uses
auth-id+auth-token). No OAuth dance. Keys are generated, rotated, scoped, and split into
per-environment instances in your dashboard. Up to 25 keys on the Business tier —
one for prod, one for staging, one for each application.
Web Tools routed every operation through one dispatcher
(secure.shippingapis.com/ShippingAPI.dll) and you selected the operation via
the API= query parameter. That conflated very different operations into one
URL and made routing, retries, and circuit breakers awkward.
Each of our endpoints has its own URL: /v2/address, /v2/zip,
/v2/quick-zip, /v2/radius, /v2/suggest,
/v2/distance. Standard REST semantics. Routing and observability work the
way the rest of your stack expects. And critically — ours share one credit pool, so
even with the endpoint split, billing stays consolidated: one account, one balance,
one bill.
The address-validation migration in two columns. Same address, same workflow.
POST https://secure.shippingapis.com/ShippingAPI.dll
Content-Type: application/x-www-form-urlencoded
API=Verify&XML=
<AddressValidateRequest USERID="YOUR_USERID">
<Revision>1</Revision>
<Address ID="0">
<Address1></Address1>
<Address2>1600 Pennsylvania Ave NW</Address2>
<City>Washington</City>
<State>DC</State>
<Zip5></Zip5>
<Zip4></Zip4>
</Address>
</AddressValidateRequest>
# Response: text/xml
<AddressValidateResponse>
<Address ID="0">
<Address2>1600 PENNSYLVANIA AVE NW</Address2>
<City>WASHINGTON</City>
<State>DC</State>
<Zip5>20500</Zip5>
<Zip4>0003</Zip4>
</Address>
</AddressValidateResponse>
GET https://api.zip-codes.com/v2/address
?address=1600 Pennsylvania Ave NW, Washington DC
&key=YOUR_API_KEY
# Response: application/json
{
"success": true,
"results": [{
"success": true,
"matches": [{
"formatted_address": "1600 PENNSYLVANIA AVE NW, WASHINGTON, DC 20500-0003",
"address_line1": "1600 PENNSYLVANIA AVE NW",
"address_line2": "WASHINGTON, DC 20500-0003",
"address_components": {
"number": "1600", "street": "PENNSYLVANIA", "suffix": "AVE",
"post_directional": "NW", "city": "WASHINGTON", "state": "DC",
"zip": "20500", "plus4": "0003", "country": "US"
},
"match_info": { "confidence": "high" },
"details": {
"record_type": "H", "record_type_description": "Highrise",
"carrier_route": "C049", "county_fips": "11001",
"congressional_district": "98", "building_name": "WHITE HOUSE"
}
}]
}],
"meta": { "credits": { "used": 1, "remaining": 2499 } }
}
Notice the response carries more structured data than Web Tools’ address envelope — parsed components broken out, confidence flag, carrier route, county FIPS, congressional district, building name, record type. All from the same 1-credit call.
Web Tools was free with unspecified rate limits and ToS restrictions on list/batch use. Most production Web Tools workloads fit on our free or Developer tiers.
| Monthly volume | USPS Web Tools (former) | Zip-Codes.com |
|---|---|---|
| Up to ~75,000 calls | Free (with ToS restrictions) | Free tier — 2,500/day, no card |
| 100,000 calls | Free | $49 Developer plan |
| 1,000,000 calls | Free (gray-area at this scale on Web Tools ToS) | $499 Business plan |
For most Web Tools migrations: the free tier covers evaluation and small production
workloads at no cost. Paid tiers buy higher per-minute rates, batch endpoints, and full
enrichment depth on /v2/zip.
Web Tools covered more than addresses. If your integration depended on these, you need another path:
For shipping/tracking/labels, EasyPost, Shippo, and AfterShip are common 2026 paths.
Sign up, get an API key in under 60 seconds, and try /v2/address in the
playground before you touch your code path. If you’re
migrating a WooCommerce / Magento / Drupal Commerce / nopCommerce store and want a hand
mapping the integration, email
support@zip-codes.com with your platform.
secure.shippingapis.com no
longer responds to requests, breaking every integration that hadn’t
migrated.
/v2/address does NOT
include: DPV certification (we standardize against authoritative ZIP+4 ranges;
we don’t hold USPS CASS or DPV certification). For workflows that
strictly require certified delivery-point validation, a CASS-licensed vendor
like Smarty is the right fit.
Verify, ZipCodeLookup, CityStateLookup).
Web Tools also offered RateV4 / IntlRateV2 (rate
calculation), TrackV2 (tracking),
ExpressMailCommitment (delivery commitments), eVS
(label printing), and Service Delivery Calculator operations — we
don’t replace those. If your integration depended on
shipping/tracking/labeling workflows, you’ll need a separate vendor
for that path.
secure.shippingapis.com with a JSON GET to
api.zip-codes.com/v2/address, swap your USERID for an API key,
and update your parser from XML to JSON. Plugin updates from those
platforms’ communities are landing as of early 2026; you may want to
wait for an official update or fork the legacy module. For shipping-rate and
tracking integrations, you’ll need a separate shipping API. Email
support@zip-codes.com with your
platform if you want help mapping the address path.
/v2/address call regardless of match
outcome.
X-Api-Key header or a
key= query parameter. No USERID. No password. No OAuth handshake
or token refresh. The key is generated in your dashboard at
zip-codes.com/api and can be rotated, scoped to specific IPs or domains, or
split into multiple keys (up to 25 on the Business tier) for separate
environments.
/v2/quick-zip and /v2/zip
accept Canadian FSA / postal codes directly; /v2/distance
handles cross-border pairs in one call.
/v2/address against a known
address in the playground; (2) swap the URL and auth in your existing code
path; (3) update the XML parser to a JSON parser (most languages have native
JSON in stdlib); (4) update field-name mappings since JSON field names differ
from XML element names. The bulk of effort is the XML→JSON parsing change.