Validate 1,000 Postal Codes in One Call. Same Flat Rate Per Record.
Most postal code APIs charge a premium for bulk validation. Smarty, Loqate, and the legacy enterprise vendors all do some version of the same move: per-record pricing for ones and twos, then a separate "bulk" pricing tier with custom contracts and minimum commits and a sales call gate before you can even read the rates.
PostalDataPI doesn't.
We just shipped POST /api/validate-bulk. You send up to 1,000 postal codes in a single request. You pay the same per-record price as a single validate. No bulk discount. No bulk premium. $0.000028 per record either way.
The endpoint
curl -X POST https://postaldatapi.com/api/validate-bulk \
-H "Content-Type: application/json" \
-d '{
"apiKey": "YOUR_API_KEY",
"records": [
{ "postalCode": "90210", "countryCode": "US" },
{ "postalCode": "SW1A 1AA", "countryCode": "GB" },
{ "postalCode": "10115", "countryCode": "DE" },
{ "postalCode": "FOO99", "countryCode": "US" }
]
}'
Response, real, exactly as the API returns it:
{
"results": [
{ "postalCode": "90210", "countryCode": "US", "valid": true, "normalized": "90210", "reason": null },
{ "postalCode": "SW1A 1AA", "countryCode": "GB", "valid": true, "normalized": "SW1A", "reason": null },
{ "postalCode": "10115", "countryCode": "DE", "valid": true, "normalized": "10115", "reason": null },
{ "postalCode": "FOO99", "countryCode": "US", "valid": false, "normalized": null, "reason": "not_found" }
],
"totalCost": 0.000112,
"balance": 4.999888
}
Mixed countries in a single request. Per-record valid + normalized + reason. The normalized field gives you the canonical key when the postal code is valid (for example, "SW1A 1AA" resolves to the GB outcode "SW1A"); when invalid, you get a reason you can act on programmatically:
"not_found"— the format looked plausible but no record exists in the country's dataset"unknown_country"— the country code is not one PostalDataPI covers"invalid_format"— reserved for a future release where we surface format-rule violations
The math
Per-record rate: $0.000028.
| Records in request | Cost |
|--------------------|---------------|
| 1 | $0.000028 |
| 100 | $0.0028 |
| 1,000 (max) | $0.028 |
That's $0.028 to validate a thousand postal codes across however many countries you mix in the same call. A dollar buys roughly 35,000 records, batched however your data lives.
Why this matters
The single most common reason developers ask for a postal-code API at all is list cleanup. Someone has a CRM, a marketing list, a customer database, a CSV someone uploaded last quarter — and the postal codes in it are a mess. Old codes, miskeyed codes, codes that were legal in 1998 and have been retired since. Codes that were always invalid because someone typed them into a free-text field with no validation.
The legacy way to clean that list is one of:
Option 1 works at small scale but breaks down past a few thousand records. Option 2 is gated behind a sales process most teams will not pay for. Option 3 is why so many marketing emails go to invalid addresses.
POST /api/validate-bulk is the third option done properly: same auth, same SDK, same flat per-record pricing. You batch a thousand records in a JSON body, you pay $0.028, you get clean data back.
Use cases this just got cheaper
- CRM data hygiene. Periodic sweep of your customer postal codes. Flag invalid ones for follow-up. Costs roughly the price of one bag of coffee per million-record sweep.
- Form pre-submission cleanup. A user uploads a CSV; before you accept it for downstream geocoding, run the postal codes through bulk validate to surface bad rows up-front.
- Address-list maintenance for outbound campaigns. Email and SMS campaign lists go stale. Postal codes are one of the cheapest ways to surface staleness.
- Migration validation. You're moving customer records from system A to system B. Validate the postal codes during the migration so you find data quality problems while you can still do something about them.
Naming note
If you have used PostalDataPI's single-record endpoints, you have seen the legacy field names: zipcode and country. The bulk endpoint uses modern names: postalCode and countryCode. The legacy single-record endpoints will continue to use their existing names for backward compatibility. New endpoints get the modern naming because the brand is global postal codes, not US ZIP codes.
SDKs
The new method shipped in our Python and Node SDKs as version 0.2.0. Same install command, same client object, new method:
# pip install postaldatapi
from postaldatapi import PostalDataPI
client = PostalDataPI(api_key="YOUR_API_KEY")
result = client.validate_bulk([
{"postal_code": "90210", "country_code": "US"},
{"postal_code": "SW1A 1AA", "country_code": "GB"},
])
for r in result.results:
print(r.postal_code, r.valid, r.normalized, r.reason)
print(f"Cost: ${result.total_cost:.6f}, Balance: ${result.balance:.6f}")
// npm install postaldatapi
import { PostalDataPI } from "postaldatapi";
const client = new PostalDataPI({ apiKey: "YOUR_API_KEY" });
const result = await client.validateBulk([
{ postalCode: "90210", countryCode: "US" },
{ postalCode: "SW1A 1AA", countryCode: "GB" },
]);
for (const r of result.results) {
console.log(r.postalCode, r.valid, r.normalized, r.reason);
}
The MCP server (pip install postaldatapi-mcp) ships the same capability as a tool that AI agents can call directly: validate_bulk_postal_codes. Claude, ChatGPT, or any other MCP-compatible agent can validate a list of postal codes for the user without any glue code.
Limits
- Up to 1,000 records per request. If you have more, split into multiple calls; the rate limit per minute is generous and these are cheap requests.
- Sync only. The endpoint blocks until all records are processed (typically under one second for a thousand). No async / webhook callback in this release.
- Rate limits are per-record. N records in a bulk call count as N requests against your per-minute / per-hour / per-day windows. A bulk request of 100 consumes 100 from your rate-limit budget, the same as 100 single-record calls would.
Try it
New PostalDataPI accounts get 1,000 free queries on signup, no credit card required. That covers a thousand single-record calls or a single bulk-validate request of a thousand records — your choice.
Sign up at postaldatapi.com, grab your API key, paste it into the curl above, and validate a real list. The response shape is exactly what the docs at docs.postaldatapi.com/api-reference/bulk-validate show — we test our own examples against production before we publish them. Validate 1, validate 1,000 — flat rate, every record.