Skip to main content
A session represents one AI interview — the conversation, the recording, the transcript, and the scorecard. Sessions are the core unit of usage and the most-handled object in the API.

Status lifecycle

   created       ┌──────────────┐
   ─────────────►│  scheduled   │  Session row created. AI is provisioned;
                 └─────┬────────┘  candidate has a join URL.

        candidate joins│  (started_at is stamped here, on room open)

                 ┌──────────────┐  AI is conversing with the candidate.
                 │ in_progress  │  Transcript streams in; authenticity
                 └─────┬────────┘  signals captured live.

       ┌───────────────┼───────────────┬───────────────┐
       │               │               │               │
 connection drops   completes   recruiter cancels   platform error
       ▼               ▼               ▼               ▼
┌──────────────┐ ┌──────────┐   ┌──────────┐   ┌──────────┐
│ disconnected │ │ completed│   │cancelled │   │  failed  │
└──────────────┘ └──────────┘   └──────────┘   └──────────┘
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:
1

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.
2

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.
3

Automatic resume email

The candidate is emailed a one-click link to resume, which starts a fresh attempt — subject to the round’s max_attempts. Once that budget is spent, no further automatic retry is sent.
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.
TransitionEvent fired
Created (via API or UI)session.created
Candidate joinssession.started
Completes naturallysession.completed
Connection drops / platform errorsession.failed (payload status is disconnected or failed)
Cancelled by recruitersession.cancelled
Scorecard finalizedsession.scored (fires 30s–2min after completed)
Listen for session.scored, not session.completed, when you want the full rubric scorecard. session.completed fires the moment the AI hangs up; scoring happens asynchronously and session.scored is the signal that the scorecard is final.

Reading a session

curl "https://www.intervyo.ai/api/v1/sessions/e3a1c2d4-..." \
  -H "x-api-key: $INTERVYO_API_KEY"
const res = await fetch(
  `https://www.intervyo.ai/api/v1/sessions/${id}`,
  { headers: { "x-api-key": process.env.INTERVYO_API_KEY! } },
);
const { data } = await res.json();
import os, requests

res = requests.get(
    f"https://www.intervyo.ai/api/v1/sessions/{session_id}",
    headers={"x-api-key": os.environ["INTERVYO_API_KEY"]},
)
data = res.json()["data"]
Returns:
{
  "data": {
    "id": "e3a1c2d4-...",
    "status": "completed",
    "role_id": "ce1cd564-...",
    "candidate_id": "ba4f2cdd-...",
    "stage": "screen",
    "score": "8.2",
    "passed": true,
    "recommendation": "hire",
    "ai_feedback": "Strong candidate with clear system design...",
    "evaluation_breakdown": [
      { "name": "Technical Depth", "score": 8.5, "feedback": "..." },
      { "name": "Communication",   "score": 7.8, "feedback": "..." }
    ],
    "duration_seconds": 2740,
    "started_at": "2026-06-02T07:48:31Z",
    "ended_at": "2026-06-02T08:21:14Z"
  }
}
See Get Session for the full schema.

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 same candidate_id. See Roles for how Rounds chain together.

Session vs application

These are two different objects, easy to confuse:
ObjectPurpose
SessionOne 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.
The Applications panel on the template detail page reads from 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).
Last modified on July 10, 2026