Chat reference
product: 'chat' mounts the Kaleidr Chat panel in your page. The panel runs in your document, not in an iframe.
It attaches to a map object you pass, to a Kaleidr viewer or tile element you point it at, or to nothing at all
for a chat-only panel.
This page is the lookup reference. To build a first page, start from a guide: Mapbox, MapLibre, Google Maps or Leaflet.
Requirements
| Plan | Free and up |
| Credential | A publishable key (kld_pk_live_…), or the id of a published Studio map with Control Tower on |
| Scope | ai, present on every new key by default |
| Allowed origin | The page's origin, if the key lists allowed origins |
| Loader | https://cdn.kaleidr.com/embed/v1/kaleidr.js |
| Map library | Optional. See Supported maps. |
Minimal mount
const handle = Kaleidr.mount('#chat', {
product: 'chat',
publishableKey: 'kld_pk_live_…',
map, // your live map object
contained: true, // dock inside #chat
});
Kaleidr.mount(target, options) takes a CSS selector or an element as target. It returns a
handle synchronously and does not throw for a failed mount. The chat bundle loads and the key is
exchanged in the background; if either fails, one error is logged to the console and nothing renders. The one
call that throws is a mount with no options object: Kaleidr.mount('#chat') raises a TypeError.
Mount options
All options are read once, at mount. To change one, call destroy() and mount again. The only exception is the
theme, which setTheme updates.
| Option | Type | Default | Required | Behavior on chat |
|---|---|---|---|---|
product | 'chat' | None | Yes | Selects the Chat product. |
publishableKey | string | None | Yes, unless shareId is given | Your kld_pk_… key. The SDK exchanges it for a session token before the panel makes any request. A kld_sk_… server key is refused in the browser, with a console error and no request. |
shareId | string | None | Yes, unless publishableKey is given | The id of a published Studio map with Control Tower on in its Kaleidr AI tile. Used only when no key is passed. The map's owner pays for the questions. The published map's own viewer already shows this panel. See Kaleidr AI on a published map. |
map | A live map object | None | No | The map the assistant puts pins on and moves. The library is recognized from the object. Omit it for a chat-only panel. |
mapTarget | CSS selector | None | No | A <kaleidr-map> viewer or tile element on the same page for the panel to drive. Ignored when map is given. |
contained | boolean | false | No | true docks the panel inside the mount target, which must be positioned and sized. false appends it to document.body as a fixed window at the top-left of the viewport. |
lang | string | The page's <html lang> when that is a well-formed language tag, otherwise English | No | The language the panel answers in, as a BCP 47 tag such as en, ko or pt-BR. See Language. |
title | string | A title taken from the conversation | No | The title in the chat window's header. See Title and placeholder. |
placeholder | string | Ask Kaleidr | No | The placeholder text of the panel's input. |
theme | object, or a JSON string of one | None | No | CSS custom properties to apply, for example { '--highlight-color': '#7c3aed' }. They are written to :root and are page-wide. |
enabled | boolean | None | No | The per-mount arm of the enable gate. false holds this mount. See kaleidr.js. |
apiBase | URL | https://api.kaleidr.com/inference-api | No | The API the session exchange and the questions go to. It must include the /inference-api path. |
base | URL | https://cdn.kaleidr.com | No | The origin the chat bundle is loaded from. Only the origin is used, and only the Kaleidr CDN (https://cdn.kaleidr.com), the origin kaleidr.js was loaded from or the page's own origin is honored. See the base override. |
apiKey | string | None | No | Deprecated alias of publishableKey. |
Options chat does not use
center, zoom, pitch, bearing, styleId, viewerBase and tileBase are accepted and ignored on a chat
mount. The panel does not set an initial camera; your map keeps the view you gave it.
Options that do not exist
There is no option for a forced map library, voice, or any callback. See Not available today.
Language
lang sets the language the panel answers in. It is sent with every question.
| You pass | Language used |
|---|---|
lang: 'ko', or lang="ko" on the element | That tag, as given. |
No lang, on a page with <html lang="fr"> | The page's language, when the value is a well-formed tag. |
No lang, on a page with no <html lang>, or one that is not a well-formed tag | English. |
- Accepted values are BCP 47 language tags:
en,ko,ja,pt-BR,zh-Hant. A tag longer than 35 characters is refused by the API, and every question then fails with 422lang_too_long. - The page's language is borrowed only when it is well formed: two or three letters, optionally followed by
up to three hyphen-separated subtags of one to eight letters or digits. A value such as an unrendered template
placeholder is skipped and English is used, so a broken
<html lang>never breaks the chat. - An explicit
langalways wins over the page's language. langdoes not translate the title or the placeholder. Their defaults are English. Settitleandplaceholderin the same language aslang.
Title and placeholder
Kaleidr.mount('#chat', {
product: 'chat',
publishableKey: 'kld_pk_live_…',
map,
contained: true,
lang: 'fr',
title: 'Demandez à propos d’un lieu',
placeholder: 'Posez une question',
});
placeholderreplaces the text in the input, which is "Ask Kaleidr" by default.titleis the title of the chat window. The window and its header appear once a conversation starts, and the header then shows your title for every conversation. With notitle, the header shows the visitor's first question, shortened. A minimized chat shows its own conversation's title, taken from the visitor's first question, whether or not you pass atitle.- On the element, the title attribute is
chat-title, nottitle.titleon an HTML element is the browser's hover tooltip, and it would appear over everything inside the element.
Which credential is used
| You pass | Result |
|---|---|
publishableKey | The key is exchanged for a session. shareId, if also given, is ignored. |
shareId only | The published map is exchanged for a session. |
| Neither | The panel renders, and every question fails. No error is logged at mount. |
Which map is used
| You pass | Result |
|---|---|
map | That map object. mapTarget, if also given, is ignored. |
mapTarget only | The Kaleidr viewer or tile element the selector matches. The selector is resolved each time the map is needed, so the element may mount after the panel. |
| Neither, or an object or selector that is not recognized | Chat-only: no pins, no camera moves, no route. Nothing is logged. |
Element attributes
<kaleidr-map product="chat"> is the declarative form. The element itself is the mount target.
<kaleidr-map product="chat" share-id="YOUR_MAP_ID" contained
map-target="#store-map"
style="display:block; position:absolute; inset:0; z-index:1; pointer-events:none"></kaleidr-map>
| Attribute | Option it sets | Notes |
|---|---|---|
product="chat" | product | Required. |
publishable-key | publishableKey | |
share-id | shareId | |
map-target | mapTarget | A CSS selector. |
contained | contained | A bare attribute means true. contained="false" means false. |
lang | lang | A BCP 47 tag. See Language. |
chat-title | title | The header title. Not title, which is HTML's tooltip. |
placeholder | placeholder | The input's placeholder text. |
theme | theme | A JSON string. Changing it after mount applies the new value. |
flag | enabled | flag="false" holds the mount. |
api-base | apiBase | |
base | base | |
api-key | apiKey | Deprecated alias of publishable-key. |
Things to know about the element form:
- It cannot receive a live map object. There is no attribute for
map. To attach to your own Mapbox, MapLibre, Google or Leaflet map, callKaleidr.mount. The element form drives a Kaleidr viewer or tile element throughmap-target, or runs chat-only. - Attributes are read once, when the element connects. Only
themeis applied when changed later. Changingshare-id,publishable-key,map-target,contained,lang,chat-title,placeholderorflagafterwards does nothing; remove the element and insert a new one. - Camera attributes do nothing.
center,zoom,pitchandbearingare ignored at mount on chat, and changing one later logs the "not supported" warning. - The element is
display:blockby default. Forcontained, give it a position and a size. The snippets keepdisplay:blockin the style for Safari before 16.4, where the element stays inline unless you say so. See Theming and layout. - Removing the element destroys the mount. Inserting it again mounts a new panel with a new session.
The full attribute table for every product is on The kaleidr-map element.
Handle
Kaleidr.mount returns the same handle shape for every product. On chat:
| Member | On chat | Behavior |
|---|---|---|
product | 'chat' | Read-only. |
setTheme(theme) | Supported | Takes an object of CSS custom properties, or a JSON string of one. Adds to what is already set. A key without a leading -- gets one. A non-JSON string or an array is ignored with a warning. |
destroy() | Supported | Removes the panel, its place cards, its pins and its route line, and stops session renewal. Safe to call more than once. |
setCamera(camera) | Not supported | Logs a warning and does nothing. Move the map with your map library's own API. |
setStyle(style) | Not supported | Logs a warning and does nothing. |
handle.setTheme({ '--highlight-color': '#0ea5e9' });
handle.destroy();
Calls made before the panel has loaded are queued and applied when it is ready. A destroy() made before the
panel has loaded cancels the mount.
The handle has no ready promise, no on() method, no map member and no way to send a message or read the
conversation. If the enable gate is off at mount, the handle is an inert stub: every method does nothing, and one
console warning names the control that is holding the mount.
The unsupported methods log:
[kaleidr] setCamera() is not supported on product "chat" — the call is a no-op. See the handle matrix at https://docs.kaleidr.com/sdk/kaleidr-map-element#handle-matrix.
The matrix for all four products is at The kaleidr-map element.
What the panel does after mount
- It renders an input bar reading "Ask Kaleidr", or your
placeholder. The first question expands it into a chat window. - Each question is sent with the conversation so far, the id of that conversation, the map's zoom
level when a map is attached, and the language tag: your
lang, else the page's, elseen. What leaves the page lists every request. - Places in an answer become result cards, and pins on the attached map. The camera flies to one place or fits several.
- One mount shows one conversation at a time, and each conversation has its own id. Closing the chat window clears the conversation and its pins, and the next question starts a new conversation under a new id. Minimizing the chat keeps the conversation as a minimized chat; the next question starts a new conversation, and restoring the minimized chat continues it under the id it had. A page reload starts over. Nothing is persisted.
The session exchange
Your publishable key is never used for questions. Before the panel makes any request, the SDK exchanges the key for a short-lived session token and gives the panel only that token.
POST https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions
x-api-key: kld_pk_live_…
content-type: application/json
{"product":"chat"}
{ "session_token": "kld_sess_live_…", "expires_in": 900, "product": "chat", "basemap_style_id": null }
| Behavior | Detail |
|---|---|
| Binding | The session is valid for the chat product, from the origin that requested it. |
| Renewal | The SDK requests a new session 90 seconds before the current one expires, and again when a background tab returns to the foreground with an expired or nearly expired session. |
| A failed renewal | Retried every 30 seconds while the panel is mounted. |
| A failed first exchange | The mount fails. One error is logged, nothing renders, and there is no retry. Mount again to try again. |
Without a key, with shareId | The exchange is POST …/b2b/v1/sdk/share-sessions with the body {"share_id":"…"}. The session lasts 300 seconds. If a renewal is refused with 401, 403 or 404, the SDK stops asking until the page is reloaded. |
Auth and scopes describes keys, sessions and scopes in full.
Lifecycle in a single-page app
- Call
handle.destroy()when the view that holds the map is removed. Destroy the panel before you remove the map, so it can take its pins off. - Mount again when the view returns. That is a new session exchange and a new conversation.
destroy()leaves the panel's stylesheet and any:roottheme properties in the document. See Whatdestroy()removes and leaves.- If you replace the map object (for example, you recreate the map), destroy the panel and mount it with the new object. The panel keeps the object it was given.
Frameworks shows the mount and cleanup pattern for React, Next.js and Vue.
Errors
The SDK reports a failed mount as one console error and does not repeat the server's reason. For an HTTP
failure, open the request in the Network tab and read the JSON body. A 403 or 404 carries its code in the
detail field. A 429 carries its code in the error field, with a sentence in detail.
At mount
| Console | Network | Cause |
|---|---|---|
[kaleidr:chat] mount target not found: <selector> | No request | The selector matched nothing. |
[kaleidr:chat] Kaleidr: a server key (kld_sk_…) must never be used in the browser … | No request | A server key was passed. |
[kaleidr:chat] [kaleidr] failed to load <url> | The request for chat.js failed | The bundle was blocked or the CDN was unreachable. |
A CORS error, then an error containing [kaleidr:chat] | POST …/sdk/sessions blocked by CORS | The key is unknown, revoked or expired, or the page's origin is not in the key's allowed origins. The API sends CORS headers only to an admitted origin, so the browser hides the status and body. |
[kaleidr:chat] kaleidr session exchange failed (403) | 403 insufficient_scope | The key does not carry ai. |
| The same | 403 product_not_allowed | The key is restricted to products that do not include chat. |
| The same | 403 tier_capability_not_allowed | The organization's plan does not currently admit this. |
[kaleidr:chat] kaleidr session exchange failed (429) | 429 rate_limited | More than 30 session requests for this key in a minute. |
[kaleidr:chat] kaleidr session exchange failed (404) | 404 sessions_disabled | Session exchange is switched off on the platform. Not caused by your key. |
[kaleidr:chat] kaleidr session exchange failed (503) | 503 sessions_not_configured | A platform fault. Reload to retry. |
[kaleidr:chat] kaleidr session exchange failed (403) or (404), on a mount with shareId and no key | 403 chat_disabled, 403 origin_not_allowed or 404 not_found | The published map refused the chat. See Kaleidr AI on a published map. |
[kaleidr] embed is disabled — … (a warning) | No request | The enable gate is off. The message names the control. |
[kaleidr] theme string must be JSON … (a warning) | Not applicable | The theme value was a string that is not JSON. The panel mounts without it. |
While the panel is in use
The panel shows failures to the visitor as a line in the conversation. Your code is not notified.
| The visitor sees | Status | Cause |
|---|---|---|
| "Sorry — that didn't go through. Please try again." | 401 | The session is no longer valid: the key was revoked or expired, its allowed origins no longer include this origin, or no credential was given at mount. |
| The same | 5xx, or the network failed | A transient failure. |
| "You've reached your usage limit for now." with a reset time when known | 429 quota_exceeded | The organization's AI credits are spent, or the key's own monthly cap was reached. |
| The same | 429 rate_limited | The key's request rate limit. Every visitor of a page shares the one key. |
| The same | 429 visitor_limit_reached | Keyless chat only: this visitor's per-minute or daily limit. |
Errors is the complete catalog, and Quota and rate limits explains the limits.