Quickstart
One <iframe> pointed at https://app.mountaya.com/studio/embed puts a live, interactive map on your page. Your publishable key and the configuration travel in the query string, and a session token, where your organization requires one, is handed to the embed by your page.
1
Create a publishable key (pk_…) under Settings → API keys in your Mountaya dashboard, and enable the publishing scope. Map Publishing is granted by agreement, and it is all the embed needs: the tiles the embed draws are checked against publishing rather than tiles. Its overlay and content tiles are recorded as your organization's embedding usage, which counts toward its Tile API limit and allowance as your own clients' tiles do. The base map they are drawn on, its terrain style, source tiles, sprites, glyphs and elevation raster, is recorded under terrain and never counted: see what the Tile API counts. Until your agreement grants Map Publishing the scope cannot be enabled: talk to us.
The key is safe to ship in a browser. The site that hosts the iframe must be one of your organization's allowed domains: the embed loads only on a listed site, so with no domain listed it loads on none of yours, even though the API then accepts your key from every page. Under an agreement, Mountaya sets the allowed domains as the agreement states: tell us every site you embed on, each as a host such as maps.example.com. See authentication for the key and scope model.
2
A publishable key with origin validation covers most embeds. If your organization enables session enforcement (require_session_token), also pass a short-lived session_token. Mint one server-side with your secret key, then hand the returned sess_… token to the page that builds the iframe. The hosted embed is part of Map Publishing, not an Embedded Studio, so it needs no studio token: mint it for the default surface, with no surface in the body, and no user_id. A token naming nobody reads what the key alone reaches, so the embed shows what you publish.
A token lives at most five minutes, and a token minted moments earlier for the same key is answered again while it has more than two minutes left, so read its expires_at rather than assuming the full lifetime. The embed renews its own token through the page that frames it, whenever it is framed and either your organization sets require_session_token or its src carries a session_token:
- It posts
mountaya:requestSessionTokento that page as it loads, even when itssrccarried a token, whose expiry the embed cannot read. It asks again one minute before theexpires_atof each answer, and after an ask the page left unanswered, keeping the token it holds meanwhile. - The page answers with
mountaya:setSessionToken, carrying{ token, expiresAt }, posted to the embed's origin alone. The embed sends the new token with its next request, its tiles included, without loading again. Until the page first answers, the embed sends the token itssrccarried, and once it has, the embed reads everything it shows again with the new token, the base map included, so asrctoken that expired before the embed loaded leaves it blank only until that answer. - An embed whose
srccarries no token waits for that first answer before it reads anything under your key, for at most 10 seconds, after which the ask times out. Looking your organization up needs no session token and does not wait. - The embed wizard's preview never asks.
The snippet the embed wizard copies under require_session_token carries a script that does the answering. It fetches your own endpoint, /api/mountaya-embed-session by default (edit the one line that names it), which calls POST /v1/sessions with your secret key and returns its JSON as it is, or its data member alone: the script reads token and expires_at from either. That endpoint is the embed's own, not the /api/mountaya-session an Embedded Studio mints its member tokens at: it calls POST /v1/sessions with a body naming the embed's publishable key alone ({ "publishable_key": … }, no surface and no user_id), the key the iframe carries. The script posts nothing for an answer whose user_id is a string, and says so on the page's console. The script answers only a frame of the embed's origin, so no other frame on your page is handed a token. Paste it once per page, beside the iframe: one copy serves every embed on the page. A page with a strict Content Security Policy moves it into its own bundle. Schedule from expires_at, never a fixed five minutes.
3
Point an <iframe> at the embed route with your key and any configuration as query parameters. This one pins the topographic basemap and turns on two controls.
Keep referrerpolicy="strict-origin-when-cross-origin" on the iframe. The embed serves a frame only when the request names the page it is framed by, and the attribute sends your origin even when the page sets a site-wide Referrer-Policy: no-referrer, which does not override it. Without the origin the embed answers 401 and stays blank.
Append &session_token=sess_your_session_token when your organization enforces session tokens, or leave it out and let the session script answer the embed's first request. A token in the src does not replace the script: it may have expired by the time the embed loads, behind loading="lazy" or in a page served from a cache, and the embed then shows your map once the script first answers.
That is a complete, interactive embed. Add an itinerary_id or a collection_id to show specific content, and the display and with_* parameters to change the look. The full set is on the parameters page.
Troubleshoot a failing embed
- Blank or refused. The embed loads only on a site listed in your organization's allowed domains, and an empty list frames it on none. The exact host the page is served from must be listed: a subdomain is not covered by its parent, and a host with an underscore, or an IPv6 address, cannot frame it at all. An iframe that sends no origin, one without
referrerpolicy="strict-origin-when-cross-origin"on a page whose policy strips it, is answered401too. - An itinerary never published shows nothing. The embed serves the published snapshot alone, so publish the itinerary first. While your organization does not hold Map Publishing, nothing it published is served.
- A private itinerary shows only when named. The embed draws a private itinerary of your own organization when
itinerary_idnames it, as last published, but a collection leaves it out, as every listing does. - A collection's zone does not show. The embed draws a collection's zones only once each is published and public, and only while your organization's
with_collection_zonessetting allows them. A zone is private until you make it public. - A working embed stops loading. Session tokens expire within five minutes. The embed asks the framing page for a new one a minute before expiry, so check that the session script is on the page and that your endpoint answers: a failed endpoint is reported on the page's console, and the embed asks again a minute later.
- No content loads at all. The key must carry the
publishingscope and must not be revoked. - An enabled control does not appear. Your organization's safety rules can lock capabilities off for embedded visitors: the elevation chart, the profile analysis, the overlays and their time control. They cap the result whatever the iframe parameters say, and every rule but the elevation chart's is enforced server-side.