Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.karta.sh/llms.txt

Use this file to discover all available pages before exploring further.

A session token is how an end user’s browser reaches a Karta project safely. A kt_live_… key is an org-wide management credential and must never ship to a client. Instead, your backend mints a short-lived, project-scoped JWT per authenticated end user, and the widget presents that. This is the standard “ephemeral client secret” pattern: the long-lived secret stays on your server; a narrow, expiring token reaches the browser.

The flow

  end user ──login──▶ B's backend ──(kt_live_ key)──▶ POST /agent_projects/:slug/session_tokens
                          │                                     │ mints HS256 JWT
                          ◀─────────────── session token ───────┘

  B's widget ──(session token)──▶ DATA PLANE  /v1/projects/:ref/sessions, .../messages, .../stream
1

Your backend mints a token

After your own auth confirms the user, call the mint endpoint with your kt_live_… key. You get back an HS256 JWT scoped to one org + project, with a short TTL (~15 min).
2

The widget uses it

The browser presents the session token to the project’s consumer endpoints — create a session, send, stream. It can be used on the /v1/projects/{ref}/… routes and the consumer adapters, but not on the flat /v1/sessions management routes.
3

The data plane verifies it offline

The data plane verifies the signature, scope, and expiry against the shared KARTA_SESSION_TOKEN_SECRET — no round-trip to the control plane on the hot path.

What the token pins

The minted JWT pins org_id, project_id, project_slug, scope, and exp. Because org and project are pinned, cross-tenant access is blocked: a token for one project can’t touch another.
Per-user binding is a decided, not-yet-implemented hardening. Today the token does not bind the specific end user, so cross-user isolation within an org currently rests on your integration discipline (the user_id you put in session metadata). The decision is to add a sub = user_id claim and enforce metadata.user_id == claims.sub at session-create time, turning per-user isolation into a platform guarantee. Until then, mint one token per authenticated user and set the matching user_id yourself.

Why not just use an API key?

A kt_live_… key grants org-wide management access — keys, BYOK, budgets, deploys. Putting one in a browser or mobile app exposes your whole org. The session token exists precisely so the browser never needs the key: it’s minted server-side, scoped to a single project, and expires in minutes.
See Personas for where this sits in the full trust model, and API keys for the credential it replaces at the edge.