Get started

Changelog

What changed across the Mountaya platform APIs, Map Embedding, and integrations, newest first.

August 16, 2026

Map Studio
Map Studio API
Map Embedding

Collections belong to your organization

Collections become organization-owned and shareable by link, and the embed can target a collection directly.

~

A collection now belongs to the organization that owns it, and every active member of that organization sees it. Previously a collection was listed only to the people individually invited to it, so two colleagues could organize the same itineraries into folders neither could see. A collection created in your personal scope stays yours alone. role on a collection is now your organization role.

+

GET /v1/organizations/{organization_id}/collections lists an organization's collections. GET /v1/users/{user_id}/collections now returns personal collections only. GET /v1/itineraries accepts an optional organization_id to group by that organization's collections instead of your personal ones.

+

Collections can be shared by link. POST /v1/collections/{collection_id}/share mints a read-only link, POST .../share/rotate replaces it, and DELETE .../share disables it — the same lifecycle itineraries already had. Unlike an itinerary link, which exposes exactly one itinerary, a collection link exposes the itineraries and zones the collection contains.

+

A publishable key discovers public collections. Sent without a session token, GET /v1/organizations/{organization_id}/collections returns the public collections of the organization that issued the key, and every row reports viewer because a key holds no membership. The key is pinned to its own organization, so asking for another answers 403. Private collections stay out of that listing; reaching one still takes a session token.

!

GET /v1/users/{user_id}/collections is reachable with a publishable key, returning a user's public personal collections with each row reporting viewer. A private collection is never listed to a publishable key; reaching one still needs a session token. A cross-user read with a session token answers 403 rather than an empty page, so a refusal is distinguishable from an empty library.

~

Updating a collection, an itinerary or a zone is now PATCH rather than PUT, and every field in the body is optional: whatever you leave out keeps its current value. Previously the three disagreed — a collection update required all three fields and cleared anything omitted, an itinerary update required only the name, and a zone update required nothing — so renaming a collection meant restating its description and privacy or losing them. The paths and the field names are unchanged; send PATCH and only the fields you mean to change.

-

Per-collection collaborator invitations are removed, along with GET|POST|DELETE /v1/collections/{collection_id}/users, PUT .../users/{user_id} and PUT .../users/{user_id}/invitation. Collaboration inside an organization is organization membership; collaboration outside one is a share link. A collection role no longer grants any access to the itineraries or zones inside it.

~

collection_id is now a content selector in its own right: pass it alone to embed a whole collection, or with itinerary_id to open that collection focused on one itinerary. The with_collection_itineraries and with_collection_zones URL parameters are removed — a collection embed draws what the collection contains, and your organization's embed settings still cap which layers it may serve.

August 12, 2026

Map Studio API
GraphQL API
MCP Server
Developer portal

One read path for pagination, real error codes on the Data API

Eleven wire changes break an existing consumer: pagination metadata nests under pagination, Data API errors carry a real extensions.code, the unlimited sentinel is null rather than -1, six Data API fields are renamed, removed, or retyped, thirteen public Map Studio API operations are renamed with the /groups route becoming /segment-groups, and a filtered search narrows Way.activityCompatible to the activity it was asked about. The Map Studio API also gains a public 50-operation surface, a documented 504, and a rate limit on session exchange.

~

Pagination metadata moved from the flat extensions.metadata.{limit, offset, total} to a nested extensions.metadata.pagination object carrying the same three fields. A client still reading the flat path now reads undefined. It affects the four plain list endpoints — GET /v1/itineraries/{itinerary_id}/collections, GET /v1/zones/{zone_id}/collections, GET /v1/users/{user_id}/collections, and GET /v1/collections/{collection_id}/users. GET /v1/itineraries reports the same nested object beside its own count and limit, so one read path now serves every list endpoint whether or not it also carries domain data.

!

Data API errors populate extensions.code, and the message is the localized sentence alone. Both were broken together: the wrong error presenter was rendering an error's whole string form, so the message arrived as "FORBIDDEN: <message> (input)" and extensions arrived empty. Anything parsing that prefix to recover a code must read extensions.code instead — a client that branched on the prefix will not find it, and one that branched on an absent code was treating every 402, 403, 404, 429, and 500 as a bad argument.

~

The entitlement sentinel for an unlimited dimension is null, replacing -1. It reads the same everywhere the value appears: an organization's limits map, and the limit beside the itineraries listing. A client comparing against -1 now never matches and treats an unlimited dimension as capped at whatever it defaults to; compare against null instead. A dimension absent from the map still means no limit was granted at all, which is not the same as unlimited.

~

Six fields changed shape on the Data API. Place.housenumber and Isochrone.reachfactor are now houseNumber and reachFactor, spelled the way every other field in the schema is. Place.score and Way.score are gone: both carried the upstream geocoder's own relevance figure, which is not comparable between two responses, so rank on the order results arrive in instead. Isochrone.center is nullable, because the value is forwarded verbatim from the routing provider rather than reconstructed from the origin you sent — a provider that reports no centre now reports null where it used to report an empty array. ZoneSearchResult.level and mode are the ZoneLevel and ZoneMode enums rather than free-form strings, so their values arrive upper-snake-cased: WARNING, POLYGON, and the rest. Selecting a renamed or removed field is not a null in the response — it is a validation error, Cannot query field, raised before a resolver runs, so a selection set that still names one of them comes back with no data at all.

~

