Address Validation API: Check and Standardise Addresses per Call
Validate, parse and geocode free-text addresses with one key, billed per call, and see what a real call returns for a good address and a made-up one.

Check and standardise a list of addresses in one prompt. Paste this into your agent:
Set up https://monid.ai/SKILL.md, and then use Monid to take this list of addresses, resolve each one to a standard form with coordinates, keep the ones that resolve, and give me a separate list of the ones that came back empty.
One prompt cleans a whole list. 1 min setup · 8-20 hrs saved.
You have addresses typed by customers, scraped from listings or exported from a CRM, and you need to know which ones are real, how to write them in one standard form, and where they are on a map. This guide shows the quickest way to do that from your agent or a script, what a real call returned for a good address and for a made-up one (we ran both on 2026-10-16), and the traps in a bulk run. It runs through Monid, the OpenRouter for agent tools: one key, one balance, every tool priced per call.
What is the easiest way to validate addresses with an API?
Monid. Install it once, add a key, and your agent calls address validation, parsing and geocoding endpoints with no portal, no plan and no vendor account to open first.
- Pay per call. Each call is billed on its own: $0.03564 for the validate endpoint and $0.011 for a geocoding endpoint (Verified 2026-10-16 on the utilities tools page). Buy calls as you need them: no monthly plan and no minimum top-up. Discovery and inspection are free; only a run bills.
- One install, every API. The same key and the same balance call address endpoints and everything else on Monid, from email checks to company lookups. Building and wiring those yourself is the 8 to 20 hours this page claims to save.
- Lives inside your agent. Install the CLI, add your key, run the prompt above, and the tools are there whenever your agent needs them, with nothing to keep running. Your agent reads
SKILL.mdand learns the rest, so setup is about a minute.
For a feel of the bill: a list of 400 addresses is 400 calls, which is $4.40 on the $0.011 endpoint (Verified 2026-10-16).
How do you validate a whole list of addresses?
Run one call per address, keep the ones that return a result, and set aside the ones that do not. There is no batch endpoint among the address tools we inspected, so a list is a loop.
For agents
Grab an API key at app.monid.ai, then paste this to your agent and hand it the key:
set up https://monid.ai/SKILL.md
It learns the whole discover, inspect, run workflow itself. More in the agent quickstart.
For humans
npm install -g @monid-ai/cli
monid keys add -k <your-api-key> -l main
Validate one address
monid run -p api.strale.io -e /x402/v2/address-validate \
--query '{"address":"1600 Amphitheatre Pkwy, Mountain View CA 94043","country_code":"US"}'
The country_code hint is optional and worth sending. It narrows the search and stops a US street name matching something in another country.
Geocode one address for less
monid run -p api.kadec0.xyz -e /v1/geocode \
--query '{"q":"1600 Amphitheatre Pkwy, Mountain View CA 94043","maxItems":"1"}'
maxItems is a string, not a number, and it caps how many candidates come back. For one address, ask for one.
Loop it over a file
Put one address per line in addresses.txt, then run:
mkdir -p out
n=0
while IFS= read -r addr; do
n=$((n+1))
monid run -p api.kadec0.xyz -e /v1/geocode \
--query "{\"q\":\"$addr\",\"maxItems\":\"1\"}" > "out/$n.json"
done < addresses.txt
Each address writes one file. A file with no items is an address that did not resolve, and the next section shows what that looks like and what it costs. The same shape, one call per row and a verdict per row, is in checking email addresses in bulk.
Or hand the whole job to an agent
Give this to your agent![]()
Set up https://monid.ai/SKILL.md, and then use Monid to standardise these 400 customer addresses, keep the ones that resolve, and give me a list of the ones that came back empty so I can chase them.Can you validate addresses yourself in Python?
Yes. You can split an address with a parsing library, or send the string to a public geocoder and read the answer, and both are a few lines to start. The effort sits in what comes after the first ten addresses.
A parsing library gives you labelled parts and nothing more. It accepts a street that does not exist, because the string was well formed. To know a place exists you need a lookup against a real dataset, which means a geocoder: either a public one with usage limits you manage yourself, or one you host, which means loading and updating a map database and running the service. Both need retry logic, rate limiting, a cache and a mapping from the geocoder's field names to yours, and each geocoder names the parts differently.
The case for Monid is that the lookup, the field mapping and the upkeep are already done: you send a string and get typed JSON back, and a call is $0.011 on the geocoding endpoint (Verified 2026-10-16). Setting up your own pipeline takes hours before the first useful row. If your list is a one-off of a few dozen addresses, a script is fine. If the same job runs every week, or an agent has to do it on demand, a per-call endpoint costs less of your time than keeping a script alive.
What does an address validation response contain?
Three layers: the parts of the address, the standard string, and the location. We ran two geocoding endpoints on 2026-10-16 with the address of Google's headquarters, so the fields below are what came back. The validate and parse endpoints are the pricier two, so we inspected them and did not run them; their fields are as listed in their descriptions.
What the validate endpoint says it returns
What the parse endpoint says it returns
What the Strale geocode call returned
One call, $0.02376 (Verified 2026-10-16), HTTP 200, 179 ms inside the response and about 2.2 seconds on the wall clock:
{ "latitude": 37.4224858,
"longitude": -122.0855846,
"display_name": "Google Building 41, 1600, Amphitheatre Parkway, Mountain View, Santa Clara County, California, 94043, United States",
"bounding_box": { "south": 37.4221124, "north": 37.4228508,
"west": -122.0859868, "east": -122.0851511 },
"place_type": "commercial",
"importance_score": 0.0000627,
"input_address": "1600 Amphitheatre Pkwy, Mountain View CA 94043",
"found": true,
"_meta": { "provenance": { "source": "openstreetmap-nominatim" } } }
found is the field to branch on. display_name is the standardised string: Pkwy came back as Parkway, and a building name and a county were added. The coordinates carry seven decimals.
What the kadec0 geocode call returned
The same address on the cheaper endpoint, $0.011 (Verified 2026-10-16), HTTP 200, about 2.6 seconds:
{ "count": 1,
"items": [ { "displayName": "Google Building 41, 1600, Amphitheatre Parkway, Mountain View, Santa Clara County, California, 94043, United States",
"lat": 37.4224858, "lon": -122.0855846,
"category": "building", "addressType": "building",
"address": { "building": "Google Building 41", "house_number": "1600",
"road": "Amphitheatre Parkway", "city": "Mountain View",
"county": "Santa Clara County", "state": "California",
"ISO3166-2-lvl4": "US-CA", "postcode": "94043",
"country": "United States", "country_code": "us" },
"osmType": "way", "osmId": 23733659 } ] }
This one hands you the parts already split, which the Strale geocode call does not. The two agree on the coordinates to the last decimal, so they read the same underlying map record. They differ in names: lat and lon against latitude and longitude, displayName against display_name, road against a street you would extract yourself.
What you can build with it
- A cleaned customer list. Resolve every address, store the standard string and the coordinates, and chase the empties by hand.
- A territory or distance filter. Coordinates on every row let you keep leads within a radius of a branch, and Google Maps scraper alternatives covers where to get the businesses to filter.
- A duplicate check. Two differently typed addresses that resolve to the same
osmIdor the same coordinates are the same place.
What goes wrong when you validate addresses in bulk?
Three things show up once you run more than a handful.
Why does an address that does not exist return an error?
On the kadec0 endpoint, an unmatched address is an error, not an empty list. We sent 99999 Nowhere Blvd, Faketown ZZ 00000 and the run came back COMPLETED with providerResponse.httpStatus 400, the message no geocoding results for '99999 Nowhere Blvd, Faketown ZZ 00000', a null output, and zero billed units. The call cost nothing and took about 3 seconds.
Treat HTTP 400 with that message as a result, not a crash. In your loop, record the address as unresolved and move on:
const unresolved = [];
for (const addr of addresses) {
const run = await geocode(addr);
if (run.providerResponse.httpStatus === 400) { unresolved.push(addr); continue; }
rows.push({ addr, ...run.output.items[0] });
}
Why is a resolved address not a delivered address?
Because the data behind these calls is a map, not a postal file. Both endpoints we ran name OpenStreetMap as their source. A map dataset can tell you a street and a building exist. The first is existence, the second is deliverability, and they are priced and sold as different products. For a mailing or a shipment, a service built on postal data is the right tool; for cleaning a lead list or placing points on a map, existence is usually the question.
What does a list of 400 cost, and does the endpoint choice change it?
The endpoint choice changes it by a factor of five. At the listed prices (Verified 2026-10-16), 400 addresses cost $4.40 on the $0.011 geocoder, $9.50 on the $0.02376 one, $14.26 on the $0.03564 validate endpoint and $23.76 on the $0.0594 parse endpoint. Unresolved addresses on the kadec0 endpoint do not bill, so a dirty list costs less than the full count.
Pick by the fields you need, not by name. If you only need coordinates and parts, the geocoder is enough. If you need the validate endpoint's confidence and suggested corrections, test it on a sample of your own list first.
Which endpoint should I use for which job?
| Endpoint | What it does | Input | Returns | Latency | Billing |
|---|---|---|---|---|---|
api.strale.io/x402/v2/address-validate | Validate and standardise | address, country_code | Components, validity confidence, suggested corrections (per its description) | Not measured | Per call |
api.strale.io/x402/address-parse | Split a string into parts | address | Street, city, postal code, state or province, country (per its description) | Not measured | Per call |
api.strale.io/x402/address-geocode | Address to coordinates | address | Coordinates, standard string, bounding box, found | 179 ms in response, about 2.2 s wall clock | Per call |
api.kadec0.xyz/v1/geocode | Address to coordinates and parts, or the reverse | q, or lat and lon, plus maxItems | Standard string, coordinates, split address, OSM id | About 2.6 s wall clock | Per call, unmatched not billed |
api.strale.io/x402/postal-code-lookup | Postal code to place | A postal code | City, region and approximate coordinates (per its description) | Not measured | Per call |
The geocode rows were run on 2026-10-16; the other rows were inspected the same day and not run. Billing shape is given here and the current figures are on monid.ai/tools.
The rows are not interchangeable. The validate row is the one built to answer "is this address good". The parse row only splits text and will split a fictional street without complaint. The two geocode rows answer "where is it", and a miss is how they tell you it is not there. If you need to know a place is real, use a lookup row. If you only need the parts, parse is enough.
When is another route a better fit?
You need deliverability, not existence. A postal authority knows whether mail arrives at a unit. A map dataset knows a street exists. For shipping, address correction and delivery-point validation, use a service built on postal data, which database vendors often quote by the seat or the volume.
Your addresses are rural or outside major markets. Map coverage differs by country and by how built-up the area is. Run fifty of your own addresses before you commit to a full list. It is cheap and conclusive.
You are validating at signup, synchronously. The calls we ran took 2 to 3 seconds on the wall clock. That is fine for a batch job and slow for a blocking form submit. If it has to be in the request path, cache aggressively and let the form through while the check finishes.
You think a resolved address means a real customer. It does not. A resolved address means the place exists. Anyone can type the address of a building they have never visited.
Rules apply to your data. Rules on storing and processing addresses differ by country and by industry, so check yours before you build a pipeline.
And the disclosure: we resell these endpoints. The most useful habit in this post is to test a known-good and a made-up address on any endpoint before trusting it, which costs two calls and works whoever you buy from.
Conclusion
The quickest way to validate and standardise a list of addresses is one call per address through Monid: $0.011 a call on the geocoder, $0.03564 on the validate endpoint (Verified 2026-10-16), one key for addresses and everything else, about a minute to set up and ready inside your agent whenever you need it. A list of 400 is $4.40 on the geocoder. Writing your own pipeline works for a one-off and costs hours the moment it has to run every week.
Two things matter more than the endpoint. A map lookup answers "does this place exist" and only postal data answers "will mail arrive". And handle the miss. A made-up address returned HTTP 400 and cost nothing on the geocoder, so a loop must treat that as an answer.
How we estimated the time saved: building and running your own address cleaning job, with a geocoder to host or rate-limit, a field mapping and retry logic, is roughly 4 to 10 hours each for two tasks (the first pipeline and the second source you add when the first misses). That is 8 to 20 hours. The 1 minute is the install, key and first call once you already have a Monid key.
Free next step: run monid inspect -p api.kadec0.xyz -e /v1/geocode, send one address you know is real and one you made up, and compare the two. Start at monid.ai.
FAQ
Is there a free address validation API?
Not free, but you only pay for what you run: through Monid the geocoder costs $0.011 a call (Verified 2026-10-16), with no monthly plan and no minimum top-up, and discovery and inspection cost nothing. An address that does not resolve on that endpoint is not billed.
What is the difference between validation, parsing and geocoding?
Parsing splits a string into labelled parts and is text work, so it succeeds on invented streets. Geocoding turns an address into coordinates, which needs a map dataset and fails when the place is not in it. Validation asks whether the address is real, and strictly needs postal data to say it can be delivered to. The endpoints we ran are map lookups with OpenStreetMap as the source. Decide which of the three you need before you compare prices, because they are different products under one label.
Does it work for international addresses?
Yes, with testing. The validate endpoint is described as covering 200+ countries and takes an optional country_code hint, which stops a street name matching a similar one elsewhere. Map data is denser in some countries and cities than others, and a field such as state or province holds very different things from one country to the next. Take fifty addresses from each country you care about, run them, and count the misses.
Can I use a geocoder to check an address?
Yes, for existence. If a geocoder returns a match for your string, a place with that name is on the map; if it returns nothing, as it did for our made-up address, the address is suspect. Read the match type too: a result of building is a different level of certainty from a street or a town. What a geocoder cannot tell you is whether mail is delivered there.
Does a valid address prove the customer is real?
No. A resolved address means a place exists at those coordinates, and anyone can copy a real building from a map. What address resolution gives a risk model is the negative: an address that resolves to nothing is a signal, and so is one that resolves to a different country from the payment method. Treat it as one weak input among several, next to signals that are harder to borrow.
Published October 2026.


