Sessions
List, get, create, and control assessment sessions
A session is one assessment attempt. Auth: organization API key.
Only for partner customers. Pass the active organization with the optional x-organization-id header. Omit it to use the organization that owns the API key. A partner key may pass a direct child. An unknown organization returns 404. An organization the key cannot access returns 403. A non-empty organization_id query or body field returns 400 VALIDATION_ERROR.
| Method | Path | Summary |
|---|---|---|
GET | /v1/sessions | List sessions |
GET | /v1/sessions/:id | Get one session by UUID |
POST | /v1/sessions | Create a session |
Session status
session_status is the lifecycle of one attempt. Poll GET /v1/sessions/:id until it is COMPLETED, FAILED, DROPPED_OUT, or EXPIRED.
| Status | Meaning |
|---|---|
PENDING | Created. The environment is not ready yet. |
PROVISIONING | Compute is starting. |
READY | The lobby is ready. Recording has not started. |
DROPPED_OUT | The candidate clicked "I am ready" and never began recording within 30 minutes. A container sandbox is destroyed. No evaluation runs and no session webhooks fire. |
EXPIRED | Still PENDING when expires_at passed. The lobby link is already closed at expires_at. A minute cron writes this status. No evaluation runs and no session webhooks fire. |
RECORDING | The candidate is in the assessment. recording_started_at is set. Webhooks: SESSION.STARTED on entry, SESSION.STOPPED on exit. |
STORING_INPUT_EVENTS | Recording stopped. Input events are being stored (container and VM sessions). |
CONVERTING_VIDEO | The recording is being converted. |
GENERATING_NARRATIVE | The narrative is being written (container and VM sessions). |
GENERATING_EVALUATION | An evaluation set is running. EVALUATION_SET.STARTED fires when latest_evaluation_set_id is set. |
COMPLETED | The attempt finished. latest_evaluation_set is present when automatic evaluation ran, and null when the organization scores later. EVALUATION_SET.STOPPED fires only when status becomes COMPLETED and a set id is set. |
FAILED | Provisioning or evaluation failed. |
Local sessions skip STORING_INPUT_EVENTS and GENERATING_NARRATIVE: they go from RECORDING to CONVERTING_VIDEO, then to GENERATING_EVALUATION or straight to COMPLETED.
Older sessions may still report SAVING, WAITING_FOR_EVALUATION, or CANCELLED from an earlier pipeline.
lobby_url uses the organization's active vanity domain when one is configured, including a domain inherited from a parent organization, and otherwise uses the default Skillflare origin.
List
curl "https://api.skillflare.co/v1/sessions?limit=20&offset=0" \
-H "x-api-key: sk_skillflare_YOUR_KEY" \
-H "x-organization-id: CHILD_ORG_UUID"Returns { data, meta } as described in Errors and pagination. Each item:
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"created_at": "2026-01-15T12:00:00.000Z",
"session_status": "PENDING",
"candidate_full_name": "Alex Example",
"candidate_email": "alex@example.com",
"candidate_meta": { "external_id": "ats-123" },
"lobby_url": "https://skillflare.co/sessions/b2c3d4e5-f6a7-8901-bcde-f12345678901/lobby?t=...",
"expires_at": null
}id— session UUID (use this in path params).created_at— when the session was created (ISO 8601).session_status— current session status.candidate_full_name— candidate display name, ornullif unknown.candidate_email— candidate email, ornullif unknown.candidate_meta— opaque partner metadata from create-candidatemeta, or{}when unset. Same value webhooks send ascandidate_meta.lobby_url— candidate link to open the session lobby, ornull.expires_at— when the lobby link stops working (ISO 8601), ornullwhen the link does not expire. After this time the candidate lobby returns403SESSION_LINK_EXPIRED. List and get still return the session.
Get by id
curl https://api.skillflare.co/v1/sessions/b2c3d4e5-f6a7-8901-bcde-f12345678901 \
-H "x-api-key: sk_skillflare_YOUR_KEY" \
-H "x-organization-id: CHILD_ORG_UUID"A session that belongs to another organization is NOT_FOUND.
Returns the session at the top level. Detail adds publish and recording fields, the latest evaluation set, and a signed URL for the canonical evaluation file:
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"created_at": "2026-01-15T12:00:00.000Z",
"session_status": "COMPLETED",
"candidate_full_name": "Alex Example",
"candidate_email": "alex@example.com",
"candidate_meta": { "external_id": "ats-123" },
"lobby_url": "https://skillflare.co/sessions/b2c3d4e5-f6a7-8901-bcde-f12345678901/lobby?t=...",
"expires_at": "2026-02-01T23:59:59.999Z",
"published_at": null,
"recording_started_at": "2026-01-15T12:06:00.000Z",
"latest_evaluation_set": {
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"created_at": "2026-01-15T13:00:00.000Z",
"total_score_avg": 0,
"total_score_min": 0,
"total_score_max": 0,
"score_confidence": 1,
"evaluations": [
{
"id": "d4e5f6a7-b8c9-0123-def0-234567890123",
"total_score": 0,
"evaluation_status": "COMPLETED",
"evaluation_error": null,
"scores": [{ "title": "Discovery", "points": 0, "max_points": 0 }]
}
]
},
"url": "https://sessions.example/signed-recording",
"evaluation_url": "https://evaluations.example/signed-evaluation.json"
}id— session UUID (use this in path params).created_at— when the session was created (ISO 8601).session_status— current session status.candidate_full_name— candidate display name, ornullif unknown.candidate_email— candidate email, ornullif unknown.candidate_meta— opaque partner metadata from create-candidatemeta, or{}when unset. Same value webhooks send ascandidate_meta.lobby_url— candidate link to open the session lobby, ornull.expires_at— when the lobby link stops working (ISO 8601), ornullwhen the link does not expire.published_at— when the candidate published the session, ornull.recording_started_at— when recording began, ornull.latest_evaluation_set— latest evaluation set with aggregates and member evaluations, ornull. Point totals on this object are the set aggregates. They are not re-read from the evaluation file.url— signed URL for the session recording, ornullwhen it cannot be signed.evaluation_url— signed GET URL for the canonical evaluation'sevaluation.json, ornullwhen no completed member exists or the URL cannot be signed. The link expires after one hour. Fetch it separately. The file stays in object storage and is not copied into the database. A lowscore_confidencestill includes this URL when a canonical file exists.
Member evaluation_status is PREPARING, COMPLETED, FAILED, or FURTHER_REVIEW. FURTHER_REVIEW is set on completed member evaluations when the set reaches its grader cap without a cluster (score_confidence is 0).
Invalid UUIDs → VALIDATION_ERROR. Missing session → NOT_FOUND.
Create
Creates a session for a candidate on a challenge.
curl https://api.skillflare.co/v1/sessions \
-H "x-api-key: sk_skillflare_YOUR_KEY" \
-H "x-organization-id: CHILD_ORG_UUID" \
-H "content-type: application/json" \
-d '{
"candidate_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"challenge_id": "e5f6a7b8-c9d0-1234-ef01-345678901234",
"expires_at": "2027-02-01T23:59:59.999Z"
}'| Field | Required | Notes |
|---|---|---|
candidate_id | Yes | Candidates resource id, linked to the active organization. Missing → candidate_id is required. Not a UUID → candidate_id must be a uuid. Unknown or outside the org → 404 Candidate does not exist |
challenge_id | Yes | A challenge the active organization can access. Missing → challenge_id is required. Not a UUID → challenge_id must be a uuid. Unknown or inaccessible → 404 Challenge does not exist |
expires_at | No | ISO 8601 timestamp. Omit, null, or "" for a lobby link that does not expire. Not a timestamp → 400 expires_at must be an ISO 8601 timestamp. At or before now → 400 expires_at must be in the future |
The challenge status must be READY, WARMING_UP, or PREPARING. Any other status returns 400 VALIDATION_ERROR with message Challenge must be READY before creating a session. A CONTAINER challenge also needs a packaged image: Challenge has no packaged image; finish packaging first when the image is missing, and Challenge image has no E2B template when the image has no template.
Success: 201 with:
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"invite_sent": true,
"lobby_url": "https://skillflare.co/sessions/b2c3d4e5-f6a7-8901-bcde-f12345678901/lobby?t=...",
"expires_at": "2027-02-01T23:59:59.999Z"
}id— session UUID.invite_sent—truewhen an invite email was queued for the candidate. The email uses the active organization's name and branding. See Where branding is applied.lobby_url— candidate link to open the session lobby.expires_at— the stored deadline, ornullwhen the link does not expire.
After expires_at, opening the lobby link returns 403 SESSION_LINK_EXPIRED with message This assessment link has expired. The candidate sees an Expired screen. A minute cron then sets session_status to EXPIRED when the session is still PENDING. List and get still return the session.
A missing session, a session outside the key's organization, or a session with no VM returns 404 Session does not exist.