Geo-fence
Resolve a coordinate to the map that covers it, and localize without naming a map.
Overview
A geo-fence is the real-world area a map covers. It follows the shape of the scan rather than a circle drawn around a pin, so it stays accurate on sites that are long, irregular, or built on several levels.
It answers a question a GPS fix alone cannot: which of my maps is this person standing in?
That unlocks two things:
Localize by coordinate. Send a position instead of a
mapCodeand let the server pick the map.Resolve once, cache it. Ask what is nearby at the start of a session, then query that target for the rest of it.
Prerequisite: geo-reference the map
A map with no geo-reference has no fence, and is invisible to everything on this page. Nothing below works until the map has real-world coordinates and a heading.
There are three ways to get there, depending on what you have:
A surveyed E57 in a known grid
Declare it at upload with source.metadata.crs. The scan georeferences itself.
An existing map and some known points
Georeference Map, which solves origin and heading from ground control points.
A rough position and a compass bearing
Place the map over satellite view in the Developer Portal (below), or auto geo-reference.
When a fence is available
Fences are produced for you. You never create or upload one.
A map has a fence once it is active and carries both coordinates and a heading. Changing either of those refreshes the fence, and it is briefly unavailable while that happens.
geoFenceReady on the map tells you where things stand. While it is false, geoFence is null and the map is not matched by anything on this page.
Generating a fence manually
A fence is produced when a map's placement is saved in the Developer Portal. There is no separate action for it.
Heading is not captured during a scan and defaults to 0, so a new map is usually positioned correctly but oriented incorrectly, and has no fence until its placement is corrected.
1. Open the map over satellite view
Open the map in the Developer Portal and switch the viewer to Satellite. A map without a fence shows only Satellite tiles, Terrain and Mesh opacity in the View panel.

2. Correct the placement
Search for the site by name or lat, long, then align the mesh with the imagery using the gizmo or the Placement fields. See How to Manually Align Scans for the handles and fields in detail.
3. Save
Save is enabled once the placement changes. Saving writes the coordinates and heading, and starts fence generation.

4. Verify the fence
Generation runs in the background and completes within a few seconds for most maps. Reopen the viewer: the View panel now includes a Geo-fence toggle, with the vertex count of the traced outline.

Enabling it draws the fence over the imagery.

The outline should follow the building. If it does not, the map's location or heading is incorrect — correct the placement and save again.
The map is now returned by nearby and can be localized against with geoLocation.
Reading a fence
Returns the polygon as a GeoJSON Feature, so it can be handed straight to a mapping library, along with a bbox and center for fitting the view.
The real-world area a map covers, as a GeoJSON Feature ready to hand to a mapping library, plus a bbox and centre for framing it.
geoFenceReady is false and geoFence is null while a map has no fence, including the short period after its coordinates or heading change.
The ID or mapCode of the map
Geo-fence state for the map
MAP_63ERQ0V9XSJDFerry newTrue only when a polygon exists and is current for the map's present location and heading. Every other case is false with a null geoFence.
truePoints in the ring, including the repeated closing point.
2762026-09-15T13:04:47.778Z[minLon, minLat, maxLon, maxLat], for fitBounds.
[-122.3951151,37.79467653,-122.39322079,37.79593026]Unauthorized
Map belongs to another account
Map not found
GET /v1/vps/map/{mapId}/geo-fence HTTP/1.1
Host: api.multiset.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"mapCode": "MAP_63ERQ0V9XSJD",
"mapName": "Ferry new",
"geoFenceReady": true,
"vertexCount": 276,
"generatedAt": "2026-09-15T13:04:47.778Z",
"bbox": [
-122.3951151,
37.79467653,
-122.39322079,
37.79593026
],
"center": {
"latitude": 37.795303395,
"longitude": -122.394167945
},
"geoFence": {
"type": "Feature",
"properties": {
"mapCode": "MAP_63ERQ0V9XSJD",
"mapName": "Ferry new",
"source": "mesh"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-122.395,
37.794692
],
[
-122.3949,
37.7947
]
]
]
}
}
}Accepts either the mapId or the mapCode.
Finding what is nearby
Given a coordinate, returns the ranked candidates around it. Use this once per session and cache the answer, rather than paying for the lookup on every frame.
The maps and map sets whose area is within a radius of a point, nearest first.
Use it once per session to turn a coordinate into something you can query, then reuse that code. Results are grouped by what you would actually query, so a building whose floors share a map set returns the set rather than each floor. type tells you whether to send back a mapCode or a mapSetCode.
Where several maps cover the same spot, every candidate is listed. distanceMeters is 0 when the point is inside an area.
37.794853-122.394573Search radius in metres, measured to the fence edge.
100Maximum fences considered before grouping, so a map set may collapse several.
10Ranked candidates, nearest first. An empty results array means nothing is in range.
Missing or out-of-range latitude/longitude, radius or limit
Unauthorized
GET /v1/vps/map/nearby?latitude=1&longitude=1 HTTP/1.1
Host: api.multiset.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Accept: */*
{
"latitude": 37.794853,
"longitude": -122.394573,
"radiusMeters": 200,
"count": 2,
"results": [
{
"rank": 1,
"type": "map",
"mapCode": "MAP_63ERQ0V9XSJD",
"name": "Ferry new",
"distanceMeters": 0,
"containsPoint": true
},
{
"rank": 2,
"type": "mapSet",
"mapSetCode": "SET_TESTAB12",
"name": "HSR Office",
"distanceMeters": 5.9,
"containsPoint": false,
"matchedMaps": [
{
"mapCode": "MAP_FLOOR1",
"distanceMeters": 5.9
},
{
"mapCode": "MAP_FLOOR2",
"distanceMeters": 12.7
}
]
}
]
}Three details worth knowing:
Results are grouped by what you would query. A building whose floors share a map set returns one
mapSetentry listing its matched maps, not one entry per floor. Querying a single floor is what breaks indoor localization, so the grouping steers you towards the right target.typetells you whether to sendmapCodeormapSetCode.Distance is measured to the fence edge, so
distanceMetersis0whenever the point is inside, andcontainsPointis simplydistanceMeters == 0.Ambiguity is surfaced, not hidden. Where fences overlap, every candidate is listed. A query by coordinate would have silently picked one.
The polygons themselves are not returned here. Fetch one from the geo-fence endpoint when you need to draw it.
Localizing by coordinate
Pass geoLocation to Map Query instead of naming a map. The nearest map whose fence is in range is resolved and queried for you.
If the resolved map belongs to a map set, the whole set is queried, which is what you want indoors.
geoLocation
[latitude, longitude] in WGS 84 degrees. Mutually exclusive with mapId, mapCode, mapSetId and mapSetCode.
geoSearchRadius
Overrides the search radius in metres for this request only. Ignored unless geoLocation is supplied. Defaults to 25 m.
A successful response carries resolvedFrom, naming the map the coordinates landed on:
Only active maps in your account with geoFenceReady: true are considered. When nothing is in range you get a 404.
Which approach to use
You already know the map
Send mapCode or mapSetCode as before. Nothing changes.
A user opens your app somewhere in a large estate
Call nearby once, pick a target, then query that target for the session.
One-off query and you do not want to manage state
Send geoLocation on the query itself.
Fences overlap and you need to choose deliberately
Call nearby, which lists every candidate, rather than letting the query pick.
Drawing a fence
To draw a fence in your own application, fetch the Feature and hand it to your mapping library, using bbox with fitBounds to frame it.
For a quick visual check of a single map, the Developer Portal already draws it — see Generating a fence manually.
Last updated
Was this helpful?

