Validate postal code format by country
Postal codes are short, but their formats vary sharply from one country to another.
Run — free
This capability takes a postal or ZIP code together with a two-letter country code and checks the value against the standard structural pattern for that country. It gives applications a deterministic answer without a network lookup, geocoding request, or address database. Use it to catch misplaced letters, missing digits, and incorrect separators before data reaches checkout, fulfillment, billing, or customer records. An unsupported country code produces a clear input error instead of an uncertain validation result.
Validate the format in the right national context
A postal code cannot be judged reliably without knowing its country. Five digits are normal for the United States, France, Germany, Spain, and several other systems, yet that same shape is incomplete for India, China, or Singapore. Canada alternates letters and digits, Poland uses a required hyphen, and the United Kingdom has several alphanumeric arrangements. This capability keeps those rules separate and selects exactly one pattern from the supplied two-letter country code. It trims harmless outer whitespace and treats country-code letters without regard to case, but it does not silently rewrite the postal code into a different value. The response reports the normalized uppercase country code, the trimmed submitted code, the expected display format, and a boolean validation result. That combination makes the answer useful both to software and to people: an application can branch on the boolean while a form can show the expected shape when the value is invalid. If the country is not in the supported rule table, the request fails clearly rather than pretending every unfamiliar value is invalid. This distinction prevents incomplete coverage from becoming misleading data quality advice.
Understand what a format check can and cannot prove
The algorithm checks structure, not existence or deliverability. A successful result means the characters, length, and separator placement conform to the standard pattern represented for that country. It does not mean that a postal authority has assigned the code, that a street belongs to it, or that a carrier currently serves the destination. Those stronger claims require current external address data and often a full street address. Keeping the boundary explicit is important: deterministic format validation is fast, private, repeatable, and suitable for immediate input feedback, while deliverability verification is a different product with different data dependencies. The validator also preserves leading zeroes because postal codes are identifiers, not numbers. Submit them as strings so values such as French, Italian, or New England codes remain intact. Letter comparisons are case-insensitive where the national format uses letters, and common optional spaces are accepted only for formats where spacing is conventionally variable. Punctuation is not removed globally, since a separator can be required in one country and wrong in another. The returned format label explains the target shape without claiming that every structurally possible code exists.
Place validation where bad records first enter
The most useful place for this check is immediately after a user chooses a country and enters a postal code. A checkout can call the capability before creating an order, a signup flow can flag a likely typo before saving a profile, and an import pipeline can test each record before merging it into a customer database. For interactive forms, keep the user's original value visible and use the returned format as corrective guidance rather than replacing the text unexpectedly. For batch processing, record the boolean result and country code alongside the row so reviewers can separate malformed values from requests that failed because the country was unsupported. The function is deterministic and has no network, random source, clock, or mutable state, so the same input always receives the same answer. That makes it straightforward to test and safe to run repeatedly. API automation costs $0.002 per completed request, while the declared item unit means each submitted postal-code check is independently measurable. Treat a false result as a request for correction, not proof of fraud or a nonexistent address. Treat an unrecognized-country error as a configuration or coverage issue that needs an explicit decision rather than coercing it into a false result.
What you can do with it
Checkout input feedback
Check the postal code after the shopper selects a country and show the expected national format before creating a shipping label.
CRM import quality control
Flag structurally malformed postal codes in customer records while keeping unsupported countries separate from ordinary invalid values.
Multi-country account forms
Apply the appropriate letter, digit, length, and separator rules without embedding a separate regular expression in every client application.
FAQ
Does a valid result prove the address exists?
No. It proves only that the postal code matches the standard structural format for the selected country; it does not confirm assignment or deliverability.
What happens for an unrecognized country code?
The request returns an invalid-input error. The capability never turns missing country coverage into a misleading false validation result.
Should postal codes be sent as numbers?
No. Send a string so leading zeroes, letters, spaces, and required punctuation are preserved.
Are lowercase letters accepted?
Yes, for countries with alphabetic postal codes. The country code is also matched case-insensitively and returned in uppercase.
How much does validation cost?
Each successfully completed API request costs $0.002. Failed input requests are reported as errors.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/data/postal-code-validate \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"postal_code":"94105","country_code":"US"}'const res = await fetch("https://api.kit.forhosting.com/data/postal-code-validate", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"postal_code": "94105",
"country_code": "US"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/data/postal-code-validate",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"postal_code": "94105",
"country_code": "US"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/data/postal-code-validate", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"postal_code":"94105","country_code":"US"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"postal_code":"94105","country_code":"US"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/data/postal-code-validate", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"postal_code": "94105",
"country_code": "US"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "data.postal_code_validate",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |