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
| Credential | Looks like | Where it's used | Who may hold it |
|---|---|---|---|
| Secret key | sk_live_… | POST/DELETE /api/v1/sessions | Your server only |
| Publishable key | pk_live_… | POST /api/v1/anonymous-sessions | Any web page on your allowed sites |
| Chat session | cs_… | /api/v1/chat, /api/v1/persona | The 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
}'
| Field | Required | |
|---|---|---|
subclient.id | yes | Your id for this user. Stable: the same id is the same subclient (history, memory). Up to 128 characters: letters, numbers and . _ : @ | + - |
subclient.name | no | Shown in your Conversations and used by the persona to greet them |
subclient.email | no | Shown in your Conversations |
subclient.metadata | no | Up to 20 string key/values, shown in Conversations |
expires_in | no | Seconds, 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
| Session | Lifetime | Renewal |
|---|---|---|
Server-created (cs_…) | expires_in, default 1 hour, max 24 hours | The widget calls getSession again |
Anonymous (cs_…) | 2 hours | The widget creates a new one |
| Dashboard sign-in | 30 days | Sign in again |
| Sign-in email link | 15 minutes, single use | Request a new link |