Skip to main content
A session is one voice call: a media room, a dispatched agent, a participant, and the transcript/usage recorded when it ends. Every voice conversation is a session, whichever way it started — a browser client, an API-fired call, a campaign attempt or an inbound call.

Create a session

POST /sessions is authenticated with a bearer login session (not an API key) and sessions:write, because the session is attached to the logged-in user.
To place an outbound phone call from your backend, use POST /calls instead — it takes an API key, and adds retries, calling windows and idempotency. POST /sessions is the browser/dashboard path.
The response is a SessionRecord that includes the participant_token — this is the only place the token is returned. Connect it to room_name at livekit_url with a voice client to join the call.
customer_id, user_id, agent_id, and session_id are stamped server-side and overwrite any client-supplied metadata. Participant tokens never appear in list/get responses.

Web vs outbound phone

  • Web — the browser participant connects to the room and talks to the agent. The token grants publish + subscribe.
  • Outbound phone — the agent dials the recipient over SIP; the token is subscribe-only (the human is on the phone leg). Requires an outbound SIP trunk to be configured on the deployment.

Status lifecycle

  • ended_at is set on the transition to any terminal status.
  • Long-running active sessions are swept to expired after the session TTL (default 24h).
  • Terminal status is frozen. Once a session is ended, failed, or expired, its status and ended_at stop changing. A PATCH /sessions/{id}/status on a terminal session is a silent no-op — 200 with the record unchanged, not an error.
  • Ending tears down the room. POST /sessions/{id}/end (or a PATCH that drives the session terminal) deletes the media room, so an explicit end actually stops a call that would otherwise keep billing.

Manage a session

GET /sessions is paged: pass ?limit= (default 20, max 100) and ?offset=, and read pagination.total from the { "data": [...], "pagination": { ... } } envelope.

Results

When a call ends, the agent posts a session-update webhook with the transcript, usage, and a session report — merged into the session record and used for billing. For production, register an outbound webhook and receive call_completed rather than polling. Two fields are written during that finalize step:
  • outcome — how the call ended: completed, no_media, no_answer, busy, declined, failed, user_disconnected or expired. It’s the same vocabulary campaigns use to decide retries and analytics uses to aggregate.
  • sentimentpositive, negative or neutral, and only for agents that opted into sentiment analysis.

Webhooks & Events

Receive transcript and usage.

Campaigns

Run sessions in bulk.