Everything a visitor’s browser does — connecting the SDK, joining conversations, sending messages — is authorized by a short-lived SDK token. This page explains the credentials involved and the three ways to obtain a token.
Keys stay on your backend. Tokens go to the browser. Your App ID, public key (pk_…), and especially your secret key (sk_…) must never appear in frontend code. The frontend only ever receives a token.

Credentials

Create an app in the dashboard to get its App ID, public key, and secret key. You can rotate the secret at any time (POST /apps/:id/rotate-secret) — it’s shown only once.

Three ways to get a token

Mint a token

Backend mints a token for a known user. Most flexible.

Support session

Backend mints a token and opens a support conversation in one call.

Anonymous session

Browser self-provisions with just a public key. No backend.

1. Mint a token (server-to-server)

Your backend calls POST /api/v1/apps/:appId/tokens with either your API keys or a dashboard JWT, and returns the token to your frontend.
Use this when you already have conversations (e.g. an external conversation for an order or appointment chat) and just need to authorize the current user. Full reference: Issue SDK Token.

2. Start a support session (one call)

For a support widget, POST /api/v1/apps/:appId/support-sessions mints the token and creates the support conversation together, returning both token and conversation_id. See Start a Support Session.

3. Anonymous session (no backend)

A static site can provision entirely in the browser using only the public key: POST /api/v1/sdk/anonymous-session with X-Api-Key: pk_…. The request’s Origin must be in the app’s allowed origins (secure by default — empty means disabled). See Open an Anonymous Session.

Using a token

Once your frontend has a token, hand it to the SDK or widget — it manages the WebSocket connection and auth for you:
Connecting to the WebSocket directly instead? See WebSocket Authentication.

Token lifetime & refresh

SDK tokens are short-lived. When you issue a fresh token (e.g. on page load), update the client without tearing down your app state:

Dashboard authentication

Your own admin app (not the visitor-facing frontend) authenticates dashboard users with a JWT via POST /api/v1/auth/login, and refreshes it via POST /api/v1/auth/refresh. These tokens carry a role (OWNER, ADMIN, AGENT, MEMBER) and are used for management APIs like bot config, FAQs, the support inbox, and agent tools.

Security checklist

Secret stays server-side

Never ship sk_… (or App ID / public key for server auth) to the browser.

Allow-list origins

For anonymous embeds, add only the exact sites you trust to the app’s allowed origins.

HTTPS / WSS only

Always use TLS in production for both the API and the WebSocket.

Rotate secrets

Rotate the app secret if it may have leaked (POST /apps/:id/rotate-secret).

Quickstart

Put a token to work end-to-end.

Issue SDK Token

Full endpoint reference.