Every Map Studio API operation name is now derived from its path rather than chosen, so a method's name says where it goes. Thirteen public names change: the itinerary sub-resources regain the parent the path already carries, so postSegment is postItinerarySegment, putWaypoint is putItineraryWaypoint, and the segment-group trio follows the same shape. The route /v1/itineraries/{itinerary_id}/groups is now /v1/itineraries/{itinerary_id}/segment-groups, which is what the payloads have always called it — SegmentGroupCreateParams, ItinerarySegmentGroup — and the old path is gone rather than aliased. Twenty-seven console-only names changed the same way and reach no API key.

~

A search filtered to one activity now reports Way.activityCompatible as that activity alone, where it used to list every activity the way accepts. The field reports what was established rather than a catalogue: a filtered search verifies only the activity it was asked about, so naming the others would claim a routing check that never ran. Read an absent activity as unreported, not as refused. An unfiltered search is unchanged.

+

The Map Studio API has a public surface of its own: 50 operations covering itineraries, segments, waypoints, segment groups, zones, collections, and sessions, published as their own OpenAPI document and rendered as a reference in the developer portal. The console-only operations are filtered out of it, so what the reference shows is what an API key can reach.

+

POST /v1/sessions declares 429 Too Many Requests. It is now rate limited, per calling address and, on failed exchanges, per secret key — a session exchange that presents an unknown key is the one cheap way to probe for a valid one, and it was previously unbounded. A working integration mints roughly one token per four minutes per key thanks to the existing get-or-mint cache, so legitimate traffic sits far below the ceiling.

+

Every public Map Studio API operation declares 504 Gateway Timeout with the GATEWAY_TIMEOUT code. Routes run under a request time budget, and a spent budget used to surface as whichever internal error the interruption happened to produce. The restatement only ever replaces a 5xx, so an expiring deadline never turns a 404 into a 504.

+

A page documenting the error contract both APIs share: the envelope, all sixteen codes with their statuses, where each surface puts the offending field path, and what separates a PAYMENT_REQUIRED from a CARD_REQUIRED.

August 5, 2026

GraphQL API
MCP Server
Map Studio

Know what a route crosses

Routed results report the tollways and access-restricted ways they cross, directions can route around them on request, and suggestions never propose one at all.

+

Routed results now report the tollways and access-restricted ways they cross. Every GeometryAnalysis carries advisories, naming whether the line crosses a way that charges a toll or one restricted to owners, customers, deliveries, permit holders, or destination traffic — and where, as coordinate ranges. Permissive ways, where the owner tolerates passage, are reported but are not treated as a restriction.

+

directions accepts avoid: [TOLLWAY, RESTRICTED_ACCESS] to route around those ways. It costs a second routing pass only when the first route actually crosses one. Avoidance is best-effort, so each route reports an avoidance outcome: NOT_NEEDED, APPLIED, or NO_ROUTE when the hazard could not be routed around — which usually means a waypoint sits on the way itself.

~

suggestions never proposes a route through a tollway or an access-restricted way. There is no opt-out: when no hazard-free candidate can be generated from the given points the query fails rather than returning one that crosses something. Use directions when a route should go through such a way deliberately.

~

Placing a point that routes a segment through a tollway or an access-restricted way now asks first. Confirm and the point is placed; decline and the route returns to its last accepted shape. Opening a saved segment that already crosses one does not prompt — only a change you make does.

August 2, 2026

Map Studio
Map Embedding
Tile API
GraphQL API
MCP Server

Reshape a route after you have drawn it

Itineraries gain a draft and a published version, segments can be merged, split, inserted, grouped, and switched between routing engines, and itineraries can be duplicated.

+

Itineraries now have a draft and a published version. Editing changes only the draft, so a course can be reworked in the open; share links, embeds, and the tiles they render keep serving the last published snapshot until you publish again. An itinerary that has never been published is not reachable from a share link or an embed. Publishing is refused while a collaborator is still editing any part of the itinerary.

+

Segments can be reshaped after they are drawn. Merge two neighbours that share a routing engine, split one in two at a point you click on the route, or insert a new segment between two neighbours or before the first. The chain renumbers itself and stays continuous.

+

A segment's routing engine can be switched between smart routing and freehand. Going from freehand to smart routing snaps the drawn line to the trail network while keeping the original start and end points, and reports a clear error when the line cannot be routed.

+

Neighbouring segments can be collected into a group that shows a single name, color, and speed on the elevation profile. The segments themselves are untouched and stay individually editable, which suits a course that dips into a freehand line for a few hundred metres where no trail is mapped.

+

The itinerary query returns an itinerary's segment groups as groups, and each segment names the group it belongs to through groupId. Groups are flat rather than nested, so the ordered segment chain stays the primary structure and a run is resolved by matching the ids. An itinerary with no groups returns an empty list.

!

analyzeGeometry and directions now return the trailDifficultyInfo stretches they compute. The field was on the schema but missing from the queries the MCP server and AI agents issue, so the analysis was calculated and then dropped before it reached a caller.

+

Itineraries can be duplicated, optionally into another organization, choosing which segments and waypoints to carry over. The kept segments must stay a continuous run, so only the ends of the remaining route can be dropped.

~

Clicking a segment on the map opens it for editing, the same as clicking its row in the list. A segment a collaborator is already editing stays inert.

!

The mode field on the segment update request has been removed. It was accepted and silently ignored, so a request that set it never changed the segment's routing engine. Changing the engine is now its own operation.