Geocoding, road distances, route plans, drive-time areas, flood and crime risk, official facts, places nearby and plain-English questions over a table, as one REST API. Free for 2,500 lookups a day, and the results are yours to keep.
Quick answer
The InstaMaps API is a REST API for location data on lists of addresses. Send a POST to https://get-instamaps.com/v1/<endpoint> with your key in Authorization: Bearer and a JSON body, and get JSON back. It geocodes addresses with a confidence for every row, measures road miles and drive times, plans routes for up to 10 drivers, checks flood zones, crime and natural-hazard risk, and answers plain-English questions about a table (the =ASK formula, as an API). The first 2,500 lookups each day are free, keys are free with a Google sign-in, and there is no 30-day cache rule: store the results for as long as you like. It is strongest in the US and Great Britain, on InstaMaps' own address index, roads and official data.
curl https://get-instamaps.com/v1/geocode_batch \
-H "Authorization: Bearer $INSTAMAPS_KEY" \
-H "Content-Type: application/json" \
-d '{"records": [{"id": "hq", "address": "10 Downing Street, London SW1A 2AA"},
{"id": "wh", "address": "1600 Pennsylvania Ave NW, Washington DC 20500"}]}'Answer: 3 rows: 2 placed, 0 to review, 1 unplaced · 2 of 3 high confidence (0 medium, 1 low). Caveats: not placed (1 row).
{
"confidence": {
"summary": "2 of 3 high confidence (0 medium, 1 low). Caveats: not placed (1 row).",
"levels": {
"high": 2,
"medium": 0,
"low": 1
},
"caveats": [
{
"basis": "not_placed",
"level": "low",
"rows": 1,
"ids": [
"x"
],
"meaning": "This row could not be placed.",
"next": "Leave it out of totals, say so, and ask the user for a postcode or coordinates."
}
]
},
"records": [
{
"id": "hq",
"input": "10 Downing Street, London SW1A 2AA",
"record_key": "rk1_e9ec1ea25045e3a5e393",
"address_quality": {
"value": "full_street",
"basis": "rule"
},
"status": "placed",
"location": {
"value": {
"lat": 51.5034878,
"lng": -0.1276965
},
"precision": "rooftop",
"confidence": {
"value": 0.95,
"basis": "rule",
"evidence": [
"named site matched (10 Downing Street)",
"house number 10 matched",
"street matched (Downing Street)",
"… 5 more"
]
}
},
"admin": {
"value": {
"house_number": "10",
"street": "Downing Street",
"city": "London",
"county": "Greater London",
"state": "England",
"postcode": "SW1A 2AA",
"country": "GB",
"council": "Westminster"
},
"basis": "rule",
"evidence": [
"open map data",
"council from the official postcode directory"
]
},
"map_version": "osm-2026-10-03",
"uprn": {
"value": "100023336956",
"distance_m": 6,
"basis": "nearest"
},
"confidence": {
"level": "high",
"score": 0.95,
"basis": "geocode_checked",
"why": "rooftop"
}
},
{
"id": "wh",
"input": "1600 Pennsylvania Ave NW, Washington DC 20500",
"record_key": "rk1_0579e7bc70379e42dce9",
"address_quality": {
"value": "full_street",
"basis": "rule"
},
"status": "placed",
"location": {
"value": {
"lat": 38.8976387,
"lng": -77.0365525
},
"precision": "rooftop",
"confidence": {
"value": 0.95,
"basis": "rule",
"evidence": [
"house number 1600 matched",
"street matched (Pennsylvania Avenue Northwest)",
"postcode agrees (20500)",
"… 4 more"
]
}
},
"admin": {
"value": {
"house_number": "1600",
"street": "Pennsylvania Avenue Northwest",
"city": "Washington",
"county": "District of Columbia",
"state": "DC",
"postcode": "20500",
"country": "US"
},
"basis": "rule",
"evidence": [
"open map data"
]
},
"map_version": "osm-2026-10-03",
"confidence": {
"level": "high",
"score": 0.95,
"basis": "geocode_checked",
"why": "rooftop"
}
},
{
"id": "x",
"input": "asdfgh",
"record_key": "rk1_8588310a98676af6e225",
"address_quality": {
"value": "town_only",
"basis": "rule"
},
"status": "unplaced",
"location": {
"value": null,
"precision": "none",
"confidence": {
"value": 0.2,
"basis": "rule",
"evidence": [
"town differs (The Municipal District of Newcastle West on the map)",
"position: the centre of the town",
"nothing about it matches the input"
]
},
"why": "unreadable address: no street, town or postcode we recognise"
},
"admin": {
"value": null,
"basis": "rule",
"evidence": [
"open map data"
]
},
"map_version": "osm-2026-09-19",
"confidence": {
"level": "low",
"score": 0.2,
"basis": "not_placed",
"why": "unreadable address: no street, town or postcode we recognise"
}
}
],
"summary": {
"records": 3,
"status": {
"placed": 2,
"review": 0,
"unplaced": 1
},
"precision": {
"rooftop": 2,
"none": 1
},
"vs_paid_reference": null,
"vs_live_product": null,
"declined_but_placed_by": {
"paid_reference": [],
"live_product": []
},
"sent": 3
},
"ms": 1875,
"run": {
"tool": "geocode_batch",
"at": "2026-10-13T15:59:09.444Z",
"rows": 3,
"placed": 2,
"review": 0,
"unplaced": 1,
"not_placed": 1,
"sources": [
{
"name": "InstaMaps address index (OpenStreetMap, OpenAddresses) and postcodes.io",
"as_of": "2026-10-08"
}
],
"run_id": "run_30182f16c73e3d50",
"confidence": {
"high": 2,
"medium": 0,
"low": 1
}
}
} Every answer has a message (the answer in a sentence), the data, a run block (sources with their dates, confidence counts and a run_id any endpoint can take as source: {"{"} "run": … {"}"}), and usage (lookups this call cost and what's left today, also in the X-Lookups-Used and X-Lookups-Remaining headers). Errors are an HTTP status with {"{"} "error": "…" {"}"}: 400 can't answer, 401 key, 404 endpoint, 429 out of lookups.
The same tools as the InstaMaps MCP server, as plain HTTP. The body is the tool's input, as below.
POST /v1/geocode_batch
Geocode a list of addresses
Turn a list of addresses, business names, postcodes or coordinates into points, with a confidence and the address parts for every row.
Coverage: Worldwide; strongest in the US and Great Britain (house-level address data); council and UPRN in Great Britain.
| Field | Type | What it is |
|---|---|---|
| addresses | array, up to 100 | Addresses, one per row. |
| records | array, up to 100 | Or rows with your own ids. |
| format | string | csv: also return every row as CSV text (csv), one line per row in the order sent, to save as a file in Drive or paste into a sheet. One of: json, csv. |
| columns | array | The fields for the CSV and for write_to_sheet, in order (CSV default: status, lat, lng, precision, confidence, reason, house_number, street, city, county, state, postcode, country, council, uprn, record_key; write_to_sheet default: lat, lng, status, address, city, county, state, postcode, country, precision, confidence). ID and input always lead the CSV. council (Great Britain: the local authority) and uprn (Great Britain: the nearest UPRN to a pin on a building, within 15 m) are blank elsewhere. |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 100 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"records": [
{
"id": "hq",
"address": "10 Downing Street, London SW1A 2AA"
},
{
"id": "wh",
"address": "1600 Pennsylvania Ave NW, Washington DC 20500"
},
{
"id": "x",
"address": "asdfgh"
}
]
}Answer: 3 rows: 2 placed, 0 to review, 1 unplaced · 2 of 3 high confidence (0 medium, 1 low). Caveats: not placed (1 row).
Full reference: when to use it, sources, what's been measured →POST /v1/filter_by_location
Filter records by distance to sites
Which records are within N miles or km of one or more sites, or the nearest sites to each record, by straight-line distance.
Coverage: Worldwide (straight-line distance).
| Field | Type | What it is |
|---|---|---|
| records | array | The list to filter: {id, address} or {id, lat, lng}. |
| sites | array, up to 25 | Depots, stores, offices: {id, address} or {id, lat, lng}. |
| within_miles | number | Keep records within this many miles of any site. |
| within_km | number | Or the same in kilometres. |
| nearest_n | integer | Also list the N nearest records to each site. |
| render | boolean | Also keep the map (the sites, their radius and the records): a link to share, GeoJSON and KML. |
| title | string | The kept map's title when render is on. |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 200 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
| sites_source | object | The sites by reference, the same way as source. |
Example body
{
"records": [
{
"id": "a",
"name": "Leeds Town Hall",
"address": "Leeds Town Hall, Leeds LS1 3AD"
},
{
"id": "b",
"name": "York Minster",
"address": "York Minster, York YO1 7HH"
},
{
"id": "c",
"name": "Manchester Piccadilly",
"address": "Manchester Piccadilly station, Manchester M1 2BN"
}
],
"sites": [
{
"id": "depot",
"name": "Leeds depot",
"address": "Leeds LS1 4AP"
}
],
"within_miles": 30
}Answer: within 30 miles of the site; straight-line distance, not driving distance. 2 of 3 placed records match · 2 of 3 high confidence (1 medium, 0 low). Caveats: placed, less sure (1 row).
Full reference: when to use it, sources, what's been measured →POST /v1/get_road_distances
Road distance and drive time for journeys
Road distance and drive time for each from–to journey, on our own road network, with typical weekday traffic.
Coverage: Great Britain and the US by road; elsewhere straight line, labelled as such.
| Field | Type | What it is |
|---|---|---|
| journeys | array, up to 100 | {id, from, to}; from/to are text (address, postcode) or {lat, lng}. |
| region | string | Optional; worked out from the postcodes when left out. One of: uk, us. |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 100 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| traffic | string | weekday (default): road times with the area's measured weekday slowdown (DfT delay on local 'A' roads by council and on motorways in Great Britain; the Urban Mobility Report's Travel Time Index by US urban area). free_flow: empty roads. One of: weekday, free_flow. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"journeys": [
{
"id": "1",
"from": "Leeds LS1 4AP",
"to": "York YO1 7HH"
},
{
"id": "2",
"from": "Austin TX 78701",
"to": "Dallas TX 75201"
}
]
}Answer: 2 journeys: 2 by road (228.3 road miles) · 0 of 2 high confidence (2 medium, 0 low). Caveats: postcode centre (2 rows); street or named place (1 row).
Full reference: when to use it, sources, what's been measured →POST /v1/get_travel_time_area
Area reachable within a travel time
The area reachable from a place within N minutes by car, on foot or by bike, and which of your records fall inside each band.
Coverage: Great Britain and the US on our roads, with measured weekday traffic for driving.
| Field | Type | What it is |
|---|---|---|
| originrequired | object | An address or {lat, lng}. |
| minutes | array, up to 3 | |
| mode | string | One of: drive, walk, cycle. |
| records | array, up to 500 | {id, address} or {id, lat, lng}. Send your own ids to merge results back. |
| addresses | array, up to 500 | Or plain addresses/postcodes, numbered from 1. |
| include_geometry | boolean | |
| render | boolean | Also keep the map (the bands, the origin and the records): a link, GeoJSON and KML. |
| title | string | The kept map's title when render is on. |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 150 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| traffic | string | weekday (default): road times with the area's measured weekday slowdown (DfT delay on local 'A' roads by council and on motorways in Great Britain; the Urban Mobility Report's Travel Time Index by US urban area). free_flow: empty roads. One of: weekday, free_flow. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"origin": "Leeds LS1 4AP",
"minutes": [
15,
30
],
"addresses": [
"York YO1 7HH",
"Harrogate HG1 1HN"
]
}Answer: drive from Leeds LS1 4AP: 15 min 155 km² (0 records inside), 30 min 1023 km² (0 records inside) · 0 of 2 high confidence (2 medium, 0 low). Caveats: street or named place (1 row); postcode centre (1 row).
Full reference: when to use it, sources, what's been measured →POST /v1/find_postcodes_in_radius
Every ZIP code or postcode within a radius
Every US ZIP code, or UK postcode sector or district, within a radius of a place, nearest first.
Coverage: US (Census ZIP code areas) and the UK (postcode sectors and districts).
| Field | Type | What it is |
|---|---|---|
| centerrequired | string | A ZIP ("10001"), a UK postcode, sector or district ("SW1A 1AA", "SW1A 1", "SW1A"), an address, or "lat,lng". |
| radiusrequired | number | Up to 500 miles or 800 km. |
| unit | string | One of: mi, km. |
| granularity | string | UK only: postcode sectors ("SW1A 1") or districts ("SW1A"). One of: sector, district. |
| country | string | Optional: worked out from the centre. One of: us, gb. |
| limit | number | Most areas to list, nearest first (up to 2,500); the total found is always given. |
| render | boolean | |
| title | string |
Example body
{
"center": "10001",
"radius": 1,
"limit": 5
}Answer: 9 ZIP codes within 1 mi of 10001 (nearest 5 listed; raise limit for more)
Full reference: when to use it, sources, what's been measured →POST /v1/plan_routes
Plan routes for one or more drivers
Split up to 100 stops across up to 10 drivers from one depot, in the best order on real roads, with Google Maps links per driver.
Coverage: Great Britain and the US on our roads; elsewhere straight-line estimates, labelled.
| Field | Type | What it is |
|---|---|---|
| depotrequired | object | Where the drivers start: an address or {lat, lng}. |
| stops | array, up to 100 | Addresses, or {id, name, address} / {id, name, lat, lng}. name labels the stop on the map and in the plan. |
| drivers | integer | |
| return_to_depot | boolean | |
| shift_hours | number | |
| service_minutes | number | Time spent at each stop. |
| render | boolean | Also keep the map: a link to share with the drivers, GeoJSON and KML. |
| title | string | The kept map's title when render is on. |
| traffic | string | weekday (default): road times with the area's measured weekday slowdown (DfT delay on local 'A' roads by council and on motorways in Great Britain; the Urban Mobility Report's Travel Time Index by US urban area). free_flow: empty roads. One of: weekday, free_flow. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"depot": "Canning Town, London E16 1DQ",
"stops": [
{
"id": "0",
"address": "Stratford Station, London E15 1AZ"
},
{
"id": "1",
"address": "Hackney Central, London E8 1LL"
},
{
"id": "2",
"address": "Bethnal Green Road, London E2 6AH"
},
{
"id": "3",
"address": "Bow Road, London E3 4DH"
},
{
"id": "4",
"address": "Leyton High Road, London E10 5NA"
}
],
"drivers": 1
}Answer: 5 stops across 1 driver(s) · 1 of 5 high confidence (4 medium, 0 low). Caveats: street or named place (4 rows).
Full reference: when to use it, sources, what's been measured →POST /v1/ask_table
Ask a question about a table
Answer a plain-English question about a whole table (filters, counts, distances to a named place or a second list), showing how it read the question.
Coverage: Any table; place questions use our UK and US geography.
| Field | Type | What it is |
|---|---|---|
| questionrequired | string | The question, as a person would ask it. |
| records | array, up to 5000 | The table as row objects (keys are the column names). |
| headers | array | Or the column names… |
| rows | array, up to 5000 | …and the rows as arrays in the same order. |
| mode | string | One of: rows, match, why. |
| reference_records | array | Optional second list for two-list questions (depots, competitors, stores). |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"question": "Which accounts have annual revenue over 50k?",
"records": [
{
"Account": "Rice University",
"Address": "6100 Main St Houston TX 77005",
"Annual revenue": 82000
},
{
"Account": "Museum of Fine Arts",
"Address": "1001 Bissonnet St Houston TX 77005",
"Annual revenue": 23000
},
{
"Account": "Toyota Center",
"Address": "1510 Polk St Houston TX 77002",
"Annual revenue": 61000
}
]
}Answer: Read as: Annual revenue > 50,000. 2 of 3 rows match
Full reference: when to use it, sources, what's been measured →POST /v1/get_location_facts
Official areas and zones for each address
The official areas each address falls in: US census tract, income level, county, metro, HUBZone, Opportunity Zone, USDA eligibility, FEMA flood zone; GB conservation area, listed buildings, nearest UPRN, England flood zone.
Coverage: US and Great Britain (England for flood zones and planning constraints; Article 4 and tree preservation orders where the council has published them: 112 and 81 councils).
| Field | Type | What it is |
|---|---|---|
| records | array, up to 200 | {id, address} or {id, lat, lng}. Send your own ids to merge results back. |
| addresses | array, up to 200 | Or plain addresses/postcodes, numbered from 1. |
| fields | array | Only these facts (default: all that apply). flood is FEMA in the US, the Environment Agency in England. |
| region | string | Optional; worked out per address from its postcode or ZIP. One of: us, uk. |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 150 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"addresses": [
"10 Downing Street, London SW1A 2AA",
"1600 Pennsylvania Ave NW, Washington DC 20500"
]
}Answer: 2 of 2 placed and checked
Full reference: when to use it, sources, what's been measured →POST /v1/get_area_risk
Crime, flood or natural-hazard risk for each place
One risk fact per place: recorded crime nearby (England and Wales) with the commonest types, flood zone (England, US), or FEMA natural-hazard rating (US). Flood answers also compare: base flood elevation, the neighbourhood's river and coastal flooding with its national percentile (US), the rank on the list and a sentence in words, on a map over the official flood zones.
Coverage: Crime: England and Wales (police.uk, latest month). Flood: England and US. Hazard: US census tracts (FEMA National Risk Index).
| Field | Type | What it is |
|---|---|---|
| metricrequired | string | One of: crime, flood, hazard. |
| kind | string | |
| records | array, up to 250 | {id, address} or {id, lat, lng}. Send your own ids to merge results back. |
| addresses | array, up to 250 | Or plain addresses/postcodes, numbered from 1. |
| render | boolean | flood: also keep the map (the places by risk over the flood zones): a link to share, GeoJSON and KML. |
| title | string | The kept map's title when render is on. |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 200 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"metric": "flood",
"addresses": [
"York YO1 7HH",
"10 Downing Street, London SW1A 2AA"
]
}Answer: flood zone: 2 of 2 answered · 1 of 2 high confidence (1 medium, 0 low). Caveats: street or named place (1 row).
Full reference: when to use it, sources, what's been measured →POST /v1/get_live_hazards
Flood, storm and earthquake warnings in force now
Warnings and events in force now: England's flood warnings, US weather warnings, and worldwide earthquake shaking, hurricanes, floods, wildfires and volcanoes, with kind, level, area, times and outline.
Coverage: England (Environment Agency), the US (National Weather Service), and worldwide: earthquakes M4.5+ of the past week with a ShakeMap (USGS), Atlantic and Pacific storms (National Hurricane Center), and GDACS floods, wildfires, volcanoes and other cyclones (automatic estimates). Refreshed every 10 minutes.
| Field | Type | What it is |
|---|---|---|
| region | string | gb: England's flood warnings and world events touching Great Britain; us: National Weather Service warnings and world events touching the US; world: the earthquake, hurricane and GDACS feeds only; all: everything. One of: gb, us, world, all. |
| perils | array | Only these perils (default: all). |
| min_level | string | Only this level and above (default: all). One of: severe, warning, watch, advisory. |
| render | boolean | |
| title | string |
Example body
{
"region": "us",
"min_level": "warning"
}Answer: 7 warnings in force (7 warning): 7 flood
Full reference: when to use it, sources, what's been measured →POST /v1/check_live_hazards
Which of your places are inside a live warning or event
Which of your places are inside or near a warning or event now (or were hit by one), with insured values added up.
Coverage: Everything get_live_hazards covers: England and US warnings, and worldwide earthquakes, hurricanes and GDACS events. Refreshed every 10 minutes.
| Field | Type | What it is |
|---|---|---|
| records | array, up to 500 | {id, address} or {id, lat, lng}. Send your own ids to merge results back. |
| addresses | array, up to 500 | Or plain addresses/postcodes, numbered from 1. |
| near_km | number | Also flag places within this distance of a warning (0 to 50 km). |
| value_field | string | The records' field to add up (e.g. "TIV"); found automatically when it is called TIV, sum insured, insured value or value. |
| region | string | One of: gb, us, all. |
| perils | array | |
| min_level | string | One of: severe, warning, watch, advisory. |
| render | boolean | |
| title | string | |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 500 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"records": [
{
"id": "leeds",
"address": "Leeds LS1 4AP",
"TIV": 2500000
},
{
"id": "austin",
"address": "500 Congress Avenue, Austin, TX 78701",
"TIV": 900000
}
]
}Answer: 0 of 2 places inside a live warning, 0 within 5 km of one, 2 clear · value inside 0, near 0 (28 warnings in force) · 1 of 2 high confidence (1 medium, 0 low). Caveats: postcode centre (1 row).
Full reference: when to use it, sources, what's been measured →POST /v1/find_nearby
Places of a kind near each address
The nearest, the count, or a list of places of a kind (stations, schools, supermarkets, pharmacies…) around each address.
Coverage: UK and US, from OpenStreetMap; each answer says how well that kind of place is mapped.
| Field | Type | What it is |
|---|---|---|
| categoryrequired | string | |
| mode | string | One of: nearest, count, list. |
| radius_km | number | Default 10 km for nearest, 2 km otherwise. |
| n | integer | How many places to return per record. |
| records | array, up to 500 | {id, address} or {id, lat, lng}. Send your own ids to merge results back. |
| addresses | array, up to 500 | Or plain addresses/postcodes, numbered from 1. |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 150 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"category": "pharmacy",
"addresses": [
"Leeds LS1 4AP"
],
"n": 3
}Answer: Pharmacy (nearest, 10 km): 1 of 1 placed · 0 of 1 high confidence (1 medium, 0 low). Caveats: postcode centre (1 row); open map data, not the official register (1 row).
Full reference: when to use it, sources, what's been measured →POST /v1/find_official_places
Official registers near each address (UK)
The official record: A&E departments, hospitals, GP practices, care homes and dentists with CQC ratings, NHS pharmacies, food hygiene ratings; or the record of the business at each row.
Coverage: England for CQC, England and Wales for NHS pharmacies, the UK for food hygiene.
| Field | Type | What it is |
|---|---|---|
| kindrequired | string | One of: ae, hospital, urgent_care, gp, care_home, nursing_home, dentist, hospice, pharmacy, food. |
| mode | string | at: the registered place at each address itself (send name). One of: nearest, count, list, at. |
| radius_km | number | How far to look. Defaults: A&E 60, hospital 30, GP 10, care home 10, pharmacy 5, food 1. |
| n | integer | How many places to return per record. |
| rating | array | CQC ratings to keep, e.g. ["Requires improvement", "Inadequate"]. For A&E, the rating of its urgent and emergency services. |
| nhs | boolean | Hospitals: true for NHS only, false for independent only. |
| include_specialist | boolean | A&E: also the eye and children's hospitals' emergency departments (left out by default). |
| food_type | string | restaurant, takeaway, pub, supermarket, shop, hotel, school, caring, mobile or manufacturer. |
| min_hygiene | integer | |
| max_hygiene | integer | |
| records | array, up to 500 | {id, address} or {id, lat, lng}. Send your own ids to merge results back. |
| addresses | array, up to 500 | Or plain addresses/postcodes, numbered from 1. |
| background | boolean | With source: run as a background job and answer at once with job_id (automatic past 200 rows). Check with get_job; write_to_sheet with the job_id puts the results in the sheet as they finish. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
Example body
{
"kind": "gp",
"addresses": [
"Leeds LS1 4AP"
],
"n": 2
}Answer: GP practice (nearest, 10 km): 1 of 1 records have one · 0 of 1 high confidence (1 medium, 0 low). Caveats: postcode centre (1 row).
Full reference: when to use it, sources, what's been measured →POST /v1/render_map
Make a map to keep, share or change
A hosted, layered map to keep or share: pins, lines or areas, colours by field, a legend, GeoJSON and KML.
Coverage: Worldwide.
| Field | Type | What it is |
|---|---|---|
| title | string | The map's title (and how to find it again). |
| layers | array, up to 20 | One or more layers, drawn in order (later ones on top). |
| legend | boolean | |
| rows | array, up to 2500 | Shortcut for a one-layer map: rows with lat/lng or addresses. |
| color_by | string | With rows: the field to colour the pins by. |
| flood_zones | boolean | Draw the official flood zones under the layers: FEMA's in the US (they show from street level) and the Environment Agency's in England. |
| source | object | Instead of typing rows: { sheet: "<Google Sheets link>", tab?: "Sites" } (shared with the InstaMaps service account, or viewable by anyone with the link), { file: "<Drive link to a CSV or Excel file>" }, or { run: "<run_id from an earlier answer>" }. Columns are found by their headers (id, name, address or its parts, lat/lng); name them if they aren't obvious (id_column, address_column, lat_column, lng_column; from_column and to_column for road distances). Rows with coordinates are used as they are. |
| from_run | string | A run_id from an earlier answer: its rows as the map's pins (with color_by, bins and labels), in one call. |
| bins | array | With from_run, source or rows and color_by on a number: band breaks. |
| labels | boolean | With from_run, source or rows: names on the map. |
Example body
{
"title": "Docs example: two depots",
"rows": [
{
"id": "leeds",
"name": "Leeds depot",
"lat": 53.7966,
"lng": -1.5484
},
{
"id": "york",
"name": "York depot",
"lat": 53.958,
"lng": -1.0803
}
]
}Answer: Made "Docs example: two depots": 1 layer(s), 2 pins: https://get-instamaps.com/v/9hd9pnytqs
Full reference: when to use it, sources, what's been measured →POST /v1/update_map
Change a kept map
Change a kept map in place: add or remove layers, move or add pins, recolour, rename; the link stays the same and earlier versions are kept.
Coverage: Worldwide.
| Field | Type | What it is |
|---|---|---|
| maprequired | string | The map_id or link render_map returned. |
| title | string | A new title. |
| add_layers | array | |
| remove_layers | array | Names of layers to remove. |
| update_layers | array | |
| upsert_points | array | Move, rename or re-field a pin by its id, or add a new one (new pins need lat/lng or an address). |
| remove_points | array | |
| legend | boolean | |
| flood_zones | boolean | true: draw the official flood zones under the layers (FEMA in the US, the Environment Agency in England); false: take them off. |
| revert_to | integer | Put this earlier version back (it becomes the newest version; nothing is lost). |
Example body
{
"map": "9hd9pnytqs",
"upsert_points": [
{
"layer": "Rows",
"id": "harrogate",
"name": "Harrogate depot",
"lat": 53.9921,
"lng": -1.5418
}
]
}Answer: Updated "Docs example: two depots" to version 2: added harrogate to "Rows". Same link: https://get-instamaps.com/v/9hd9pnytqs
Full reference: when to use it, sources, what's been measured →POST /v1/get_map
Look at a kept map
Look at a kept map from an earlier conversation: its layers, pin ids and fields. With no map named, list the person's own maps, including the ones they made in the InstaMaps Google Sheets add-on.
Coverage: Maps made with render_map or a tool's render, and the signed-in person's own Sheets add-on maps.
| Field | Type | What it is |
|---|---|---|
| map | string | The map_id or link. Leave out to list the person's maps. |
| layer | string | A layer whose pins to list ("pins" for a Sheets add-on map). |
Example body
{
"map": "9hd9pnytqs"
}Answer: "Docs example: two depots" version 2: Rows (3 pins)
Full reference: when to use it, sources, what's been measured →POST /v1/delete_map
Delete maps for good
Delete the person's own maps for good, made here or in the InstaMaps Google Sheets add-on: the link stops working and the pins, versions, logbook and photos go with it.
Coverage: Only maps the signed-in person made; anyone else's reads as not found.
| Field | Type | What it is |
|---|---|---|
| mapsrequired | array, up to 25 | The map_ids or links to delete. |
POST /v1/combine_runs
Combine kept runs on the same places
Join two to six kept runs on the place ID every tool returns (record_key) and say what changed between them.
Coverage: Any runs from earlier answers (run_ids) or tables you send.
| Field | Type | What it is |
|---|---|---|
| runsrequired | array, up to 6 | Oldest first. |
| key | string | The place ID column every run has. |
| columns | array | Only these columns from each run (default: all). |
| compare | array | Columns to compare between runs: numbers get the change, text whether it changed. |
| only_changed | boolean |
Example body
{
"runs": [
"run_… (geocode_batch)",
"run_… (get_area_risk flood)"
],
"key": "record_key"
}Answer: 2 places across 2 runs, 2 in every run
Full reference: when to use it, sources, what's been measured →POST /v1/get_job
How far a background job has got
How far a background job has got: status, rows done, minutes left, and its run_id when done.
Coverage: Jobs started by the same person; checking costs no calls.
| Field | Type | What it is |
|---|---|---|
| job_idrequired | string |
POST /v1/write_to_sheet
Put an answer into a Google Sheet
Put an earlier answer into a Google Sheet: new dated columns beside the rows it came from, or a new tab. Never overwrites a cell. The only tool that writes.
Coverage: Google Sheets shared with the InstaMaps service account as Editor; rows are matched by id, and a row that now holds a different place is skipped and named.
| Field | Type | What it is |
|---|---|---|
| run_id | string | The run_id from an answer (run.run_id), or from get_job when a job is done. |
| job_id | string | Or a background job's job_id. |
| sheet | string | A Google Sheets link. Default: the sheet the rows came from. |
| tab | string | The tab. Default: the tab the rows came from. |
| mode | string | beside: new columns next to the rows they came from (the default when the run came from this tab). new_tab: the rows as a table in a new tab (the default for any other sheet). One of: beside, new_tab. |
| columns | array | Which of the answer's fields to write, by name (e.g. "Latitude", "Confidence", "Nearest A&E", or geocode keys such as postcode or uprn). Default: the tool's usual columns. |
Example body
{
"run_id": "run_ae02fe5fb0d18808",
"mode": "new_tab",
"columns": [
"lat",
"lng",
"postcode",
"council",
"uprn",
"confidence"
]
}Answer: Wrote 3 rows to "geocode_batch · 2026-10-13 17:36" (a new tab) in InstaMaps write_to_sheet test (landmarks), and a line in "InstaMaps runs".
Full reference: when to use it, sources, what's been measured →A call that fails costs nothing.
Free
2,500 lookups a day
Every endpoint, no card. About 75,000 a month. Resets at midnight UTC.
Get a keyMore than 2,500 a day
Tell us what you're building
Need more than that? Write to gbade@get-instamaps.com and tell us what you are building.
Email us| InstaMaps API | Google Maps Platform | |
|---|---|---|
| Free allowance | 2,500 lookups a day (about 75,000 a month), across every endpoint | Up to 10,000 free calls a month for each API (Geocoding, Routes and so on, counted separately) |
| Keeping results | Store them in your own database for as long as you like | Coordinates may be cached for at most 30 days |
| Showing them on a map | Any map | Only on a Google map |
| In one API | Geocoding, road distances, route plans for up to 10 drivers, drive-time areas, flood and crime risk, official facts, places nearby, questions over a table, hosted maps | Separate APIs and keys for each |
| Confidence per row | Every row: high, medium or low, with the reason and what to do about it | A location type per result |
Google's terms and free allowances as published by Google, October 2026 (Google Maps Platform Terms of Service; pricing page).
Is there a free geocoding API?
Yes. The InstaMaps API geocodes 2,500 addresses a day free, with a confidence for every row and the address parts (city, county, state, postcode; in Great Britain the council and UPRN). Get a key with a Google sign-in in the developer portal, get-instamaps.com/developers/portal; no card.
What is a cheaper alternative to the Google Maps Geocoding API?
The InstaMaps API: 2,500 free lookups every day across geocoding, road distances, routes and risk, results you can store for as long as you like (Google allows 30 days), and no rule that they go on a Google map. It runs on InstaMaps' own address index and roads, strongest in the US and Great Britain.
Can I store the results?
Yes. There is no cache limit: keep the coordinates, distances and answers in your own database. Every answer names its sources and their dates; some are OpenStreetMap data (© OpenStreetMap contributors), which asks for a credit.
Is there an API for road distances and drive times between many addresses?
Yes: POST /v1/get_road_distances takes up to 100 journeys a call (bigger lists by reference run as a background job) and returns road miles, kilometres and drive time for each, as weekday estimates; plan_routes orders up to 100 stops across up to 10 drivers.
Does the API include =ASK?
Yes: POST /v1/ask_table answers a plain-English question about a whole table ("customers in Texas with revenue over 50k"), the same as the =ASK formula in the Google Sheets add-on, and shows how it read the question. A question is 10 lookups, however long the table.
How do I get an API key?
Sign in with Google in the developer portal (get-instamaps.com/developers/portal) and press Make a key. It is shown once; keep it secret and send it as Authorization: Bearer im_live_… (or X-API-Key). The portal shows your lookups today and over the last 30 days, by endpoint and by key, and lets you name, rename and revoke up to 5 keys.
How much does the InstaMaps API cost?
Nothing. It is free: 2,500 lookups a day per account, across every endpoint, reset at midnight UTC, no card. Need more? Write to gbade@get-instamaps.com.
Is it the same as the InstaMaps MCP server?
The same tools and engines. The MCP server is for AI assistants (Claude, ChatGPT and others) and counts calls; the API is for code and counts lookups. One Google sign-in covers both, so runs and maps are shared.