Status lifecycle
scheduled
Session row created. AI hasn’t joined yet. The candidate can join via the
join_url from the invite at any time.in_progress
Candidate joined and the AI is actively interviewing. Transcript +
authenticity signals stream into the session record live.
completed
Interview finished naturally — the AI delivered the closing line and
ended the call. Scorecard ready within 2 minutes.
disconnected
The candidate’s connection dropped mid-interview and they did not return
within the reconnect grace window. Distinct from
failed: nothing broke on
our side — the network did. The partial transcript is retained, and if the
candidate was in the interview long enough, a scorecard flagged incomplete
is still produced. error.message carries the LiveKit disconnect reason
(CLIENT_INITIATED, SIGNAL_CLOSE, …) and a connection-quality trail.failed
A platform or agent error interrupted the session (missing interview
context, an unrecoverable agent error, a crash). Reserved for problems on
our side — candidate connection drops surface as
disconnected instead.
Partial transcript may still be available; no scorecard.Before the
disconnected status existed, connection drops were also
reported as failed. The value is additive: existing integrations that
only branch on failed keep working, but new code should treat
disconnected as the “candidate’s network” case and failed as the
“something broke” case.cancelled
Recruiter cancelled the session via the API or UI before the candidate
joined. No interview happened.
no_show
The candidate never joined before the scheduled window elapsed. No
interview happened; no scorecard.
Reconnecting after a drop
A candidate’s connection dropping is not immediately terminal. When the candidate’s client disconnects mid-interview:Grace window (3 minutes)
The room and AI interviewer stay alive. The candidate’s existing
join_url remains valid — reopening it drops them back into the same
session. On rejoin the AI welcomes them back and repeats its last question
verbatim; it does not restart or re-introduce itself.Grace window expires
If the candidate hasn’t returned within the window, the session moves to
disconnected. If they were in the interview long enough, a scorecard
flagged incomplete is still produced from the partial transcript.Drops are also headed off before they happen: the candidate lobby runs a
pre-join mic check plus a browser/network preflight (warning on non-Chrome
browsers, weak connections, and VPNs), and mid-interview the AI proactively
tells the candidate when their audio is breaking up so they can fix it before
the line fully drops.
Status changes emit events
Every state transition fires a webhook. Configure your endpoint to receive them — see Webhooks for the payload shape + HMAC signing.| Transition | Event fired |
|---|---|
| Created (via API or UI) | session.created |
| Candidate joins | session.started |
| Completes naturally | session.completed |
| Connection drops / platform error | session.failed (payload status is disconnected or failed) |
| Cancelled by recruiter | session.cancelled |
| Scorecard finalized | session.scored (fires 30s–2min after completed) |
Reading a session
Re-runs and retries
Each session is immutable once it lands in a terminal state (completed / failed / cancelled). If you need another interview for
the same candidate — say after a technical failure — create a fresh
session. Sessions for the same (participant, stage) are independent
rows; the platform doesn’t try to “merge” or “supersede” them.
The Applications panel on each template’s detail page automatically
picks the latest session per stage when displaying the rolled-up
status, so retries surface immediately.
Multi-stage progression
Multi-stage templates auto-create a fresh session for the next stage when a candidate passes a stage. You don’t need to manually invoke this — the session-status mirror trigger handles it. A candidate’s full trajectory through a 3-Round Role ends up as 3 sessions, one per Round, linked through the samecandidate_id. See
Roles for how Rounds chain together.
Session vs application
These are two different objects, easy to confuse:| Object | Purpose |
|---|---|
| Session | One conversation between AI and participant. Holds the transcript, scores, recording. |
Application (template_applications) | The relationship between a participant and a template. Tracks HR approval, scheduling status, and the latest session. Created by the public apply flow or by manually adding a participant to a template. |
template_applications, but the data shown (scores, transcripts, status)
comes from the latest session joined onto the application. They’re paired
1:N — one application can have many sessions over time (retries,
multi-stage progressions).