Live sessions
A session (sess_…) is one live conversation with a persona. Your app starts it on its server, the browser joins it, and your server ends it.
Start#
POST /v1/sessions/tokens with a personaId starts a session and answers with what the browser needs: a short-lived sessionToken (it lasts 15 minutes and works for this session only), the url to join, the persona's name, and the AI disclosure. Optional:
| Field | What it does |
|---|---|
identity | Your own id for the person, for your records. |
language, languageMode | This session's language, and whether it follows the person's (follow) or not (fixed). |
overrides | This session only: another systemPrompt, greeting, or values for {{name}} placeholders (variables). |
autoRespond: false | Your app decides every word the avatar says (see below). |
Refusals you can meet: 402 insufficient_minutes, 429 concurrency_limit, 403 feature_not_in_plan, 409 duo_not_live, 409 consent_withdrawn.
The AI disclosure#
People must know they are talking to an AI. Every token carries disclosure (required is always true): keep disclosure.label on or right next to the avatar's video for the whole session and show disclosure.text when it starts. The browser and React SDKs do both for you. What was sent is recorded with the session (GET /v1/sessions/{id}/analytics), and the token says aiGenerated: true. See Telling people it's an AI.
Join#
The browser joins with the token, never the key: the browser SDK (or the React components) shows the avatar and gives you live captions and who is speaking.
While it runs#
Only sessions your API key started can be changed; any other session is 404 not_found.
- Steer it:
PATCH /v1/sessions/{id}changes the instructions, the language or the{{variables}}for the turns that follow. - Make it say something:
POST /v1/sessions/{id}/saywithtext(up to 2,000 characters), optionally in anotherlanguage. In external turn mode (below), and for a duo, the line is spoken exactly as sent, cutting off anything being said unless you sendinterrupt: false. An avatar answering on its own says the line as its next turn once it is quiet, and may word it slightly differently. - Answer every turn yourself: start with
autoRespond: falseand the avatar speaks only the greeting and the lines you send; the browser receives what the person said on the session's live events channel. See Bring your own brain.
End#
POST /v1/sessions/{id}/end (or DELETE /v1/sessions/{id}) ends the session: the room closes, its minutes stop and session.ended goes out once. Leaving the room in the browser doesn't end the session by itself: end it from your server when the person leaves. A session nobody ends is ended by Zentiq's clean-up once its room is found empty, a few minutes later.
status is ACTIVE while it runs, then COMPLETED or ABANDONED.
Afterwards#
GET /v1/sessionslists sessions (source=apifor your app's own), newest first, with filters. A candidate's interview, a child's session and a builder's preview are never listed.GET /v1/sessions/{id}and/analytics: length, minutes, turns, talk share, and a report's numbers where the session has one and its result is released (see Results).responseTimeson a session (listed or read): how fast the avatar started answering,{ p50Ms, p90Ms, maxMs, turns }, measured in the person's browser on Zentiq's own session pages, where an owner has switched on "Measure how fast the avatar answers".nullotherwise, and for sessions your own app shows.GET /v1/sessions/{id}/transcript(scopetranscripts:read): the turns, where Zentiq's rules let the words leave. A candidate's interview is403 candidate_interview; a young learner's conversation is403 learner_conversation; a session whose subject keeps nothing has no turns (kept: false).