Get an API key
An API key identifies your organization to Kaleidr. Every request made with it, from a browser or from a server, is admitted against your organization's plan and counted against your organization's usage. You create and manage keys at kaleidr.com/api-keys.
You need a key to use Chat, Editor and Tile, and to call the server API. You do not need a key to embed a published map with Viewer: the map's id is enough.
The two key types
A key comes in one of two types. Which one you create depends on where the code that uses it runs.
| Publishable key | Server key | |
|---|---|---|
| Prefix | kld_pk_live_… | kld_sk_live_… |
| Where it runs | In a web page: the SDK and the <kaleidr-map> element | On your servers only |
| Safe in page source | Yes | No. Treat it like a password. |
| How it is used | The SDK exchanges it for a short-lived session token, and the session makes the calls | Sent directly on each request as Authorization: Bearer or X-Api-Key |
| Can be limited to | The sites you list as allowed origins | Any restriction set through the key API, such as an IP allowlist |
| Plans | Free, Pro, Enterprise | Pro, Enterprise |
| Name on the API Keys page | Browser / Embed Key | Server Key |
Use a publishable key for anything that runs in a visitor's browser. It is designed to be visible. What protects it is the allowed-origins list and the fact that it cannot call the API on its own: a publishable key sent directly to an API endpoint is refused with 401 publishable_requires_session.
Use a server key when your backend calls Kaleidr: a job that geocodes addresses, an API route that streams an answer to your own front end, a mobile app's backend. A server key is refused whenever a request carries an Origin header (403 server_key_in_browser), which is what a browser sends, and the SDK refuses to mount with one before it makes any request. Never put a server key in a web page or a mobile app binary.
Both types belong to the same organization and draw on the same usage pools. See How Kaleidr works for sessions, organizations and metering.
Keys created before the two types existed start with kld_live_. They keep working and are sent directly, like a server key.
What each plan admits
Your organization's plan decides which key types it can create, which scopes a key may carry and which products a key may mount.
| Plan | Publishable | Server | Scopes admitted | Products admitted |
|---|---|---|---|---|
| Free | Yes | — (403 free_plan_publishable_only) | ai, maps, design | chat, editor, viewer, tile |
| Pro | Yes | Yes | ai, maps, design | chat, editor, viewer, tile |
| Enterprise | Yes | Yes | ai, maps, design, vendor* | chat, editor, viewer, tile |
* vendor is never included by default, and only an Enterprise key can carry it. See Scopes.
Each plan also limits how many active keys an organization holds:
| Plan | Active keys |
|---|---|
| Free | 2 |
| Pro | 10 |
| Enterprise | 25 |
Past the limit, creating a key is refused with 409 key_limit_reached; revoke a key to create another. Rotating a key does not count as creating one, but the old key still counts until its grace period ends.
Five points about this table:
- Free runs every browser product. A Free organization can put Chat, Editor, Tile and Viewer on its site. Chat answers spend the Free plan's monthly AI credits; when they are spent, requests return 429 until the next billing period, an add-on pack or an upgrade.
- Viewer is in the table because a plan admits it, not because a key unlocks it. A published map embeds with no key on every plan.
- Pro adds server keys and more keys. A Pro organization can create server keys for its backend and hold 10 active keys instead of 2. It admits the same scopes and products as Free.
- Your own business data in AI answers is Enterprise only, in both halves. An owner or admin of an Enterprise organization can upload business data, within the limits set in the organization's agreement, and Kaleidr Studio's assistant answers from it for the organization's signed-in members. Free and Pro cannot upload it. Holding a key that may read the data through the API or the SDK (the
vendorscope) is also available to Enterprise organizations only: a request to create a key withvendoron Free or Pro is refused with 403tier_capability_not_allowed. Your data covers the whole path. - Every plan can add datasets to a map in Kaleidr Studio. A signed-in user uploads files (spreadsheets and geographic files) in a map's Data panel, on Free, Pro and Enterprise. The limits depend on the plan: on Free, 50,000 rows in one dataset, 32 MiB for one file and 250,000 rows across the organization's datasets; on Pro, 100,000 rows, 64 MiB and 5,000,000 rows. On Enterprise, one dataset and one file have the same ceilings as on Pro (100,000 rows and 64 MiB), and the total across the organization is set in the agreement. This data is drawn on the map, in Studio and for visitors of the published map, and Studio's AI assistant answers questions about it; it is not read through an API key. See Datasets on a map.
Plan prices and allowances are on the pricing page. Enterprise allowances are custom and set in your contract.
Scopes
A scope is a permission a key carries. A product or endpoint checks for the scope it needs.
| Scope | What it allows | On a new key |
|---|---|---|
ai | Chat, and the server API's chat, place and geocoding endpoints | Included |
maps | Tile basemap sessions | Included |
design | Editor, and the server API's design endpoints | Included |
vendor | Lets Chat answers draw on your organization's published business data | Not included; must be requested. Enterprise only. |
A key created on the API Keys page always carries ai, maps and design. The page has no scope picker. To create a key with vendor (Enterprise only), or without one of the default scopes, use the key API.
Scopes are fixed when the key is created. They cannot be edited afterward, and rotating a key keeps its scopes, with two exceptions: a scope your current plan no longer admits is left off the replacement, and on Free the replacement always carries the whole Free surface (see When your plan changes). To change a key's scopes, create a new key and revoke the old one.
When your plan changes
What a key may do is the overlap of what the key carries and what your current plan admits, checked on every request.
From Enterprise to Pro or Free. Existing keys keep working. A key that carries vendor keeps the scope in its stored settings, but the scope stops applying: the key no longer brings your business data into answers, and no error tells you so. Requests succeed and are answered from general knowledge. Browser sessions issued before the change are ended: their next request returns a 401, and the SDK obtains a new session under the new plan. On Pro, rotating such a key succeeds and returns a replacement without vendor; its other scopes and its product list are unchanged. The organization can no longer upload business data: the upload calls return 403 vendor_data_not_on_plan. Its owners and admins can still list, unpublish and delete the releases it uploaded.
To Free. A Free organization cannot create new server keys, and cannot rotate a server or legacy key it already holds: the rotation is refused with 403 free_plan_publishable_only. Rotating a publishable key on Free returns a replacement that carries the whole Free surface (ai, maps, design, and all four products), whatever the old key held. Datasets already added to maps in Kaleidr Studio are kept; a new upload is checked against the Free dataset limits. Browser sessions issued before the change are ended in the same way, and the SDK obtains new ones.
Moving back up restores what the plan admits. A key that still stores vendor reaches your data again on Enterprise. A replacement that was rotated on a lower plan does not regain the scope; create a new key for that.
Create a key
You must be an owner or admin of your organization.
- Sign in at kaleidr.com and open kaleidr.com/api-keys. The page lists your organization's keys under Your API Keys.
- Choose Create Key. A dialog titled Create a Key opens with three fields.
- Key Name. A label for you, such as
Production site. It is never shown to visitors. Name keys after where they run so you can tell them apart when you revoke one. - Key Type. Choose Browser / Embed Key (publishable) or Server Key. On the Free plan the Server Key option is not shown. The type cannot be changed later.
- Allowed Origins. For a publishable key, enter the sites that may use it, separated by commas, for example
https://www.example.com, https://app.example.com. Leave it empty to allow every site. See Allowed origins for the format. A server key is not tied to a site, so leave this empty for one. - Choose Create Key.
- Copy the key now. The dialog shows the full key once, with the warning "Copy this key now — it won't be shown again." Choose Copy, store the key, then choose Done. Kaleidr does not keep the full value. If you lose it, rotate the key to get a new one.
What you should see: the new key in the table with its first characters under Key, its name, its type (Browser or Server), the status Active and today's date.
If the page says "You must be an organization admin to manage API keys.", ask an owner or admin of your organization to create the key or change your role.
Allowed origins
Allowed origins are the list of sites a publishable key works from. When the SDK exchanges the key for a session, the browser sends the page's origin in the Origin header and Kaleidr compares it with the list.
- An empty list allows every site. That is convenient while you build, but anyone who copies the key from your page source can then use it on their own site and spend your allowance. Give every production key a list.
- A list with at least one entry allows only those entries. The match is exact:
https://example.comdoes not coverhttps://www.example.com, andhttp://localhost:3000does not coverhttp://localhost:5173. List each one.
An origin is a scheme, a host and an optional port, with no path:
| Entry | Accepted |
|---|---|
https://www.example.com | Yes |
https://app.example.com:8443 | Yes |
http://localhost:8000 | Yes. http is accepted for localhost and 127.0.0.1 only. http://[::1] can be set through the key management API, not on this page. |
http://www.example.com | No. Sites other than localhost must use https. |
https://www.example.com/store | No. An origin has no path. |
*.example.com | No. There are no wildcards. https://*.example.com is saved as written and matches no site. |
A key holds at most 100 origins.
To change the list, choose the edit (pencil) action on the key's row. In the Edit Key dialog, change Allowed Origins and choose Save changes. The same dialog renames the key.
- Adding an origin takes effect for new sessions from that site.
- Removing an origin stops that site. Sessions already issued to a page on the removed origin fail on their next request with 401
Invalid or missing API key, instead of running until they expire.
What a blocked site looks like. When a page on an origin that is not in the list tries to mount a product, the exchange is refused with 403 origin_not_allowed. The response carries no CORS headers, so the browser reports a CORS error for the request to …/b2b/v1/sdk/sessions, the SDK logs a [kaleidr:<product>] error and nothing renders. Troubleshooting shows the exact text.
The allowed-origins list limits where a key works from in a browser. It does not make a publishable key secret, and a request that is not from a browser can send any Origin it likes. Security model explains what the list does and does not protect, and CORS and allowed origins covers the request details.
Rotate and revoke
Rotate a key to replace its value without downtime. Choose the rotate action on the key's row and confirm. Kaleidr issues a replacement with the same type, scopes and allowed origins and shows its value once. The old key keeps working for 24 hours, so you can deploy the new value before the old one stops. During those 24 hours the old key counts toward your plan's key limit and cannot be rotated again.
Rotate a key when someone who had access to it leaves, or on whatever schedule your security policy sets. For a key that has leaked, revoke it instead: a rotation from this page leaves the old value working for 24 hours.
Revoke a key to stop it immediately. Choose the delete (trash) action on the key's row and confirm. The page warns: "Revoke this API key? Any site using it will stop working immediately." Revoking also ends every session issued from the key, so open pages stop on their next request. A revoked key cannot be restored.
Revoke, do not rotate, when a server key has leaked: the 24-hour grace period would keep the leaked value working.
Test keys
Both key types have a test variant: kld_pk_test_… and kld_sk_test_….
A test key is not a sandbox. It calls the same API, gets the same answers and spends the same AI credits and map loads as a live key. One thing differs: a test key cannot load basemap tiles.
What a test key gives you is separation. Traffic from your staging site is tied to its own key, which you can revoke without touching production. Do not treat test traffic as free.
The API Keys page creates live keys only. Create a test key through the key API with "environment": "test".
Options the page does not offer
The API Keys page sets a key's name, type and allowed origins. A key has more settings, and they are available through the key API at https://api.kaleidr.com/shared-api/api-keys.
The key API is authenticated as you, not as a key: send the access token of a signed-in organization owner or admin as Authorization: Bearer. An API key cannot create or change keys.
| Field | Type | Default | What it does |
|---|---|---|---|
name | string, 1–200 characters | required | The key's label. |
org_id | UUID | your primary organization | The organization the key is created in. Send it in the body: on the create call a query org_id is ignored. |
key_type | "publishable" or "server" | "publishable" | The key type. Fixed after creation. |
environment | "live" or "test" | "live" | Creates a live or a test key. Fixed after creation. |
scopes | string array | ["ai", "maps", "design"] | The scopes the key carries. Fixed after creation. |
vendor_acknowledged | boolean | false | Must be true to create a publishable key that carries vendor. |
allowed_origins | string array, up to 100 | [] | Allowed origins. Publishable keys only. |
allowed_products | string array | [] (all products) | Limits the key to some of chat, editor, viewer, tile. Applies to every key type: see the note under this table. |
allowed_ips | string array, up to 100 | [] (any address) | IP addresses or CIDR ranges a server key may call from. |
monthly_cap_tokens | integer, 0 or more | none | The most AI credits this key may spend in a billing period. 1 or more is a cap; 0 or null means no cap. |
expires_at | date-time in the future | none | When the key stops working. |
On the Free plan, scopes and allowed_products are always set to everything the plan admits (ai, maps, design; chat, editor, viewer, tile), whichever of them the request names, and the same holds for a key rotated on Free. On every plan, a request that names a scope or a product the plan does not admit is refused with 403 tier_capability_not_allowed; nothing is dropped from a request without an error.
A product limit is enforced wherever the key is used. A publishable key limited to some products is refused with 403 product_not_allowed at the session exchange when a page mounts a product outside the list. A server key (or a legacy key) limited to some products is refused with the same 403 product_not_allowed on each request to an endpoint of another product: the chat, place and geocoding endpoints belong to chat, and the design endpoints belong to editor. A server key that should call every endpoint its scopes allow needs an empty allowed_products. The endpoint-to-product table is in Auth and scopes.
This request creates a publishable test key limited to Chat on one staging site:
curl -X POST https://api.kaleidr.com/shared-api/api-keys \
-H "Authorization: Bearer $KALEIDR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Staging site chat",
"key_type": "publishable",
"environment": "test",
"allowed_origins": ["https://staging.example.com"],
"allowed_products": ["chat"]
}'
A 201 response carries the key's settings and, once only, the full value in plaintext_key:
{
"id": "5f0c2a9e-…",
"name": "Staging site chat",
"key_prefix": "kld_pk_test_…",
"key_type": "publishable",
"environment": "test",
"scopes": ["ai", "maps", "design"],
"allowed_origins": ["https://staging.example.com"],
"allowed_products": ["chat"],
"allowed_ips": [],
"monthly_cap_tokens": null,
"status": "active",
"expires_at": null,
"plaintext_key": "kld_pk_test_…"
}
A key that can read your business data
The vendor scope lets Chat answers draw on the business data your organization has published. Uploading that data and holding the scope that reads it through a key are both available on Enterprise only, and the scope is granted only through the key API:
curl -X POST https://api.kaleidr.com/shared-api/api-keys \
-H "Authorization: Bearer $KALEIDR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Site chat with our data",
"key_type": "publishable",
"scopes": ["ai", "vendor"],
"vendor_acknowledged": true,
"allowed_origins": ["https://www.example.com"]
}'
vendor_acknowledged exists because a publishable key sits in your page source: anyone who can load the page can ask the chat questions, and the answers may include your uploaded data. Setting the field to true records that you intend that.
- A publishable key that requests
vendorwithout"vendor_acknowledged": trueis refused with 422vendor_scope_requires_acknowledgement. - A server key needs no acknowledgement.
- On Free and Pro, a request that includes
vendoris refused with 403tier_capability_not_allowed, whether or notvendor_acknowledgedis sent. No key is created.
Your data covers uploading the data and checking that an answer used it.
Changing a key (PATCH /shared-api/api-keys/{id}) accepts name, allowed_origins, allowed_products, allowed_ips, monthly_cap_tokens and expires_at. Rotating (POST /shared-api/api-keys/{id}/rotate) accepts grace_hours from 0 to 8760; with the default of 0 the old key stops at once. Revoking is POST /shared-api/api-keys/{id}/revoke. The refusal codes for these calls are listed under Errors.
Two prerequisites every embed needs
A correct key is not enough for a keyed product to render. Two things about the page itself must also be true, and the browser reports both failures in ways that do not point at the cause.
1. The page is served from an origin the key allows
- Serve the page over HTTP or HTTPS, including while you develop. A file opened from disk (
file://) has no origin that can be listed on a key. - If the key lists allowed origins, your page's origin must be one of them, written exactly as the browser sends it: scheme, host and port. For local work that usually means adding
http://localhost:<port>.
When this is wrong, nothing renders and the console shows a CORS error for the session exchange. It looks like a network problem; it is the allowed-origins list.
2. Your Content Security Policy allows what the product loads
If your site sends a Content-Security-Policy header, it must allow the Kaleidr hosts each product uses. A site with no such header needs nothing.
| Product | What your policy must allow |
|---|---|
| Viewer, Tile | Scripts from https://cdn.kaleidr.com, a frame from https://map-embed.kaleidr.com, and for a keyed mount a connection to https://api.kaleidr.com |
| Chat, Editor | Scripts from https://cdn.kaleidr.com, connections to https://api.kaleidr.com, and inline styles, because both products add their styles to your page. Editor also loads its basemap from https://tile.kaleidr.com. |
Content Security Policy has the complete policy for each product, directive by directive.
When this is wrong, the browser logs a Refused to load… or Refused to connect… message that names the blocked address and the directive.
Use the key
In a web page, pass a publishable key to the product. The SDK exchanges it for a session and keeps the session fresh for as long as the product is mounted.
<script src="https://cdn.kaleidr.com/embed/v1/kaleidr.js"></script>
<kaleidr-map
product="tile"
publishable-key="kld_pk_live_…"
style-id="kaleidr-morning"
style="display:block; height:480px"
></kaleidr-map>
What you should see: the basemap renders, and the Network tab shows a 200 from https://api.kaleidr.com/inference-api/b2b/v1/sdk/sessions. The Quickstart has a complete page for each product.
From a server, send a server key on each request. This call lists the map styles the design endpoints know about; it spends no AI credits, which makes it a good first check that a key works.
curl https://api.kaleidr.com/inference-api/b2b/v1/design/styles \
-H "Authorization: Bearer kld_sk_live_…"
What you should see: a 200 with a JSON object that has a styles array. A 401 with {"detail":"Invalid or missing API key"} means the key value is wrong or the key was revoked. A 403 with {"detail":"server_key_in_browser"} means the request carried an Origin header; remove it. Server quickstart continues from here.
Next steps
- Quickstart: one working page for Chat, Viewer and Tile.
- How Kaleidr works: sessions, organizations and the two usage pools.
- Auth and scopes: how each credential is sent and checked.
- Production checklist: one key per site, allowed origins and the rest before you ship.