Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: InstaMaps Measure API
version: 0.6.0
description: 'Location data for lists, as one REST endpoint per job: geocode with a confidence per row, straight-line and road distances,
multi-driver route plans, drive-time areas, official facts (census tract, HUBZone, flood zones), flood, crime and natural-hazard
risk, live warnings, places nearby, plain-English questions over a table, and hosted maps. Strongest in the US and Great Britain,
on our own address index, roads and official data. The same tools as the InstaMaps MCP server, as plain HTTP.
**Auth.** Authorization: Bearer (or X-API-Key). Keys are free: sign in with Google at /developers/portal.
**Free.** 2,500 lookups a day per account, every endpoint, reset at midnight UTC. No card.
**What counts as a lookup.**
- One lookup per row a call carries: an address placed, a journey measured, a stop routed, a place checked.
- A question to ask_table is 10 lookups, however long the table.
- A drive-time area is 10 lookups a band, plus one per place checked against it.
- Maps, live hazards and postcode-radius lists are one lookup a call. Checking a background job (get_job) is free.
- Rows sent by reference (a Google Sheet, a Drive file or an earlier run) are counted from the answer.
**Keep what you get.** No 30-day cache rule: store the results in your own database for as long as you like. Every answer names its sources and their dates.
**Every answer:**
- Nothing is dropped: every row sent comes back, in order, under your own id; rows that cannot be placed or answered say why. An answer that would lose rows fails loudly instead.
- Every row carries confidence {level: high | medium | low, score, basis}; basis is a stable code (rooftop, postcode_centre, not_placed…) and the answer''s confidence object says what each basis present means and what to do about it.
- Every row carries record_key, the same place ID from every tool, so answers from different tools join on it.
- Every answer ends with a run block: when, how many rows, sources with their dates, the confidence counts, calls used and left today, and a run_id that any tool can take as source {run} and render_map as from_run.
- Lists by reference: pass a Google Sheet, a Drive file or a run_id instead of typing rows. Every tool but one only reads; write_to_sheet puts an answer into the sheet as new dated columns or a new tab, never overwriting.
- No vendor or model names in answers; every source is named with its date.
Docs: https://get-instamaps.com/developers'
contact:
name: InstaMaps
email: hello@get-instamaps.com
url: https://get-instamaps.com/developers
termsOfService: https://get-instamaps.com/terms
servers:
- url: https://get-instamaps.com
description: InstaMaps
security:
- apiKey: []
tags:
- name: Measure
paths:
/v1/filter_by_location:
post:
operationId: filter_by_location
summary: Which records are within N miles or km of one or more sites, or the nearest…
description: 'Which records are within a distance of any site, the nearest site to each record, and/or the N nearest records to each site. Records and sites can be addresses (placed first, up to 100 addresses per call) or lat/lng (up to 2000 records, 25 sites). Distances are straight-line (great-circle), not driving. Every record says which site it was measured to and how far; records held for review are flagged and records that could not be placed are listed, never silently counted in or out. Over 200 records the answer is compact: every record''s nearest site as [id, site, miles], full detail for the matches only. The map shows in the chat by itself. Set render to true only when the user wants to keep or share the map: it returns a link, GeoJSON and KML, and update_map can change it later.
Use when:
- "Customers within 25 miles of our depots"
- The nearest store or branch to each customer
- Large lists where speed matters more than road distance
Not for:
- Driving distance or time: get_road_distances
- Everything reachable in N minutes: get_travel_time_area
- Every ZIP or postcode inside a radius: find_postcodes_in_radius
Coverage: Worldwide for rows with coordinates (straight-line distance); addresses are placed as geocode_batch places them.
Reference: https://get-instamaps.com/mcp-server/tools/filter_by_location'
tags:
- Measure
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
records:
type: array
items:
type: object
properties:
id:
type: string
address:
type: string
lat:
type: number
lng:
type: number
label:
type: string
description: 'The list to filter: {id, address} or {id, lat, lng}.'
sites:
type: array
items:
type: object
properties:
id:
type: string
address:
type: string
lat:
type: number
lng:
type: number
label:
type: string
maxItems: 25
description: 'Depots, stores, offices: {id, address} or {id, lat, lng}.'
within_miles:
type: number
description: Keep records within this many miles of any site.
within_km:
type: number
description: Or the same in kilometres.
nearest_n:
type: integer
minimum: 1
maximum: 100
description: Also list the N nearest records to each site.
render:
type: boolean
default: false
description: 'Also keep the map (the sites, their radius and the records): a link to share, GeoJSON and KML.'
title:
type: string
description: The kept map's title when render is on.
background:
type: boolean
description: '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:
type: object
description: '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.'
properties:
sheet:
type: string
tab:
type: string
range:
type: string
description: e.g. "A1:H501"; the first row is the header.
file:
type: string
run:
type: string
id_column:
type: string
name_column:
type: string
address_column:
type: string
lat_column:
type: string
lng_column:
type: string
from_column:
type: string
to_column:
type: string
sites_source:
type: object
description: The sites by reference, the same way as source.
properties:
sheet:
type: string
tab:
type: string
range:
type: string
description: e.g. "A1:H501"; the first row is the header.
file:
type: string
run:
type: string
id_column:
type: string
name_column:
type: string
address_column:
type: string
lat_column:
type: string
lng_column:
type: string
from_column:
type: string
to_column:
type: string
required: []
example:
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
responses:
'200':
description: 'The answer. For example: "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)."'
headers:
X-Lookups-Used:
schema:
type: integer
description: Lookups this call cost.
X-Lookups-Remaining:
schema:
type: integer
description: Free lookups left today.
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: The answer in one or two sentences.
additionalProperties: true
'400':
description: The request could not be answered; error says why.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'401':
description: No API key, or an unknown or revoked one.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'404':
description: No such endpoint.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'429':
description: Today's free lookups are used up (or the call needs more than are left), or too many requests a minute.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
/v1/get_road_distances:
post:
operationId: get_road_distances
summary: Road distance and drive time for each from–to journey, on our own road network…
description: 'Road miles, km and drive time for up to 100 journeys per call, on our own routing (Great Britain and US roads, normal traffic, no live traffic). Ends can be addresses, UK postcodes or districts (CO10), US addresses, or lat/lng. Every journey also gets the straight-line miles; a journey with no road route (Northern Ireland, an island without a bridge) is measured in a straight line and says so in `note`. The summary has the total road miles (for mileage claims) and the total with straight-line journeys included.
Use when:
- Mileage claims and expense checks
- Depot-to-customer drive times
- Comparing journeys where straight-line distance would mislead
Not for:
- Visiting many stops in the best order: plan_routes
- Everything reachable in N minutes: get_travel_time_area
Coverage: Great Britain and the US by road; elsewhere straight line, labelled as such.
Reference: https://get-instamaps.com/mcp-server/tools/get_road_distances'
tags:
- Measure
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
journeys:
type: array
maxItems: 100
items:
type: object
properties:
id:
type: string
from: {}
to: {}
required:
- from
- to
description: '{id, from, to}; from/to are text (address, postcode) or {lat, lng}.'
region:
type: string
enum:
- uk
- us
description: Optional; worked out from the postcodes when left out.
background:
type: boolean
description: '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:
type: string
enum:
- weekday
- free_flow
default: weekday
description: '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.'
source:
type: object
description: '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.'
properties:
sheet:
type: string
tab:
type: string
range:
type: string
description: e.g. "A1:H501"; the first row is the header.
file:
type: string
run:
type: string
id_column:
type: string
name_column:
type: string
address_column:
type: string
lat_column:
type: string
lng_column:
type: string
from_column:
type: string
to_column:
type: string
required: []
example:
journeys:
- id: '1'
from: Leeds LS1 4AP
to: York YO1 7HH
- id: '2'
from: Austin TX 78701
to: Dallas TX 75201
responses:
'200':
description: 'The answer. For example: "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)."'
headers:
X-Lookups-Used:
schema:
type: integer
description: Lookups this call cost.
X-Lookups-Remaining:
schema:
type: integer
description: Free lookups left today.
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: The answer in one or two sentences.
additionalProperties: true
'400':
description: The request could not be answered; error says why.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'401':
description: No API key, or an unknown or revoked one.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'404':
description: No such endpoint.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'429':
description: Today's free lookups are used up (or the call needs more than are left), or too many requests a minute.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
/v1/get_travel_time_area:
post:
operationId: get_travel_time_area
summary: The area reachable from a place within N minutes by car, on foot or by bike…
description: 'The area you can reach from one place within 5 to 60 minutes (up to three bands) driving, walking or cycling, with its size; and, given records (up to 500 with lat/lng, or 200 addresses), which band each record falls in: "which customers are within 30 minutes'' drive of the depot". Our own routing on Great Britain and US roads; elsewhere an open routing service. Set include_geometry to get the GeoJSON polygons (larger answer). The bands show on a map in the chat by itself. Set render to true only when the user wants to keep or share the map: it returns a link, GeoJSON and KML, and update_map can change it later.
Use when:
- "Customers within a 30-minute drive"
- Service areas and catchments
- Comparing what two sites can reach
Not for:
- A fixed-distance circle: filter_by_location or find_postcodes_in_radius
Coverage: Great Britain and the US on our roads, with measured weekday traffic for driving.
Reference: https://get-instamaps.com/mcp-server/tools/get_travel_time_area'
tags:
- Measure
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
origin:
description: An address or {lat, lng}.
minutes:
type: array
items:
type: integer
minimum: 5
maximum: 60
maxItems: 3
default:
- 30
mode:
type: string
enum:
- drive
- walk
- cycle
default: drive
records:
type: array
maxItems: 500
items:
type: object
properties:
id:
type: string
description: Your id for the row; results come back under it.
name:
type: string
description: What to call the place on the map.
address:
type: string
lat:
type: number
lng:
type: number
description: '{id, address} or {id, lat, lng}. Send your own ids to merge results back.'
addresses:
type: array
maxItems: 500
items:
type: string
description: Or plain addresses/postcodes, numbered from 1.
include_geometry:
type: boolean
default: false
render:
type: boolean
default: false
description: 'Also keep the map (the bands, the origin and the records): a link, GeoJSON and KML.'
title:
type: string
description: The kept map's title when render is on.
background:
type: boolean
description: '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:
type: string
enum:
- weekday
- free_flow
default: weekday
description: '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.'
source:
type: object
description: '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.'
properties:
sheet:
type: string
tab:
type: string
range:
type: string
description: e.g. "A1:H501"; the first row is the header.
file:
type: string
run:
type: string
id_column:
type: string
name_column:
type: string
address_column:
type: string
lat_column:
type: string
lng_column:
type: string
from_column:
type: string
to_column:
type: string
required:
- origin
example:
origin: Leeds LS1 4AP
minutes:
- 15
- 30
addresses:
- York YO1 7HH
- Harrogate HG1 1HN
responses:
'200':
description: 'The answer. For example: "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)."'
headers:
X-Lookups-Used:
schema:
type: integer
description: Lookups this call cost.
X-Lookups-Remaining:
schema:
type: integer
description: Free lookups left today.
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: The answer in one or two sentences.
additionalProperties: true
'400':
description: The request could not be answered; error says why.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'401':
description: No API key, or an unknown or revoked one.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'404':
description: No such endpoint.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'429':
description: Today's free lookups are used up (or the call needs more than are left), or too many requests a minute.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
/v1/find_postcodes_in_radius:
post:
operationId: find_postcodes_in_radius
summary: Every US ZIP code, or UK postcode sector or district, within a radius of a…
description: 'Every US ZIP code, or every UK postcode sector (or district), whose centre is within a radius of a place, nearest first with the distance. The centre can be a ZIP, a UK postcode, sector or district, an address, or "lat,lng". For service areas, delivery zones, direct-mail and ad targeting lists. Straight-line distance between centres (an area counts when its centre is inside). Free: our own copy of the Census ZIP centres and the UK postcode centres. The answer has a run_id: write it into a sheet or map it (render_map from_run). For "who on MY list is within X miles", use filter_by_location instead. Set render to true only when the user wants to keep or share the map: it returns a link, GeoJSON and KML, and update_map can change it later.
Use when:
- Service areas, delivery zones and direct-mail lists
- "Which ZIP codes are within 25 miles of 10001?"
- Ad targeting by postcode
Not for:
- Which of YOUR records are within a radius: filter_by_location
Coverage: US (Census ZIP code areas) and the UK (postcode sectors and districts).
Reference: https://get-instamaps.com/mcp-server/tools/find_postcodes_in_radius'
tags:
- Measure
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
center:
type: string
description: A ZIP ("10001"), a UK postcode, sector or district ("SW1A 1AA", "SW1A 1", "SW1A"), an address, or "lat,lng".
radius:
type: number
description: Up to 500 miles or 800 km.
unit:
type: string
enum:
- mi
- km
default: mi
granularity:
type: string
enum:
- sector
- district
default: sector
description: 'UK only: postcode sectors ("SW1A 1") or districts ("SW1A").'
country:
type: string
enum:
- us
- gb
description: 'Optional: worked out from the centre.'
limit:
type: number
default: 500
description: Most areas to list, nearest first (up to 2,500); the total found is always given.
render:
type: boolean
title:
type: string
required:
- center
- radius
example:
center: '10001'
radius: 1
limit: 5
responses:
'200':
description: 'The answer. For example: "9 ZIP codes within 1 mi of 10001 (nearest 5 listed; raise limit for more)"'
headers:
X-Lookups-Used:
schema:
type: integer
description: Lookups this call cost.
X-Lookups-Remaining:
schema:
type: integer
description: Free lookups left today.
content:
application/json:
schema:
type: object
properties:
message:
type: string
description: The answer in one or two sentences.
additionalProperties: true
'400':
description: The request could not be answered; error says why.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'401':
description: No API key, or an unknown or revoked one.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'404':
description: No such endpoint.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
'429':
description: Today's free lookups are used up (or the call needs more than are left), or too many requests a minute.
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
components:
securitySchemes:
apiKey:
type: http
scheme: bearer
bearerFormat: im_live_…
description: 'Authorization: Bearer <your API key> (or X-API-Key). Keys are free: sign in with Google at /developers/portal.'
externalDocs:
description: Docs, pricing and examples
url: https://get-instamaps.com/developers