Sessions
A session is the unit of everything: one running avatar, from creation to teardown. This page covers the full lifecycle beyond the happy path in the Quickstart.
Lifecycle
Section titled “Lifecycle”- Create:
POST /v1/sessionswithavatar_id,mode, and optionallyvoice_id+transport: "livekit". Returnssession_id,livekit_url,participant_token,room_name,agent_identity. - Connect: the client joins the LiveKit room using
livekit_url+participant_token. The agent appears as another participant; subscribe to its video + audio tracks. See Streaming into your app. - Drive: your server calls
POST /v1/sessions/{id}/speak(or/audio) whenever the avatar should talk, andPOST /v1/sessions/{id}/interruptto cut it off. - Idle (optional):
POST /v1/sessions/{id}/waiting_stateparks the session in its idle loop without ending it, and resumes it later. - Reconnect (as needed): LiveKit SDKs handle reconnect internally; on long-dropped sessions your mint proxy may re-mint via
POST /v1/sessionsto get a freshparticipant_token. - End:
DELETE /v1/sessions/{id}when the conversation is over, releasing the session’s resources.
Creating a session
Section titled “Creating a session”curl -X POST https://api.2wai.ai/v1/sessions \ -H "Authorization: Bearer $TWAI_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{ "avatar_id": "avt_441ad4d95906438490a85b79", "mode": "video", "voice_id": "vc_e72e888d566aca3a4e63fbe8", "transport": "livekit" }'Listing and inspecting sessions
Section titled “Listing and inspecting sessions”List sessions on your account, optionally filtered by status:
curl "https://api.2wai.ai/v1/sessions?status=active" \ -H "Authorization: Bearer $TWAI_SECRET_KEY"Fetch a single session:
curl https://api.2wai.ai/v1/sessions/$SESSION_ID \ -H "Authorization: Bearer $TWAI_SECRET_KEY"Pausing without ending
Section titled “Pausing without ending”If a user steps away mid-conversation but you expect them back, park the session instead of tearing it down and re-creating it later:
curl -X POST https://api.2wai.ai/v1/sessions/$SESSION_ID/waiting_state \ -H "Authorization: Bearer $TWAI_SECRET_KEY" \ -H "Content-Type: application/json" \ -d '{"waiting": true}'Send {"waiting": false} to resume active rendering. This keeps the session (and its session_id) alive and still counts against your concurrency limit (see Limits & concurrency), so end sessions you no longer need rather than leaving them parked indefinitely.
Reconnecting after a dropped LiveKit connection
Section titled “Reconnecting after a dropped LiveKit connection”LiveKit SDKs handle short network blips automatically — the SDK reconnects to the same room with the same participant_token without any help from your mint proxy. For longer drops (token expired, room closed, server-side session ended), mint a new session and have the client re-join the fresh livekit_url + participant_token:
async function reconnect(mintProxyURL) { const res = await fetch(mintProxyURL, { method: 'POST' }); // your own backend route const { livekit_url, participant_token } = await res.json(); await room.disconnect(); await room.connect(livekit_url, participant_token);}Ending a session
Section titled “Ending a session”Always end sessions you’re done with. This frees the concurrency slot immediately instead of waiting for an idle timeout:
curl -X DELETE https://api.2wai.ai/v1/sessions/$SESSION_ID \ -H "Authorization: Bearer $TWAI_SECRET_KEY"Good times to call this: the user closes the chat/tab (via a beforeunload handler that fires a sendBeacon to your backend), your app’s own idle timeout fires, or the conversation is explicitly ended.
Session hygiene checklist
Section titled “Session hygiene checklist”- End sessions when a user leaves; don’t rely solely on idle timeouts.
- Don’t create a new session per message. One session covers an entire conversation. Reuse it and drive it with
/speak//audio. - Let your LiveKit SDK handle reconnect for short blips; re-mint via
POST /v1/sessionsfor longer drops rather than letting a stale token surprise you. - Watch
x-twai-concurrent-sessionson responses so you can back off before you’re throttled. See Limits & concurrency.
- Streaming into your app for the browser side of steps 2-3.
- Limits & concurrency for how many sessions you can run at once.