Persona

Sessions API reference

Base URL: https://persona.ignited.tools (or your custom domain). All bodies are JSON. Errors look like:

{ "error": { "code": "invalid_api_key", "message": "Missing or invalid secret API key." } }

Authentication

CredentialLooks likeWhere it's usedWho may hold it
Secret keysk_live_…POST/DELETE /api/v1/sessionsYour server only
Publishable keypk_live_…POST /api/v1/anonymous-sessionsAny web page on your allowed sites
Chat sessioncs_…/api/v1/chat, /api/v1/personaThe browser of one subclient

Send all of them as Authorization: Bearer <value>.

Create a session

POST /api/v1/sessions, with a secret key.

curl https://persona.ignited.tools/api/v1/sessions \
  -H "Authorization: Bearer $PERSONA_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subclient": {
      "id": "user_123",
      "name": "Dana Lee",
      "email": "dana@example.com",
      "metadata": { "plan": "pro" }
    },
    "expires_in": 3600
  }'
FieldRequired
subclient.idyesYour id for this user. Stable: the same id is the same subclient (history, memory). Up to 128 characters: letters, numbers and . _ : @ | + -
subclient.namenoShown in your Conversations and used by the persona to greet them
subclient.emailnoShown in your Conversations
subclient.metadatanoUp to 20 string key/values, shown in Conversations
expires_innoSeconds, 60 to 86400. Default 3600

201 Created:

{
  "session": {
    "token": "cs_…",
    "expires_at": "2026-10-30T12:00:00.000Z",
    "client_id": "cli_…",
    "subclient_id": "user_123",
    "url": "https://persona.ignited.tools/chat/cli_…#session=cs_…"
  }
}

Requests that carry a browser Origin header are rejected with 403 browser_request. Secret keys must never reach a browser.

End a user's sessions

DELETE /api/v1/sessions, with a secret key. Body: { "subclient_id": "user_123" }. Returns { "revoked": 2 }. Use it on sign-out, account deletion or when you suspect a token leaked.

Anonymous sessions

POST /api/v1/anonymous-sessions?client_id=cli_…, with a publishable key, from a page on one of your allowed sites. Body: { "client_id": "cli_…", "visitor_id": "v_…" } (visitor_id optional; pass the one you got last time to continue as the same visitor). Requires Let anonymous visitors chat. Returns { "session": { "token", "expires_at", "visitor_id" } }. Sessions last 2 hours. The widget does all of this for you.

Hosted links

Send a signed-in user to a full-page chat without embedding anything: create a session on your server and redirect to session.url. The token is in the URL fragment (#session=…), which browsers never send to servers or put in Referer headers. The page reads it, then removes it from the address bar.

app.get("/coach", requireLogin, async (req, res) => {
  const { session } = await createPersonaSession(req.user); // POST /api/v1/sessions
  res.redirect(session.url);
});

Persona profile

GET /api/v1/persona with a chat session. Returns the public face of the persona for a chat UI: name, photo, tagline, welcome message and your theme (app name, logo, accent color, appearance). It never returns knowledge, offers or other subclients.

Chat

POST /api/v1/chat with a chat session. See Headless.

Session lifetimes

SessionLifetimeRenewal
Server-created (cs_…)expires_in, default 1 hour, max 24 hoursThe widget calls getSession again
Anonymous (cs_…)2 hoursThe widget creates a new one
Dashboard sign-in30 daysSign in again
Sign-in email link15 minutes, single useRequest a new link