Tile reference
product="tile" shows a Kaleidr basemap, chosen by style id. The SDK
exchanges your publishable key for a tile session, then replaces the contents
of the mount target with an iframe that loads
https://map-embed.kaleidr.com/?style=<style>. The map draws inside that
iframe.
The session is how Kaleidr checks the key, its scope and your page's origin
and counts the map load, and it delivers your organization's default basemap.
It is not passed to the frame. The frame's URL is the style id plus the
camera you gave (camera, pitch, bearing): it carries no publishable key
and no session token, and the map inside the frame makes no call with either.
| Key | A publishable key (kld_pk_live_…). Required. |
| Scope | maps. New keys carry it by default. |
| Plan | Every plan, Free included. |
| Renders in | An iframe from https://map-embed.kaleidr.com. |
| Metering | One map load per tile session. |
| CSP | script-src https://cdn.kaleidr.com, connect-src https://api.kaleidr.com, frame-src https://map-embed.kaleidr.com. |
For a walkthrough, see Use a Kaleidr basemap.
Mount
With the element:
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<kaleidr-map product="tile"
publishable-key="kld_pk_live_…"
style-id="kaleidr-morning"
center="-0.1276,51.5072" zoom="11"
style="display:block; height:480px"></kaleidr-map>
From JavaScript:
const handle = Kaleidr.mount('#basemap', {
product: 'tile',
publishableKey: 'kld_pk_live_…',
styleId: 'kaleidr-morning',
center: [-0.1276, 51.5072],
zoom: 11,
});
Options
| Mount option | Attribute | Type | Default | Required | Description |
|---|---|---|---|---|---|
product | product | 'tile' | none | yes | Selects tile. |
publishableKey | publishable-key | string | none | yes | A kld_pk_… key with the maps scope. A server key (kld_sk_…) is refused in the browser before any request is made. |
styleId | style-id | string | your organization's default basemap, if one is set | recommended | A style id from the table below, or a full https:// URL of a style document. Must match ^[A-Za-z0-9._:/~-]{1,200}$. |
center | center | [longitude, latitude]; the attribute is "longitude,latitude" | the style's default view | no | Opening center. |
zoom | zoom | number | the style's default view | no | Opening zoom. Ignored at mount unless center is also given. |
pitch | pitch | number, degrees | the style's default view | no | Opening tilt. |
bearing | bearing | number, degrees | the style's default view | no | Opening rotation. |
apiBase | api-base | URL | https://api.kaleidr.com/inference-api | no | Where the session exchange is sent. Must include the /inference-api path. You do not need this in production. |
viewerBase | viewer-base | URL | https://map-embed.kaleidr.com | no | Origin the iframe loads from. Only the origin is used. This is the host of the map page, not of the map data. |
base | base | URL | https://cdn.kaleidr.com | no | Origin the SDK loads tile.js from. Only the origin is used, and only the origins listed under The base override are honored. |
enabled | flag | boolean | none | no | Per-mount arm of the enable gate. |
shareId, theme, map, mapTarget, contained and tileBase have no
effect on a tile mount.
Style ids
style-id | Look |
|---|---|
kaleidr-morning | Bright: white ground, cyan water, white roads. |
kaleidr-afternoon | Mid-tone ground with green vegetation and gray roads. |
kaleidr-evening | Golden hour: warm sand and olive tones. |
kaleidr-night | Dark navy and charcoal with amber highways. |
kaleidr-plain | White canvas with borders and place labels. 3D buildings appear from zoom 15. |
kaleidr-editorial | The afternoon palette with labels off, for small or decorative maps. |
Rules:
- Ids are exact and case-sensitive. There are no short aliases.
- When
styleIdis omitted, the embed uses the default basemap your organization has set, which arrives with the session. If none is set, the frame shows "Couldn't find a map id in the URL." PassstyleIdso the result does not depend on an account setting. - An explicit
styleIdalways wins over the organization default. - An id that does not exist produces an empty frame and a
kaleidr-embed:errormessage with the codemaplibre_error. - A value with a character outside the allowed set does not mount. The
console shows
[kaleidr:tile] Kaleidr tile: invalid style "…" — must match ^[A-Za-z0-9._:\/~-]{1,200}$.A style URL therefore cannot carry a query string.
Camera
The opening camera is the style's default view, with each field you pass
replacing the style's value. A style with no default view opens on the whole
world: center [0, 20], zoom 2, no tilt, no rotation.
centeris longitude first:[-0.1276, 51.5072]is London.- At mount,
zoomis used only together withcenter. pitchandbearingare independent ofcenter.
Sizing
- The iframe is 100% of the mount target's width, has no border, and has rounded corners.
- Its height is 100% of the target when the target has a height at mount time. Otherwise it is a fixed 500 pixels.
- The mount replaces the target's children and sets
position:relative(if the target has no inline position) andoverflow:hiddenon it. <kaleidr-map>isdisplay:blockby default, so aheighton it applies. Give it a height. The snippets also writedisplay:block, which covers Safari before 16.4, where the element stays inline.
Handle
Kaleidr.mount returns the handle synchronously. See the
handle matrix for every product.
| Member | On tile |
|---|---|
handle.product | 'tile' |
handle.setCamera(camera) | Moves the map. |
handle.setStyle(style) | Swaps the basemap in place. |
handle.setTheme(theme) | Not supported. Logs a warning and does nothing. |
handle.destroy() | Removes the iframe and stops the session renewals. |
setStyle(style)
handle.setStyle('kaleidr-night');
Takes a style id or a full style URL, resolved the same way as styleId at
mount. The iframe does not reload, the camera stays where it is, and no map
load is counted. Tile is the only product with setStyle.
setCamera(camera)
handle.setCamera({
center: [2.3522, 48.8566], // [longitude, latitude]
zoom: 12,
pitch: 45,
bearing: -20,
duration: 1200, // milliseconds
});
| Field | Type | Description |
|---|---|---|
center | [number, number] | Longitude, latitude. |
zoom | number | Zoom level. Unlike at mount, zoom works without center here. |
pitch | number | Tilt in degrees. |
bearing | number | Rotation in degrees. |
duration | number | Animation length in milliseconds. Omitted or 0 jumps with no animation. |
All fields are optional. Fields you leave out keep their current value.
Timing
You can call setCamera and setStyle at any time after Kaleidr.mount
returns, including on the next line. Calls made before the map inside the
iframe is ready are kept and applied, in order, when the map reports ready.
The latest 256 are kept. If the map has not reported ready after a bounded
wait, normally 10 seconds after the frame loads, the kept calls are sent anyway,
with one console warning. You do not need to wait for the kaleidr-embed:ready message first. For the
view and style the map opens with, mount options are still the direct way:
the map starts there instead of changing to it.
Element attributes after mount
On a mounted <kaleidr-map product="tile">, changing center, zoom,
pitch or bearing moves the map with no animation. Changing style-id,
publishable-key or any other attribute does nothing.
Messages from the iframe
// The basemap drew for the first time.
{ type: 'kaleidr-embed:ready', id: string, source: 'tile' }
// Something failed to draw.
{ type: 'kaleidr-embed:error', id: string, code: 'maplibre_error', message: string }
// No style: none was passed, and the organization has no default basemap.
{ type: 'kaleidr-embed:error', id: null, code: 'no_id', message: string }
id is the style id or URL you passed. With no_id it is null, the frame
shows "Couldn't find a map id in the URL." and ready is not sent.
window.addEventListener('message', (event) => {
if (event.origin !== 'https://map-embed.kaleidr.com') return;
if (event.source !== target.querySelector('iframe')?.contentWindow) return;
const msg = event.data;
if (msg?.type === 'kaleidr-embed:ready') onReady(msg);
if (msg?.type === 'kaleidr-embed:error') onError(msg);
});
readyis sent once, when the map has drawn. It is not sent again aftersetStyle.maplibre_errorcan arrive more than once, before or afterready.- The iframe is created with
loading="lazy", so neither message arrives until the frame comes near the viewport. - A refused session produces no message, because no iframe is created. Look for the console error.
- The frame posts other messages whose
typestarts withkaleidr-embed:. The SDK uses them to connect a chat panel to the map. They are not a public contract.
Session and metering
For each tile mount the SDK sends
POST https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions
x-api-key: kld_pk_live_…
content-type: application/json
{"product":"tile"}
and receives
{
"session_token": "kld_sess_live_…",
"expires_in": 900,
"product": "tile",
"basemap_style_id": "kaleidr-morning"
}
basemap_style_id is your organization's default basemap and is null when
none is set.
Each successful exchange with "product":"tile" counts one map load
against your organization. Exchanges happen:
| When | Count |
|---|---|
| At mount | 1 |
| 90 seconds before the session expires, for as long as the mount exists | 1 each time |
| When the tab becomes visible again and the session is within 90 seconds of expiry, or past it | 1 |
At a new mount after destroy(), or when a removed element is inserted again | 1 |
Notes:
- A failed renewal is retried every 30 seconds. It does not remove a map that is already on screen.
- If the first exchange fails, the mount fails and is not retried. Mount again to retry.
destroy()stops the renewals.- Camera moves, style swaps and visitor interaction never count.
A tile exchange is refused for the first of these that applies:
| Status | detail | Cause |
|---|---|---|
| 403 | publishable_key_required | The key is not a publishable key. |
| 403 | origin_required | The request carried no origin. |
| 403 | origin_not_allowed | The page's origin is not in the key's allowed origins. |
| 403 | product_not_allowed | The key is limited to other products. |
| 403 | tier_capability_not_allowed | The plan does not admit the product. |
| 403 | insufficient_scope | The key lacks the maps scope. |
| 429 | map_load_quota_exceeded | The organization's map loads are used up. |
Before any of these, the exchange answers 404 sessions_disabled when
session exchange is switched off on the platform, and it can answer 503
sessions_not_configured for a platform fault. Neither is caused by your
key. The full list of codes is in Errors.
Pairing with chat
A chat mount can drive a tile element. Give the tile element an id, and point
the chat's map-target attribute (mount option mapTarget) at it:
<div style="position:relative">
<kaleidr-map id="basemap" product="tile" publishable-key="kld_pk_live_…"
style-id="kaleidr-morning"
style="display:block; height:560px"></kaleidr-map>
<kaleidr-map product="chat" publishable-key="kld_pk_live_…" contained
map-target="#basemap"
style="display:block; position:absolute; inset:0; z-index:1; pointer-events:none"></kaleidr-map>
</div>
On a tile map the assistant plots pins with popups, frames the camera on places, and draws routes, the outline of an area such as a city, and live vehicle positions. The walkthrough is in Use a Kaleidr basemap, the layout is explained in Theming and layout, and the chat options are in the Chat reference.
Console messages
| Message | Meaning |
|---|---|
[kaleidr] <kaleidr-map> requires product="chat|viewer|editor|tile" | The element has no valid product. Nothing mounts. |
[kaleidr:tile] kaleidr session exchange failed (<status>) | The exchange was refused. The reason is in the response, visible in the Network tab: the detail field for a 403 and for map_load_quota_exceeded, the error field for a 429 rate_limited. |
A CORS error for …/sdk/sessions, then a [kaleidr:tile] fetch error | The key is unknown or revoked, or the origin is not allowed. A refusal for an origin that is not admitted carries no CORS headers, so the browser hides the response from the SDK. |
[kaleidr:tile] Kaleidr: a server key (kld_sk_…) must never be used in the browser — it is a standing secret. Use your publishable key (kld_pk_…) here and keep the server key server-side. | A server key was passed. No request is made. |
[kaleidr:tile] Kaleidr tile: invalid style "…" — must match ^[A-Za-z0-9._:\/~-]{1,200}$. | styleId has a character that is not allowed. |
[kaleidr:tile] mount target not found: <selector> | Kaleidr.mount found no element for the selector. |
[kaleidr:tile] [kaleidr] failed to load https://cdn.kaleidr.com/embed/v1/tile.js | The tile bundle could not load. |
[kaleidr] setTheme() is not supported on product "tile" — the call is a no-op. … | You called a handle method tile does not have. |
[kaleidr] setStyle() IS supported on product "tile", but this mount did not expose it, so the call did nothing. … | The page is running an older cached tile.js. Reload without the cache. |
Not available
- Adding your own markers, layers or popups to the map.
- Events for clicks, camera moves or selections.
- Reading the camera back.
- A way to use the map without the iframe.