> For the complete documentation index, see [llms.txt](https://multiset.gitbook.io/multiset/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://multiset.gitbook.io/multiset/fundamentals/map-versioning.md).

# Map Versioning

## Overview

MultiSet Map Versioning lets developers merge scans captured at different intervals into a single coordinate system. Unlike traditional scan merging, which relies on algorithms like ICP and weak visual features, MultiSet Map Versioning is powered by the **MultiSet VPS** under the hood. This means it can merge scans taken months apart, even when there are significant visual and geometric changes between them.

With Map Versions, a developer's content layer coordinates don't need to be updated when a map is updated, even if a different local coordinate system is used, MultiSet handles the transformation automatically.

<figure><img src="/files/PiX7fLABgqCYWCLAp1Xe" alt="Map Version panel in the Developer Portal showing base and version maps, each with a Query Active toggle"><figcaption><p>Map Version panel — toggle Query Active per map to control which maps are used for localization</p></figcaption></figure>

## When to use Map Versioning

Use a Map Version when you are **updating a scan of a space you have already mapped**, whether you re-scanned the whole space or only part of it. The new scan covers the same physical area as the original, and versioning keeps your content layer anchored to the original coordinate frame.

{% hint style="info" %}
**Extending coverage instead? Use a MapSet.** If the new scan covers **additional area** rather than re-capturing existing area, for example a new wing, an adjacent building, or another floor, add it to a [MapSet](/multiset/fundamentals/mapset-multiple-maps.md) instead of creating a Map Version. Map Versioning is for the same area over time; a MapSet is for stitching different areas together.
{% endhint %}

| Your situation                                     | Use                                      |
| -------------------------------------------------- | ---------------------------------------- |
| Re-scanned the whole space                         | Map Version                              |
| Re-scanned one section of the space                | Map Version, with both maps Query Active |
| Scanned a new area to extend coverage              | MapSet                                   |
| Re-scanned one map that is already inside a MapSet | Map Version on that individual map       |

## How it works

A Map Version groups two or more scans of the same physical space:

* One scan is the **base map**, its coordinate frame is the version's coordinate frame and the one your content layer is authored against.
* Every other scan added to the version is aligned to that base by the MultiSet VPS, which computes a rigid transform (`relativePose`) between the two scans.
* At any time, one or more maps in the version are **active**. When you query the base map, the VPS localizes against every active map in the version and transforms the returned pose back into the base map's coordinate frame. You choose which maps are active with the **Query Active** toggle in the Developer Portal.

### Why MultiSet VPS instead of ICP?

Traditional scan-merging techniques, such as ICP (Iterative Closest Point) and matchers built on low-level geometric or visual features, work well only when the two scans look almost identical. They fail in the cases that matter most in the real world:

* Furniture rearranged, walls repainted, fixtures swapped out
* Different hardware, so different coordinate systems: LHS, RHS Y Up, RHS Z Up, etc
* Different sensor or different point density (e.g. iPhone LiDAR vs. Matterport vs. Leica)
* Different lighting conditions or season
* Months between captures, with cumulative change to the space

MultiSet Map Versioning uses the same VPS pipeline that powers MultiSet localization. Because the VPS reasons about the scene at the level of recognizable structure rather than raw geometry, it stays robust under drastic change between captures. The output is a clean rigid transform between the new scan and the base map, even when ICP would have given up.

### Content layer stays put

The biggest practical benefit: **your content layer never has to move.**

Anchors, navigation paths, instruction overlays, and any other authored content live in the base map's coordinate frame. When you scan the space again, possibly with a different device that uses a different local coordinate system, you add the new scan as a version and activate it. MultiSet's VPS computes the transform once; from then on every query against the base map is transparently translated to the active map.

{% hint style="success" %}
The content you authored in your app (navigation paths, AR instructions, anchors) does **not** need to be re-authored when you re-scan the space, even if the new scan uses a completely different local coordinate system.
{% endhint %}

## Create a Map Version in the Developer Portal

The quickest way to version a map is from the Developer Portal. No API calls required.

**1. Open the map's Map Details.** In the **Maps** list, click the map you want to use as the base. On its **Map Details** screen, scroll to the **Map Version** section and click **+ Create Map Version**.

<figure><img src="/files/M4BNTboM0a2rrtWZN8hW" alt="Create Map Version button in the Map Version section of a map&#x27;s details screen"><figcaption><p>Map Details → <strong>Map Version</strong> section → <strong>Create Map Version</strong>.</p></figcaption></figure>

**2. Pick the target map.** In the **Create Map Version** dialog, the map you opened is set as the **Source Map (Base)**: its coordinate frame becomes the version's frame. Search for and select the newer scan of the same space as the **Target Map**, then click **Create Version**.

<figure><img src="/files/oQsQbOitPsZoXYrxic1t" alt="Create Map Version dialog with a base map and a searchable target map list"><figcaption><p>Choose the newer scan as the target map, then <strong>Create Version</strong>.</p></figcaption></figure>

**3. Wait for alignment.** The target map is added to the version with a **Pending** status while the MultiSet VPS computes the transform between the two scans. The base map is **Ready** and **Query Active** from the start.

<figure><img src="/files/X0jTYuaYzqadsBCVlfC8" alt="Map Version panel showing the base map Ready and the new map Pending"><figcaption><p>The new scan shows <strong>Pending</strong> while the VPS aligns it to the base map.</p></figcaption></figure>

**4. Activate the new scan.** Once the target map turns **Ready**, toggle **Query Active** to include it in localization queries. Use **View pose** to inspect the computed relative pose, and **+ Add Map Version** to add further scans over time. At least one map must remain Query Active.

<figure><img src="/files/ZJmQ5yhhgYimNNQKa56k" alt="Map Version panel with both maps Ready and Query Active"><figcaption><p>Once <strong>Ready</strong>, toggle <strong>Query Active</strong> to include the scan in queries; <strong>View pose</strong> shows its relative pose.</p></figcaption></figure>

## Query more than one map at a time

A version is not limited to a single active scan. **Any number of the maps in a version can be query active at once**, and a localization query against the base map runs against all of them, returning the pose in the base map's coordinate frame either way.

This is what makes **partial updates** practical. If you re-scan only one section of a space, you do not have to replace the whole map: keep the original active for the areas that have not changed, activate the new scan for the section that has, and queries resolve against whichever one the user is actually standing in.

### From the Developer Portal

Each map in the **Map Version** panel has its own **Query Active** toggle. Turn it on for every map you want localization to run against.

<figure><img src="/files/4Fu1XcfJ257aM9Pn3bZ3" alt="Map Version panel with the Query Active toggle highlighted on both maps"><figcaption><p>Both maps in this version are query active, so localization runs against both.</p></figcaption></figure>

{% hint style="info" %}
A map has to reach **Ready** before it can be activated, and **at least one map must stay active** at all times, so the last active map cannot be switched off.
{% endhint %}

### Over the API

Use the activate endpoint and pass `mapCodes` with the full set of maps you want active:

```json
{
    "mapCodes": ["MAP_BTTE1MOXYVT8", "MAP_QQYKIBHXZE01"]
}
```

The call **replaces** the active set, so any map in the version that is not listed is deactivated. To activate a single map, send `mapCode` instead. See [Activate Maps in Version](/multiset/fundamentals/rest-api-docs/map-version.md#activate-maps-in-version) for the full request and response.

## Detecting and applying a version at runtime

When a map has been versioned, the **map details response** carries two new fields, this is how a client app discovers that a version exists:

```json
{
    "versionCode": "MVER_3VG3VINCWUIR",
    "activeMapCode": "MAP_KRXDJ14SY7ER"
}
```

Once your client sees these fields on a map response, the flow is:

1. Call **Get Map Version** with the `versionCode` to fetch the version's full state, including the **relative pose (offset)** of the active map against the base.
2. Download the mesh / map data for the **active map** (`activeMapCode`) instead of the base map. This is the geometry that VPS queries are actually running against.
3. **Apply the relative pose as an offset** when loading the active map's mesh into your scene. With this offset applied, the new mesh lines up exactly on top of your existing content layer (which was authored in the base map's coordinate frame).

The result: the new, fresher mesh is rendered in the right place, your anchors and navigation paths stay where you originally put them, and VPS query responses already arrive in the base map's frame, so no further client-side conversion is needed.

{% embed url="<https://youtu.be/TPLYgH9EIy8>" %}

## Versioning an individual Map

The simplest case: a single base map, scanned again later.

1. Create a Map Version with the original map as `sourceMapCode` (it becomes the **base**) and the newer scan as `targetMapCode`.
2. The MultiSet VPS computes the transform between the two scans. The new map's status moves through `pending` → `computing` → `ready` as the job progresses.
3. Activate the newer scan with the **Activate Map in Version** API. From this point on, queries against the original map's code are routed to the newer scan, and the response is transformed back, so your content layer is unaffected.
4. When you scan again next quarter, add it as another version. The transform is computed against the **currently active map**, not against the original base, which keeps quality high as the space drifts further from the original scan over time.

See the [Map Version REST API](/multiset/fundamentals/rest-api-docs/map-version.md) page for the full request/response shapes.

## Versioning a Map that is part of a MapSet

Map Versions and MapSets compose cleanly:

* A MapSet groups maps that **cover different physical areas** of a venue (e.g. several floors, or several rooms).
* A Map Version groups scans that **cover the same physical area** at different points in time, or from different hardware.

To re-scan one map inside a MapSet, create a Map Version on that individual map. The MapSet keeps pointing at the same `mapCode`, the version layer transparently swaps in the newer scan. The relative pose between maps in the MapSet does not need to be re-computed, only the transform between the old and new scan of the one updated map.

{% hint style="info" %}
You don't version the MapSet itself. You version the individual maps that compose it. This keeps each capture session isolated: re-scanning Floor 2 doesn't affect Floor 1's alignment.
{% endhint %}

## Mix hardware between versions

You don't have to use the same scanning hardware for every version of a map. Add versions captured with:

* **MultiSet Mapping App** (iPhone / iPad with LiDAR)
* **Matterport** (E57 / MatterPak)
* **Insta360** and other 360° cameras
* **Leica**, **NavVis**, **Faro**, **Xgrids** scanners

The VPS computes the alignment regardless of which device produced either scan. This lets you start with a quick phone capture, then upgrade to a higher-fidelity professional scan later, without losing the content layer you already built.

See [Third Party Scans](/multiset/fundamentals/third-party-scans.md) for supported formats and upload flows.

## Lifecycle

| Status      | Meaning                                                                                 |
| ----------- | --------------------------------------------------------------------------------------- |
| `pending`   | The scan has been added to the version and is queued for alignment.                     |
| `computing` | VPS is actively computing the transform between this scan and the version's source map. |
| `ready`     | Transform is computed; this map can be set as active (toggle **Query Active**).         |
| `failed`    | VPS could not align this scan to the source. `failureReason` will be populated.         |

A version always has exactly one **base** map (its coordinate frame is the version's frame) and one or more **active** maps (the scans VPS queries run against). When a version is first created only the base map is active; use the **Query Active** toggle in the Developer Portal to activate or deactivate additional maps for querying. At least one map must stay active.


---

# 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://multiset.gitbook.io/multiset/fundamentals/map-versioning.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.
