Iframe events
Past its initial configuration, the embed speaks a small postMessage API. Your page sends commands in to switch the displayed content, and the embed posts a ready event back once the map settles. Every message is an object with a type field prefixed mountaya:.
Send a command
Post a message to the iframe's contentWindow to change what the embed shows after it has loaded. One command switches the content; the other, mountaya:setSessionToken, renews the session token.
mountaya:setItinerarycommand
Switch the map to an itinerary. The message carries itineraryId plus any of the optional display overrides below. itineraryId is required: a string, or null to show no itinerary, which leaves the base map alone, or on a collection embed the whole collection, framed again. A message without it is refused, so a member dropped by mistake never clears your embed.
Any override field you include is applied; any you omit leaves the embed's current state unchanged, and so does null on withOverlays or withTerrains. The fields are camelCase: terrain, withOverlays and withTerrains (arrays of slugs), and the boolean toggles withDirectionsControl, withDownloadControl, withNavigationControl, withOverlaysControl, withPreferencesControl, withProfileAnalysis, withProfileCharacteristics, withProfileElevation, withProfilePaceControl, and withStreetviewControl.
Overrides respect your organization's safety rules exactly as the iframe parameters do. A locked-off capability stays off even when a command sets it, and the overlay list is held to your organization's overlay allowlist; no safety rule caps the terrains. Every rule but the elevation chart's is enforced server-side.
Here the same message switches the content and changes the terrain:
Target the embed's origin (https://app.mountaya.com) when you post it.
The examples page wires the same command into a React component.
Listen for the ready event
The embed posts mountaya:ready each time the map settles: on the initial load, after every mountaya:setItinerary switch, when a load ends in an error, and once more when the embed rebuilds its map with your page's first session token. It rebuilds only where it had already read without that token: with another session_token its src carried, or with none, where your page left its first ask unanswered. Listen with a message handler and key on the message type.
typestring
Always "mountaya:ready". Key your handler on this so you ignore unrelated messages.
errorstring | null
null on a clean load. Otherwise "timeout" if the map did not finish loading in time, or "not_found" if the requested content could not be resolved. The field is always present, so test error === null for success.
bounds[number, number, number, number] | null
The framed content's own geographic extent as [west, south, east, north] in WGS 84, not the padded viewport: the itinerary's, or on a collection embed with no itinerary the extent of the collection's itineraries the visitor is served (with itineraryId null). It is null when no content frames the view, which includes a base-map-only embed, an itinerary or collection that yields no extent, and any load that ended in an error.
itineraryIdstring | null
The active itinerary id, or null if none is displayed.
terrainstring
The resolved basemap terrain slug.
A successful ready event looks like this:
The ready event is posted with a wildcard target origin, so check event.origin before trusting the message.
Renew the session token
A framed embed asks the page that frames it for a session token when your organization sets require_session_token or its src carries a session_token, because a token lives minutes and only your server can mint one. The embed wizard's preview never asks.
mountaya:requestSessionTokenevent
Posted by the embed as it loads, even when its src carried a token, whose expiry it cannot read; then one minute before the expires_at of each answer, and again after an ask your page left unanswered, while the embed keeps the token it holds. It carries no payload and no secret, so it is posted with a wildcard target origin: check event.origin before answering it.
mountaya:setSessionTokencommand
Your page's answer: { type, token, expiresAt }, the token and expires_at that POST /v1/sessions returned to your server. Post it to the embed's origin alone, never *. The embed sends the token with its next request, its tiles included, without loading again. Until your page first answers, the embed sends the token its src carried, and an embed whose src carries none waits for that answer, for at most 10 seconds, before it reads anything under your key. An embed that read with its src token reads everything it shows again once that first answer lands, the base map included, so a src token that expired before the embed loaded holds the map up only until then.
The snippet the embed wizard copies under require_session_token carries a script that answers for you, from your own endpoint, /api/mountaya-embed-session by default. It mints { publishable_key } alone, for the embed's own key, with no surface and no user_id; the script posts nothing for a session that names a user. Paste it once per page; a page with a strict Content Security Policy moves it into its own bundle. Read expiresAt rather than counting five minutes: a token minted moments earlier is answered again while it has more than two minutes left. The quickstart states the endpoint's side.
The full public protocol
mountaya:setItinerary, mountaya:ready, and the session pair mountaya:requestSessionToken and mountaya:setSessionToken are the whole protocol available to an embed on your own domain: two commands in, two events out.
Inspecting the embed's traffic may reveal other mountaya: message types. They are internal to the Mountaya console, and the embed answers them only when the sender shares its own origin, which your page never does. Posting one from your site is ignored rather than refused. Build only on the four above.