Getting Started
Mapsi provides enterprise-grade geocoding and mapping APIs with global coverage. Our APIs support worldwide address search without requiring country codes.
🌍 Global Coverage
Search addresses worldwide. Country codes are optional - use them to improve accuracy when you know the target region.
Base URL
https://mapsi.devKey Features
- Global Search - No country code required
- High Accuracy - 90%+ accuracy in major markets
- Fast Response - Sub-100ms average response time
- Multiple Languages - Response language support
Authentication
All API requests require authentication using your API key in the request headers:
X-API-Key: your_api_key_hereGet your API key from the Dashboard.
Rate Limits
Rate limits vary by subscription tier:
| Plan | Rate Limit | Daily Limit | Batch Size |
|---|---|---|---|
| Free | 2 req/sec | 1,000/day | 10 records |
| Growth | 15 req/sec | 35,000/day | 5,000 records |
| Business | 25 req/sec | 140,000/day | 30,000 records |
| Enterprise | 100 req/sec | Custom | 100,000 records |
Geocoding API
Convert addresses and place names into geographic coordinates with high accuracy.
Endpoint
GET /v1/geocodeParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Address or place name to geocode |
countries | string | No | Optional. Comma-separated ISO country codes (max 4). Example: FR or FR,DE,IT |
limit | integer | No | Maximum number of results (default: 5, max: 25) |
lang | string | No | Response language code (default: en). Example: de, fr, es |
focus.lat / focus.lon | float | No | Bias results toward this location for local relevance |
cURL
curl -X GET "https://mapsi.dev/v1/geocode?q=Eiffel+Tower+Paris&limit=5" \
-H "X-API-Key: YOUR_API_KEY"
# With optional country filter:
curl -X GET "https://mapsi.dev/v1/geocode?q=Eiffel+Tower+Paris&countries=FR&limit=5" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
// Geocode an address (global search)
const response = await fetch(
'https://mapsi.dev/v1/geocode?q=Eiffel+Tower+Paris&limit=1',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await response.json();
// Extract coordinates from the first result
const { lat, lon } = data.results[0].coordinates;
const address = data.results[0].formatted_address;
console.log(`${address}: ${lat}, ${lon}`);
// With optional country filter
const responseFiltered = await fetch(
'https://mapsi.dev/v1/geocode?q=Eiffel+Tower+Paris&countries=FR&limit=1',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);Python
import requests
# Geocode an address (global search - no country filter)
response = requests.get(
"https://mapsi.dev/v1/geocode",
params={"q": "Eiffel Tower, Paris", "limit": 1},
headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()
# Extract coordinates from the first result
result = data["results"][0]
lat = result["coordinates"]["lat"]
lon = result["coordinates"]["lon"]
address = result["formatted_address"]
print(f"{address}: {lat}, {lon}")
# With optional country filter
response = requests.get(
"https://mapsi.dev/v1/geocode",
params={"q": "Eiffel Tower, Paris", "countries": "FR", "limit": 1},
headers={"X-API-Key": "YOUR_API_KEY"}
)Autocomplete API
Get real-time address suggestions as users type. Perfect for address input forms.
Endpoint
GET /v1/autocompleteParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Partial address or place name (minimum 2 characters) |
countries | string | No | Optional. Comma-separated ISO country codes (max 4) |
limit | integer | No | Maximum number of suggestions (default: 5, max: 10) |
focus.lat / focus.lon | float | No | Bias results toward this location for local relevance |
layers | string | No | Filter by type: address, venue, street, locality |
cURL
curl -X GET "https://mapsi.dev/v1/autocomplete?text=main+str&limit=5" \
-H "X-API-Key: YOUR_API_KEY"
# With optional country filter:
curl -X GET "https://mapsi.dev/v1/autocomplete?text=main+str&countries=US&limit=5" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
// Address autocomplete (global search)
const response = await fetch(
'https://mapsi.dev/v1/autocomplete?text=main+str&limit=5',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await response.json();
// Each suggestion has main_text and secondary_text
const suggestions = data.suggestions.map(s => s.text);
console.log(suggestions);Python
import requests
# Address autocomplete
response = requests.get(
"https://mapsi.dev/v1/autocomplete",
params={"text": "main str", "limit": 5},
headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()
# Get suggestions
suggestions = [s["text"] for s in data["suggestions"]]
print(suggestions)Reverse Geocoding API
Convert geographic coordinates back into human-readable addresses.
Endpoint
GET /v1/reverseParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
lat | float | Yes | Latitude coordinate |
lon | float | Yes | Longitude coordinate |
countries | string | No | Optional. Comma-separated ISO country codes (max 4) |
limit | integer | No | Maximum number of results (default: 1, max: 10) |
layers | string | No | Filter by layer type: address, venue, street, locality |
cURL
curl -X GET "https://mapsi.dev/v1/reverse?lat=48.8584&lon=2.2945&limit=5" \
-H "X-API-Key: YOUR_API_KEY"
# With optional country filter:
curl -X GET "https://mapsi.dev/v1/reverse?lat=48.8584&lon=2.2945&countries=FR" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
// Reverse geocode coordinates
const response = await fetch(
'https://mapsi.dev/v1/reverse?lat=48.8584&lon=2.2945',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await response.json();
// Get the address from the first result
const address = data.results[0].formatted_address;
console.log(address);Python
import requests
# Reverse geocode coordinates
response = requests.get(
"https://mapsi.dev/v1/reverse",
params={"lat": 48.8584, "lon": 2.2945},
headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()
# Get address from first result
address = data["results"][0]["formatted_address"]
print(address)Places API
Find points of interest, businesses, and landmarks near any location.
Endpoint
GET /v1/placesParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query (e.g., "coffee", "restaurant", "hospital") |
lat | float | Yes | Latitude for search center |
lon | float | Yes | Longitude for search center |
radius | integer | No | Search radius in metres |
countries | string | No | Optional. Comma-separated ISO country codes (max 4) |
limit | integer | No | Maximum number of results (default: 10, max: 20) |
cURL
curl -X GET "https://mapsi.dev/v1/places?q=restaurant&lat=48.8584&lon=2.2945&limit=10" \
-H "X-API-Key: YOUR_API_KEY"
# With optional country filter:
curl -X GET "https://mapsi.dev/v1/places?q=restaurant&lat=48.8584&lon=2.2945&countries=FR" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
// Search for places nearby
const response = await fetch(
'https://mapsi.dev/v1/places?q=restaurant&lat=48.8584&lon=2.2945',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await response.json();
const places = data.places.map(p => p.name);
console.log(places);Python
import requests
# Search for places nearby
response = requests.get(
"https://mapsi.dev/v1/places",
params={"q": "restaurant", "lat": 48.8584, "lon": 2.2945},
headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()
places = [p["name"] for p in data["places"]]
print(places)Static Maps API
Generate static map images with markers and custom styling.
✅ No Country Code Required
The Static Maps API does not require the countries parameter.
Endpoint
GET /v1/static-mapParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
center | string | Yes | Map center as "lat,lon" |
zoom | integer | Yes | Zoom level (1-20) |
size | string | No | Image size as "widthxheight" (default: 600x400) |
cURL
curl -X GET "https://mapsi.dev/v1/static-map?lat=48.8584&lon=2.2945&zoom=15&width=600&height=400" \
-H "X-API-Key: YOUR_API_KEY" \
--output map.pngJavaScript
// Get static map image URL
const mapUrl = 'https://mapsi.dev/v1/static-map?lat=48.8584&lon=2.2945&zoom=15&width=600&height=400';
// Use in HTML
const img = document.createElement('img');
img.src = mapUrl + '&api_key=YOUR_API_KEY';
document.body.appendChild(img);Python
import requests
# Download static map image
response = requests.get(
"https://mapsi.dev/v1/static-map",
params={"lat": 48.8584, "lon": 2.2945, "zoom": 15, "width": 600, "height": 400},
headers={"X-API-Key": "YOUR_API_KEY"}
)
with open("map.png", "wb") as f:
f.write(response.content)Batch Geocoding API
Process multiple addresses in a single request for high-throughput applications.
Endpoint
POST /v1/batch/geocodeRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
addresses | array | Yes | Array of address strings. Max: 5,000 (Growth) or 30,000 (Business) |
countries | string | No | Optional. Comma-separated ISO country codes (max 4) |
limit | integer | No | Results per address (default: 1) |
📊 Batch Limits by Plan
Growth: Up to 5,000 records per batch
Business: Up to 30,000 records per batch
cURL
curl -X POST "https://mapsi.dev/v1/batch/geocode" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"addresses": [
"Eiffel Tower, Paris",
"Big Ben, London",
"Colosseum, Rome"
],
"limit": 1
}'
# With optional country filter:
curl -X POST "https://mapsi.dev/v1/batch/geocode" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"addresses": ["4 Avenue de la Madone, Monaco"],
"countries": "MC",
"limit": 1
}'JavaScript
// Batch geocode multiple addresses (global search)
const response = await fetch('https://mapsi.dev/v1/batch/geocode', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
addresses: [
'Eiffel Tower, Paris',
'Big Ben, London',
'Colosseum, Rome'
],
limit: 1
})
});
const results = await response.json();
console.log(results);Python
import requests
# Batch geocode multiple addresses (global search)
response = requests.post(
"https://mapsi.dev/v1/batch/geocode",
json={
"addresses": [
"Eiffel Tower, Paris",
"Big Ben, London",
"Colosseum, Rome"
],
"limit": 1
},
headers={"X-API-Key": "YOUR_API_KEY"}
)
results = response.json()
print(results)Batch Reverse Geocoding API
Convert multiple coordinate pairs into structured addresses in a single synchronous request. Built for fleet tracking, IoT telemetry, and logistics pipelines.
Endpoint
POST /v1/batch/reverseRequest Body
| Parameter | Type | Required | Description |
|---|---|---|---|
points | array | Yes | Array of objects with lat and lon properties |
points[].lat | number | Yes | Latitude (-90 to 90) |
points[].lon | number | Yes | Longitude (-180 to 180) |
points[].id | string | No | Optional client-provided ID, returned in the response for matching |
Batch Size Limits
| Plan | Max Points per Request |
|---|---|
| Free | 10 |
| Growth | 250 |
| Business | 500 |
| Enterprise | 1,000 |
💡 Credit Charging
Credits are charged at 1 credit per 2 points (rounded up). A 100-point batch costs 50 credits.
cURL
curl -X POST "https://mapsi.dev/v1/batch/reverse" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"points": [
{"lat": 48.8584, "lon": 2.2945},
{"lat": 51.5074, "lon": -0.1278},
{"lat": 40.7128, "lon": -74.0060}
]
}'JavaScript
// Batch reverse geocode multiple coordinates
const response = await fetch('https://mapsi.dev/v1/batch/reverse', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
points: [
{ lat: 48.8584, lon: 2.2945 },
{ lat: 51.5074, lon: -0.1278 },
{ lat: 40.7128, lon: -74.0060 }
]
})
});
const data = await response.json();
data.results.forEach(r => console.log(r.address));Python
import requests
# Batch reverse geocode multiple coordinates
response = requests.post(
"https://mapsi.dev/v1/batch/reverse",
json={
"points": [
{"lat": 48.8584, "lon": 2.2945},
{"lat": 51.5074, "lon": -0.1278},
{"lat": 40.7128, "lon": -74.0060}
]
},
headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()
for r in data["results"]:
print(f"{r['lat']},{r['lon']} -> {r['address']}")Point-in-Polygon API
Resolve the full administrative hierarchy for any coordinate. Returns the country, region, city, and neighbourhood that contain the given point, using Who's On First boundary data.
Endpoint
GET /v1/pipParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
lat | number | Yes | Latitude (-90 to 90) |
lon | number | Yes | Longitude (-180 to 180) |
Response Fields
| Field | Description |
|---|---|
hierarchy | Nested object with full admin hierarchy (continent, country, state, city, neighbourhood, etc.) |
country | Country name |
country_code | ISO 3166-1 alpha-3 country code (e.g., FRA) |
state | State or province |
city | City or town |
neighbourhood | Neighbourhood name (where available) |
cURL
curl -X GET "https://mapsi.dev/v1/pip?lat=48.8584&lon=2.2945" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
// Point-in-Polygon: get admin hierarchy for a coordinate
const response = await fetch(
'https://mapsi.dev/v1/pip?lat=48.8584&lon=2.2945',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await response.json();
console.log(data.country); // "France"
console.log(data.state); // "Paris"
console.log(data.city); // "Paris"
console.log(data.neighbourhood); // "Gros Caillou"Python
import requests
# Get administrative hierarchy for a coordinate
response = requests.get(
"https://mapsi.dev/v1/pip",
params={"lat": 48.8584, "lon": 2.2945},
headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()
print(f"Country: {data['country']}")
print(f"State: {data['state']}")
print(f"City: {data['city']}")
print(f"Neighbourhood: {data['neighbourhood']}")Timezone API
Resolve the IANA timezone identifier and current UTC offset for any coordinate. DST-aware, with a longitude-based fallback for coordinates outside mapped timezone boundaries.
Endpoint
GET /v1/timezoneParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
lat | number | Yes | Latitude (-90 to 90) |
lon | number | Yes | Longitude (-180 to 180) |
Response Fields
| Field | Description |
|---|---|
timezone | IANA timezone identifier (e.g., Europe/Paris) |
utc_offset | Current UTC offset (e.g., +01:00) |
dst | Whether DST is currently active (boolean) |
current_time | Human-readable current time in that timezone |
cURL
curl -X GET "https://mapsi.dev/v1/timezone?lat=48.8584&lon=2.2945" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
// Get timezone for a coordinate
const response = await fetch(
'https://mapsi.dev/v1/timezone?lat=48.8584&lon=2.2945',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await response.json();
console.log(data.timezone); // "Europe/Paris"
console.log(data.utc_offset); // "+01:00"
console.log(data.dst); // true
console.log(data.current_time); // "Thursday, March 12, 2026 at 1:00:00 PM GMT+1"Python
import requests
# Get timezone for a coordinate
response = requests.get(
"https://mapsi.dev/v1/timezone",
params={"lat": 48.8584, "lon": 2.2945},
headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()
print(f"Timezone: {data['timezone']}")
print(f"UTC Offset: {data['utc_offset']}")
print(f"DST Active: {data['dst']}")
print(f"Current Time: {data['current_time']}")Address Normalization API
Parse raw address strings into structured components and normalised variants using the Libpostal engine. Ideal for data cleansing and pre-processing pipelines before batch geocoding.
Endpoint
POST /v1/normalizeRequest Body
| Parameter | Type | Required | Description |
|---|---|---|---|
address | string | Yes | Raw address string to parse and normalise |
Response Fields
| Field | Description |
|---|---|
parsed | Object containing structured address components (house_number, road, city, postcode, country, etc.) |
normalized | Array of normalised address string variants expanded by Libpostal |
input | The original address string supplied |
💡 Use Case
Run addresses through /v1/normalize before sending to batch geocoding to improve match rates. Libpostal handles abbreviations (St → Street), transliterations, and international address formats.
cURL
curl -X POST "https://mapsi.dev/v1/normalize" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"address": "123 main st new york ny 10001"}'JavaScript
// Parse and normalize an address string
const response = await fetch('https://mapsi.dev/v1/normalize', {
method: 'POST',
headers: {
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ address: '123 main st new york ny 10001' })
});
const data = await response.json();
// Parsed components
console.log(data.parsed.house_number); // "123"
console.log(data.parsed.road); // "main st"
console.log(data.parsed.city); // "new york"
console.log(data.parsed.postcode); // "10001"
// Normalised variants (Libpostal expansions)
console.log(data.normalized); // ["123 main street new york ny 10001", ...]Python
import requests
# Parse and normalize an address string
response = requests.post(
"https://mapsi.dev/v1/normalize",
json={"address": "123 main st new york ny 10001"},
headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()
# Parsed components
parsed = data["parsed"]
print(f"House number: {parsed.get('house_number')}")
print(f"Road: {parsed.get('road')}")
print(f"City: {parsed.get('city')}")
print(f"Postcode: {parsed.get('postcode')}")
# Normalised variants
for variant in data["normalized"]:
print(variant)Map Tiles API
Access global vector map tiles for building custom map experiences. Our tiles are derived from OpenStreetMap and Natural Earth data, delivered via a global CDN for fast loading worldwide.
/v1/tiles/sources List all available tile sources
/v1/tiles?source=planet Get TileJSON specification for a source
https://mapsi.dev/tiles/planet/{z}/{x}/{y} Fetch vector tiles (PBF format) from CDN
Available Tile Sources
| Source | Type | Zoom Levels | Coverage |
|---|---|---|---|
planet | Vector (PBF) | 0-15 | Global |
Vector Layers
The planet source includes the following vector layers:
boundaries- Administrative boundariesbuildings- Building footprints (zoom 13+)landuse- Parks, forests, etc.natural- Natural featuresplaces- Place labelspois- Points of interestroads- Road networktransportation- Transport featureswater- Water bodies
Example Usage
cURL - Get Tile Sources
curl -X GET "https://mapsi.dev/v1/tiles/sources" \
-H "X-API-Key: YOUR_API_KEY"cURL - Get TileJSON
curl -X GET "https://mapsi.dev/v1/tiles?source=planet" \
-H "X-API-Key: YOUR_API_KEY"JavaScript - Using with MapLibre GL
// Initialize MapLibre GL map with Mapsi tiles
const map = new maplibregl.Map({
container: 'map',
style: {
version: 8,
sources: {
'mapsi-planet': {
type: 'vector',
tiles: ['https://mapsi.dev/tiles/planet/{z}/{x}/{y}'],
maxzoom: 15
}
},
layers: [
// Add your style layers here
{
id: 'water',
type: 'fill',
source: 'mapsi-planet',
'source-layer': 'water',
paint: { 'fill-color': '#a0c4ff' }
},
{
id: 'roads',
type: 'line',
source: 'mapsi-planet',
'source-layer': 'roads',
paint: { 'line-color': '#888', 'line-width': 1 }
}
]
},
center: [0, 20],
zoom: 2
});Python - Fetch TileJSON
import requests
# Get TileJSON specification
response = requests.get(
"https://mapsi.dev/v1/tiles",
params={"source": "planet"},
headers={"X-API-Key": "YOUR_API_KEY"}
)
tilejson = response.json()
print(tilejson["data"]["tiles"]) # CDN tile URLsMap Styles
Use the styles endpoint to get a ready-to-use MapLibre GL style JSON. Pass it directly to your map — no extra configuration needed.
/v1/tiles/styles?style={name} Get a MapLibre GL style definition. Returns full style JSON ready for use.
Available Styles
| Style | Description | Best For |
|---|---|---|
light | Clean light theme (default) | General purpose, dashboards |
dark | Dark navy theme | Night mode, data visualisation |
streets | Road-focused with colour-coded highways | Navigation, routing apps |
grayscale | Fully desaturated monochrome | Data overlays, print |
topo | Topographic paper-map aesthetic | Outdoor, hiking, terrain context |
liberty | 3D building extrusion, vibrant roads | City exploration, showcase maps |
cURL - Get a Style
curl -X GET "https://mapsi.dev/v1/tiles/styles?style=streets" \
-H "X-API-Key: YOUR_API_KEY"JavaScript - Use a Style with MapLibre GL
// Fetch the style from Mapsi and pass directly to MapLibre
const styleResponse = await fetch(
'https://mapsi.dev/v1/tiles/styles?style=liberty',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const style = await styleResponse.json();
const map = new maplibregl.Map({
container: 'map',
style: style, // ← drop it straight in
center: [0, 20],
zoom: 2
});Route API
Multi-stop routing for car, truck, bicycle, motor scooter, and pedestrian profiles. Pass 2–25 waypoints and receive total distance, duration, a per-leg breakdown, and the full route geometry as a GeoJSON LineString.
Endpoints
POST /v1/route GET /v1/route POST accepts a waypoints array (multi-stop). GET is a convenience shorthand for point-to-point only.
POST Request Body
| Field | Type | Required | Description |
|---|---|---|---|
waypoints | array | Yes* | Ordered array of {lat, lon} stops. Min 2, max 25. First = origin, last = destination. |
origin | object | Yes* | Shorthand {lat, lon} — use instead of waypoints for simple A→B routes. |
destination | object | Yes* | Shorthand end point {lat, lon}. Required when using origin. |
via | array | No | Intermediate stops when using origin/destination shorthand. Array of {lat, lon}. |
mode | string | No | auto (default), truck, bicycle, pedestrian, motor_scooter |
units | string | No | km (default) or mi |
* Provide either waypoints or origin + destination.
GET Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
origin_lat, origin_lon | number | Yes | Start coordinate |
dest_lat, dest_lon | number | Yes | End coordinate |
mode | string | No | Travel mode (default: auto) |
units | string | No | km or mi |
Response Fields
| Field | Description |
|---|---|
waypoint_count | Number of stops in the route |
distance_km | Total route distance in km (omitted when units=mi) |
distance_mi | Total route distance in miles (only when units=mi) |
duration_sec | Estimated total travel time in seconds |
legs[] | Per-leg breakdown. Each leg: from, to (waypoint indices), distance_km, duration_sec |
polyline | GeoJSON LineString of the full route geometry |
mode | Travel mode used |
units | Distance units used |
cURL — multi-stop (Eiffel Tower → Louvre → Notre Dame)
curl -X POST "https://mapsi.dev/v1/route" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"waypoints": [
{"lat": 48.8584, "lon": 2.2945},
{"lat": 48.8606, "lon": 2.3376},
{"lat": 48.8530, "lon": 2.3499}
],
"mode": "auto",
"units": "km"
}'cURL — simple point-to-point (GET shorthand)
curl "https://mapsi.dev/v1/route?origin_lat=48.8584&origin_lon=2.2945&dest_lat=48.8530&dest_lon=2.3499&mode=auto" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
const res = await fetch('https://mapsi.dev/v1/route', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
waypoints: [
{ lat: 48.8584, lon: 2.2945 }, // Eiffel Tower
{ lat: 48.8606, lon: 2.3376 }, // Louvre
{ lat: 48.8530, lon: 2.3499 } // Notre Dame
],
mode: 'auto',
units: 'km'
})
});
const data = await res.json();
console.log(`${data.distance_km} km — ${data.duration_sec}s`);
data.legs.forEach((leg, i) =>
console.log(`Leg ${i+1}: ${leg.distance_km} km, ${leg.duration_sec}s`)
);Python
import requests
payload = {
"waypoints": [
{"lat": 48.8584, "lon": 2.2945}, # Eiffel Tower
{"lat": 48.8606, "lon": 2.3376}, # Louvre
{"lat": 48.8530, "lon": 2.3499}, # Notre Dame
],
"mode": "auto",
"units": "km"
}
r = requests.post(
'https://mapsi.dev/v1/route',
json=payload,
headers={'X-API-Key': 'YOUR_API_KEY'}
)
data = r.json()
print(f"Total: {data['distance_km']} km in {data['duration_sec']}s")
for i, leg in enumerate(data['legs']):
print(f" Leg {i+1}: {leg['distance_km']} km")Matrix API
Compute travel times and distances between multiple origin–destination pairs simultaneously, returning a full N×M matrix in one request. Designed for logistics, fleet routing, and delivery optimisation.
Endpoint
POST /v1/matrixRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
sources | array | Yes | Array of {lat, lon} origin points. Max 25. |
targets | array | Yes | Array of {lat, lon} destination points. Max 25. |
profile | string | No | car (default), truck, bicycle, pedestrian |
units | string | No | metric (default) or imperial |
Batch Size Limits
| Plan | Max Matrix Size | Max Pairs |
|---|---|---|
| Free | 5×5 | 25 |
| Growth | 10×10 | 100 |
| Business | 25×25 | 625 |
| Enterprise | Custom | Custom |
Response Fields
| Field | Description |
|---|---|
durations[i][j] | Travel time in seconds from source i to target j |
distances[i][j] | Distance in metres from source i to target j |
durations_text[i][j] | Human-readable duration (e.g., "3h 33m") |
cURL
curl -X POST "https://mapsi.dev/v1/matrix" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sources": [{"lat": 48.8584, "lon": 2.2945}, {"lat": 51.5074, "lon": -0.1278}],
"targets": [{"lat": 52.5200, "lon": 13.4050}, {"lat": 41.9028, "lon": 12.4964}],
"profile": "car"
}'JavaScript
const r = await fetch('https://mapsi.dev/v1/matrix', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
sources: [{lat: 48.8584, lon: 2.2945}, {lat: 51.5074, lon: -0.1278}],
targets: [{lat: 52.5200, lon: 13.4050}, {lat: 41.9028, lon: 12.4964}],
profile: 'car'
})
});
const data = await r.json();
console.log(`Paris → Berlin: ${data.durations_text[0][0]}`);Python
import requests
r = requests.post('https://mapsi.dev/v1/matrix',
json={'sources': [{'lat': 48.8584, 'lon': 2.2945}], 'targets': [{'lat': 52.52, 'lon': 13.405}]},
headers={'X-API-Key': 'YOUR_API_KEY'})
print(r.json()['durations_text']) # [['10h 9m']]Isochrone API
Generate reachability polygons showing all areas accessible within specified travel times or distances from an origin. Returns a GeoJSON FeatureCollection with one polygon per contour. Supports up to 5 contours per request.
Endpoint
GET /v1/isochroneParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
lat | number | Yes | Origin latitude |
lon | number | Yes | Origin longitude |
time | string | One of | Comma-separated travel time contours in minutes. Example: 10,20,30. Max 5. |
distance_km | string | One of | Comma-separated distance contours in km. Cannot combine with time. |
profile | string | No | car (default), bicycle, pedestrian |
denoise | number | No | Polygon smoothing factor 0.0–1.0 (default: 0.5) |
Response
Returns a GeoJSON FeatureCollection. Each Feature is a Polygon for one contour, with contour_minutes or contour_km in properties. Polygons are nested — larger contours enclose smaller ones.
cURL
curl "https://mapsi.dev/v1/isochrone?lat=48.8584&lon=2.2945&time=10,20,30&profile=car" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
const r = await fetch(
'https://mapsi.dev/v1/isochrone?lat=48.8584&lon=2.2945&time=10,20,30&profile=car',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const geojson = await r.json();
// Pass directly to MapLibre/Leaflet as a GeoJSON source
map.addSource('isochrone', { type: 'geojson', data: geojson });Python
import requests
r = requests.get('https://mapsi.dev/v1/isochrone',
params={'lat': 48.8584, 'lon': 2.2945, 'time': '10,20,30'},
headers={'X-API-Key': 'YOUR_API_KEY'})
print(f"{len(r.json()['features'])} contour polygons returned")Elevation API
Returns SRTM 30m resolution elevation data (height above sea level in metres) for any coordinate or batch of coordinates. Global coverage. Single-point via GET, batch via POST.
Endpoints
GET /v1/elevation POST /v1/elevationParameters (GET — single point)
| Parameter | Type | Required | Description |
|---|---|---|---|
lat | number | Yes | Latitude (-90 to 90) |
lon | number | Yes | Longitude (-180 to 180) |
Request Body (POST — batch)
| Field | Type | Required | Description |
|---|---|---|---|
points | array | Yes | Array of {lat, lon} objects. Max 512 per request. |
Batch Size Limits
| Plan | Max Points |
|---|---|
| Free | 10 |
| Growth | 128 |
| Business | 512 |
| Enterprise | 2,000 |
cURL — Single Point
curl "https://mapsi.dev/v1/elevation?lat=45.8325&lon=6.8652" \
-H "X-API-Key: YOUR_API_KEY"
# Response: {"success":true,"lat":45.8325,"lon":6.8652,"elevation_m":4808,"source":"srtm30"}cURL — Batch
curl -X POST "https://mapsi.dev/v1/elevation" \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"points":[{"lat":45.8325,"lon":6.8652},{"lat":27.9881,"lon":86.9250}]}'JavaScript
// Batch
const r = await fetch('https://mapsi.dev/v1/elevation', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ points: [{lat: 45.8325, lon: 6.8652}, {lat: 27.9881, lon: 86.9250}] })
});
const data = await r.json();
data.results.forEach(p => console.log(`${p.lat},${p.lon} → ${p.elevation_m}m`));Python
import requests
r = requests.post('https://mapsi.dev/v1/elevation',
json={'points': [{'lat': 45.8325, 'lon': 6.8652}, {'lat': 27.9881, 'lon': 86.9250}]},
headers={'X-API-Key': 'YOUR_API_KEY'})
for pt in r.json()['results']:
print(f"{pt['elevation_m']}m")Nearest Road API
Identifies the closest road segment to any coordinate. Returns the road name, OSM highway classification, posted speed limit where available, and the precise snapped point on the road geometry.
Endpoint
GET /v1/nearest-roadParameters
| Parameter | Type | Required | Description |
|---|---|---|---|
lat | number | Yes | Latitude (-90 to 90) |
lon | number | Yes | Longitude (-180 to 180) |
limit | integer | No | Number of nearest roads (default: 1, max: 5) |
radius | integer | No | Search radius in metres (default: 200, max: 2000) |
Response Fields
| Field | Description |
|---|---|
road_name | Street name from OSM (null if unnamed) |
ref | Road reference number (e.g., "A1", "M25") |
highway | OSM highway classification (motorway, primary, residential, etc.) |
speed_limit_kmh | Posted speed limit where available in OSM, null otherwise |
oneway | Whether the road is one-way (boolean) |
snapped_point | Nearest point on the road geometry {lat, lon} |
distance_m | Distance from input coordinate to snapped point in metres |
osm_way_id | OpenStreetMap way ID for the road segment |
cURL
curl "https://mapsi.dev/v1/nearest-road?lat=48.8584&lon=2.2945&limit=1" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
const r = await fetch(
'https://mapsi.dev/v1/nearest-road?lat=48.8584&lon=2.2945',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await r.json();
const road = data.results[0];
console.log(`${road.road_name} (${road.highway}), ${road.distance_m}m away`);Python
import requests
r = requests.get('https://mapsi.dev/v1/nearest-road',
params={'lat': 48.8584, 'lon': 2.2945},
headers={'X-API-Key': 'YOUR_API_KEY'})
road = r.json()['results'][0]
print(f"{road['road_name']} ({road['highway']}) — {road['distance_m']}m")Map Matching API
Snaps a sequence of raw GPS coordinates to the road network, correcting GPS drift into accurate road-aligned trajectories. Returns matched geometry, road names, and a per-match confidence score.
Endpoint
POST /v1/matchRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
points | array | Yes | GPS points with lat, lon, optional timestamp (Unix seconds). Min 2, max 500. |
profile | string | No | car (default), bicycle, pedestrian |
geometry | string | No | geojson (default) or polyline |
Response Fields
| Field | Description |
|---|---|
confidence | Overall match confidence 0.0–1.0 |
geometry | GeoJSON LineString of the matched road-aligned route |
matched_points[] | Each input point snapped to the road, with distance_from_original_m |
matched_roads[] | Road segments traversed with name and highway classification |
distance_meters | Total matched route distance |
duration_seconds | Estimated duration (when timestamps provided) |
cURL
curl -X POST "https://mapsi.dev/v1/match" \
-H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"points":[{"lat":48.8584,"lon":2.2945,"timestamp":1741000000},{"lat":48.8591,"lon":2.2962,"timestamp":1741000015}],"profile":"car"}'JavaScript
const r = await fetch('https://mapsi.dev/v1/match', {
method: 'POST',
headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
points: [
{ lat: 48.8584, lon: 2.2945, timestamp: 1741000000 },
{ lat: 48.8591, lon: 2.2962, timestamp: 1741000015 }
],
profile: 'car'
})
});
const data = await r.json();
console.log(`Confidence: ${data.confidence}, Distance: ${data.distance_meters}m`);Python
import requests
r = requests.post('https://mapsi.dev/v1/match',
json={'points': [{'lat':48.8584,'lon':2.2945}, {'lat':48.8591,'lon':2.2962}], 'profile':'car'},
headers={'X-API-Key': 'YOUR_API_KEY'})
data = r.json()
print(f"Confidence: {data['confidence']}")H3 API
Converts coordinates to Uber's H3 hexagonal grid cell identifiers for spatial aggregation, heatmaps, and density analysis. Supports all H3 resolutions from 0 (coarsest, ~4M km²) to 15 (finest, ~1 m²).
Endpoint
GET /v1/h3Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
lat | number | Yes | Latitude (-90 to 90) |
lon | number | Yes | Longitude (-180 to 180) |
resolution | integer | No | H3 resolution 0–15 (default: 9, approx 0.1 km²) |
return_boundary | boolean | No | Include hex cell boundary polygon (default: false) |
return_neighbors | boolean | No | Include the 6 neighbouring cell IDs (default: false) |
Resolution Reference
| Resolution | Approx Area | Scale |
|---|---|---|
| 5 | 252 km² | City |
| 7 | 5.16 km² | District |
| 9 (default) | 0.105 km² | Neighbourhood |
| 11 | 0.001 km² | Block |
| 13 | 43 m² | Building |
cURL
curl "https://mapsi.dev/v1/h3?lat=48.8584&lon=2.2945&resolution=9&return_boundary=true" \
-H "X-API-Key: YOUR_API_KEY"JavaScript
const r = await fetch(
'https://mapsi.dev/v1/h3?lat=48.8584&lon=2.2945&resolution=9',
{ headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const data = await r.json();
console.log(`Cell: ${data.cell_id}, Area: ${data.area_km2} km²`);Python
import requests
r = requests.get('https://mapsi.dev/v1/h3',
params={'lat': 48.8584, 'lon': 2.2945, 'resolution': 9},
headers={'X-API-Key': 'YOUR_API_KEY'})
data = r.json()
print(f"{data['cell_id']} — {data['area_km2']} km²")