- authentication
- Secret API key as a bearer token
- billing
- 1 credit for a fresh lookup that answers `valid` true; addresses that cannot stand as written and 7-day repeats are free. Two spellings of one address share the repeat marker, so they are charged once. Asking for the deliverability check adds 3 credits only when the partner actually answered.
Reads a postal address against the country it is addressed to: that operator's own format (which parts it requires, how the lines are ordered, what shape the postcode takes), its naming for boxes and other non-street delivery points, the national address registers and postcode directories, the open company registers, and the branch lists mailbox operators publish themselves.
Send the address either as one written address, the way it would appear on an envelope, or as the separated fields (address_line1, address_line2, organization, building, dependent_locality, locality, administrative_area, postal_code, po_box). Both spellings may be combined: a field sent beside a written address wins over what the parser read out of it. country (ISO 3166-1 alpha-2) is always required, because an address can only be measured against a country's own format; a code the format table does not cover answers 422. A written address may end with the country's name, open with a care-of line, or put a building name above the street — each is read for what it is and reported in changes rather than mistaken for the town or the street.
The answer gives the address broken into its parts, formatted as that country writes it, whether the postcode matches the country's pattern (postal_code_valid) and, where a directory is installed, whether it exists (postcode_status, denied only by a directory that lists every code), whether the town written on the address is one the directory publishes for that postcode (locality_matches_postcode) and whether the region is (administrative_area_matches_postcode). address_type says what kind of delivery point it is (street, po_box, private_mailbox, general_delivery, parcel_locker, rural_route, military, bulk_mail) and address_type_source says what settled it. An address that cannot stand as written answers valid: false with a reason: empty_address, missing_country, unknown_country, missing_street, missing_locality, missing_administrative_area, missing_postal_code, invalid_postal_code or postcode_not_found.
Where a national address register is installed, exists answers whether the building itself is in it. It is true only on a premise match, false only when the register that answered has register_coverage: "complete" and does not carry this one, and null otherwise — including a register whose coverage is partial (the United States National Address Database is one, because states share their data voluntarily) and a register of streets alone. match_level says how close the register got (premise, range, street, postcode, none). A register that locates the building answers its position (location_source: register), and where it publishes a use or the units at the building, building_use and is_multi_unit. premise_key is the digest of the building your outcome reports and suppression list are filed under; street_suggestion names the street the register most likely meant when the typed one is not there. confirmation says, part by part, what stood behind the postcode, the street, the house number, the town and the region.
The risk_score sums the weights of the signals in risk_signals (undeliverable 80, private_mailbox 60, placeholder 60, mail_drop 50, reported_returned 50, vacant 40, general_delivery 40, po_box 30, unit_unexpected 30, terminated_postcode 30, locality_mismatch 30, region_mismatch 30, not_in_register 20, unit_missing 20, street_not_found 20, number_out_of_range 20, bulk_mail 20; 60 and above is high, 30 and above medium), each with the dataset that produced it. Being a post-office box is not scored where a box is how that country receives mail; not_in_register fires only when exists is false, so a register whose coverage is partial never contributes to the score; and a town the directory lists elsewhere in the postcode's area, or a directory that publishes only each code's default place, never scores locality_mismatch.
Every signal whose dataset is not installed answers null, which means "not evaluated" and never "no". deliverability: true asks a licensed partner whether post actually arrives at the address and whether the delivery point is a mail-receiving agency, vacant or residential; while no partner is enabled, deliverability_checked answers false and nothing extra is charged. fields keeps only the named keys of the answer, in the answer's own order; billing and meta are never narrowed by it.
Every answer ends with a decision. ok_to_ship and blocked_by apply the account's shipping policy — the signals that block whenever they fire, a ceiling on the risk score, and whether a register must have confirmed the building (GET/PUT/DELETE /api/v1/address/policy; the defaults block above 60 and on undeliverable, placeholder and vacant) — in a published order: an address that cannot stand as written is blocked whatever the policy says (blocked_by: invalid), then the first blocked signal in the weights' order, then risk_score, then unconfirmed. Batch, bulk, monitors and the browser endpoint apply the same policy.
Two signals read the input against itself and the register. looks_placeholder is true when the whole street name or the whole town is what somebody types to get past a form — a test word, a keyboard run, a refusal, a name with no vowel — and never when a real street merely contains one of the words; the placeholder weight is 60. unit_check reads the unit written against the units the register lists at the building: missing (several units listed, none written, weight 20) or unexpected (a flat or suite written at a single residence, weight 30); a suite at a non-residential building is ordinary and answers null, and a private-mailbox number never counts as a unit. seen_by_you counts your own account's lookups of the same address inside the last seven days, under the premise digest, and never anybody else's. formatted_lines is formatted as an array, postal_code_formatted the postcode as its operator prints it, and formatted_local the address in the country's own script where the input was written in one (Japan, China, Korea).
Five documented test addresses answer a fixed result each, free, with no repeat marker and nothing stored: 1 to 5 Spaw Test Street, Springfield, IL 99999 stand for a valid low-risk address, a mail drop, a building a complete register lacks, a terminated postcode, and — written as 5 Spaw Test Street PMB 5 — a private mailbox. The published sandbox key answers them too.
The product is about places, not people: no field says who lives or works at an address, and none is ever added.
Request body
| field | type | description |
|---|---|---|
| address | string | null | The whole address written as it would be on an envelope, with the lines separated by commas or newlines. Required unless `address_line1` is sent. At most 500 characters. |
| address_line1 | string | null | The street line — house number and street name, in the order that country writes them. Required unless `address` is sent. At most 255 characters. |
| address_line2 | string | null | A second line — a flat, suite or unit, or a dependent locality. A value that reads as a unit is moved into `unit`. At most 255 characters. |
| organization | string | null | The company or institution the address belongs to. At most 200 characters. |
| building | string | null | A building named instead of numbered (Rose Cottage, Kemp House). Left out, a building name above the street line of a written address is separated by the parser and reported in `changes`. At most 100 characters. |
| dependent_locality | string | null | A neighbourhood, village or district written below the town. At most 100 characters. |
| locality | string | null | The town or city. At most 100 characters. |
| administrative_area | string | null | The state, province or region, as a code or a name; it is folded to the code that country uses where one exists. At most 100 characters. |
| postal_code | string | null | The postcode or ZIP code. At most 32 characters. |
| po_box | string | null | A post-office box written on its own, when it is not part of the address lines. At most 64 characters. |
| countryrequired | string | An ISO 3166-1 alpha-2 country code the postal format table covers (`US`, `GB`, `DE`). Case-insensitive. At most 2 characters. |
| deliverability | boolean | Ask the licensed partner whether post actually arrives at the address. While a partner is configured it reserves the premium credits up front and charges them only when the partner answered; while none is, nothing is reserved and nothing is charged. Default: . |
| fields | string | null | A comma-separated list of the answer's keys to keep (`formatted,risk_score,confirmation`). Applied after billing; unknown names are ignored, `sources` is dropped unless named, and `meta` is never narrowed. At most 1,000 characters. |
Example request
curl -X POST https://spaw.co/api/v1/address \
-H "Authorization: Bearer sk_sandbox_spaw" \
-H "Content-Type: application/json" \
-d '{
"address": "1600 Amphitheatre Parkway, Mountain View, CA 94043",
"country": "US"
}'Run it
free demo · no key needed
Running a request from this page needs JavaScript. The command above makes the same call from a terminal.
Responses
200The address as the pipeline reads it; `valid: false` with a `reason` for an address that cannot stand as written.
{
"success": true,
"data": {
"valid": true,
"reason": null,
"country": "US",
"country_name": "United States",
"continent": "NA",
"is_eu": false,
"is_eea": false,
"privacy_regime": "ccpa",
"formatted": "1600 Amphitheatre Parkway\nMOUNTAIN VIEW, CA 94043",
"formatted_lines": [
"1600 Amphitheatre Parkway",
"MOUNTAIN VIEW, CA 94043"
],
"formatted_local": null,
"organization": null,
"building": null,
"street": "Amphitheatre Parkway",
"house_number": "1600",
"unit": null,
"po_box": null,
"dependent_locality": null,
"locality": "Mountain View",
"administrative_area": "CA",
"postal_code": "94043",
"postal_code_formatted": "94043",
"postal_code_valid": true,
"postal_code_type": "zip",
"postcode_status": "live",
"locality_matches_postcode": true,
"administrative_area_matches_postcode": true,
"address_type": "street",
"address_type_source": "address_rules",
"is_po_box": false,
"is_private_mailbox": null,
"exists": true,
"match_level": "premise",
"register": "us-national-address-database",
"register_coverage": "partial",
"premise_key": "239f04782171457b",
"building_use": "commercial",
"is_multi_unit": null,
"unit_check": null,
"street_suggestion": null,
"latitude": 37.42201,
"longitude": -122.08409,
"location_source": "register",
"companies_registered": null,
"is_mail_drop": false,
"mail_drop_provider": null,
"mail_drop_source": null,
"deliverability_checked": false,
"is_deliverable": null,
"is_cmra": null,
"is_vacant": null,
"is_residential": null,
"confirmation": {
"postal_code": "postcode_directory",
"street": "register",
"house_number": "register",
"locality": "postcode_directory",
"administrative_area": "postcode_directory"
},
"changes": [],
"looks_placeholder": false,
"seen_by_you": {
"count": 0,
"first_seen_at": null,
"window_days": 7
},
"risk_score": 0,
"risk_level": "low",
"risk_signals": [],
"ok_to_ship": true,
"blocked_by": null,
"sources": [
{
"dataset": "address-formats",
"version": "2026-09-05"
},
{
"dataset": "address-rules",
"version": "2026-09-05"
},
{
"dataset": "us-national-address-database",
"version": "2026-08-14"
},
{
"dataset": "geonames-postal-codes",
"version": "2026-09-16"
},
{
"dataset": "us-tiger-address-ranges",
"version": "2025"
}
]
},
"meta": {
"credits_used": 1,
"credits_remaining": 9,
"cache_hit": false,
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}401The key is missing, malformed, or revoked.
{
"success": false,
"error": {
"code": "UNAUTHENTICATED",
"message": "Provide a valid API key as a bearer token.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}402The balance is empty. The lookup did not run.
{
"success": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Your credit balance is empty.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}422The request body could not be validated; `error.errors` lists the fields.
{
"success": false,
"error": {
"code": "VALIDATION_FAILED",
"message": "The email field is required.",
"errors": {
"email": [
"The email field is required."
]
},
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}429Over 5 requests per second for the key. Retry after the limit resets.
{
"success": false,
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests. Retry after the limit resets.",
"request_id": "req_01m1kgdm4xngzmbmff68g94w0c"
}
}Error codes
Failures answer { success: false, error: { code, message, request_id } }. Each code has its own page.