> For the complete documentation index, see [llms.txt](https://docs.multiset.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.multiset.ai/fundamentals/georeferencing-maps/geo-fence.md).

# 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 `mapCode` and 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:

| You have                               | Use                                                                                                                                                   |
| -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| A surveyed E57 in a known grid         | Declare it at upload with [`source.metadata.crs`](/fundamentals/third-party-scans/coordinate-reference-system.md). The scan georeferences itself.     |
| An existing map and some known points  | [Georeference Map](/fundamentals/rest-api-docs/georeference.md), which solves origin and heading from ground control points.                          |
| A rough position and a compass bearing | Set the location and heading on the map in the Developer Portal, or [auto geo-reference](/fundamentals/georeferencing-maps/auto-georeference-map.md). |

## 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.

{% hint style="warning" %}
`geoFenceReady: false` covers both "not ready yet" and "cannot have one", so it does not on its own tell you a fence is coming. If one never appears, check that the map is active and has both coordinates and a heading.
{% endhint %}

## 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.

{% openapi src="/files/9s22fbe1NbOVwVbG0q3k" path="/vps/map/{mapId}/geo-fence" method="get" %}
[geo-fence-api.yaml](https://3163433004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FokTDI7QVY04Zvb1pQ8Ry%2Fuploads%2Fgit-blob-c57e4a63657153937c0cf3c6e07a7a0a1289dcc5%2Fgeo-fence-api.yaml?alt=media)
{% endopenapi %}

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.

{% openapi src="/files/9s22fbe1NbOVwVbG0q3k" path="/vps/map/nearby" method="get" %}
[geo-fence-api.yaml](https://3163433004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FokTDI7QVY04Zvb1pQ8Ry%2Fuploads%2Fgit-blob-c57e4a63657153937c0cf3c6e07a7a0a1289dcc5%2Fgeo-fence-api.yaml?alt=media)
{% endopenapi %}

Three details worth knowing:

* **Results are grouped by what you would query.** A building whose floors share a map set returns **one** `mapSet` entry 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. `type` tells you whether to send `mapCode` or `mapSetCode`.
* **Distance is measured to the fence edge**, so `distanceMeters` is `0` whenever the point is inside, and `containsPoint` is simply `distanceMeters == 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](/fundamentals/rest-api-docs/map-query.md) instead of naming a map. The nearest map whose fence is in range is resolved and queried for you.

```json
{
  "queryImage": "<base64>",
  "geoLocation": [37.794853, -122.394573],
  "isRightHanded": true
}
```

If the resolved map belongs to a map set, the **whole set** is queried, which is what you want indoors.

| Field             | Meaning                                                                                                                  |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `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:

```json
"resolvedFrom": {
  "mapCode": "MAP_63ERQ0V9XSJD",
  "distanceMeters": 0,
  "searchRadiusMeters": 25
}
```

Only active maps in your account with `geoFenceReady: true` are considered. When nothing is in range you get a `404`.

{% hint style="info" %}
**`geoLocation` doubles as a `geoHint`.** If you supply neither `geoHint` nor `hintPosition`, the coordinate is reused as the localization prior, and `hintRadius` then defaults to **100 m** rather than the usual 25 m, because a raw GPS fix is far less precise than a hint you calculated yourself.

Supply `geoHint` explicitly when you have a better position than the device's GPS. See [GeoHint in Localization](/fundamentals/localization/geohint-in-localization.md).
{% endhint %}

## Which approach to use

<table><thead><tr><th width="220">Situation</th><th>Do this</th></tr></thead><tbody><tr><td>You already know the map</td><td>Send <code>mapCode</code> or <code>mapSetCode</code> as before. Nothing changes.</td></tr><tr><td>A user opens your app somewhere in a large estate</td><td>Call <strong>nearby</strong> once, pick a target, then query that target for the session.</td></tr><tr><td>One-off query and you do not want to manage state</td><td>Send <code>geoLocation</code> on the query itself.</td></tr><tr><td>Fences overlap and you need to choose deliberately</td><td>Call <strong>nearby</strong>, which lists every candidate, rather than letting the query pick.</td></tr></tbody></table>

{% hint style="warning" %}
Resolving by coordinate costs a spatial lookup on every request. For anything running at frame rate, resolve once with **nearby** and reuse the code.
{% endhint %}

## Drawing a fence

The Developer Portal draws a map's fence over the satellite view, which is the quickest way to sanity-check a geo-reference: if the outline does not sit on the building, the map's location or heading is wrong, not the fence.

To draw it yourself, fetch the Feature and hand it to your mapping library, using `bbox` with `fitBounds` to frame it.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.multiset.ai/fundamentals/georeferencing-maps/geo-fence.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
