Skip to main content
All endpoints require reviewer authentication. See Authentication.

Create an assessment

POST /v1/assessments Creates a new assessment for your organization. Requires an active subscription. Request body
title
string
required
Assessment name. Between 1 and 255 characters.
role
string
required
Role being assessed. Between 1 and 255 characters.
taskBrief
string
Task description shown to the candidate. Required when issueId is not provided. If both are given, an explicit taskBrief takes precedence over the one pulled from the issue.
issueId
string
Pre-configured OSS issue ID. When provided, taskBrief is automatically populated from the issue if you do not supply one.
repoUrl
string
Repository URL for the candidate to work in. Must be a valid URL.
timeLimitMinutes
integer
Time limit for the assessment in minutes.
expiresInDays
integer
default:"7"
Number of days before generated candidate keys expire. Defaults to 7.
rubricId
string (UUID)
UUID of a scoring rubric to apply to sessions from this assessment.
Responses
  • 201 — Assessment created. Returns { assessment: AssessmentObject }.
  • 400 — Invalid request body, or taskBrief is missing and no issueId was provided.
  • 402 — Subscription inactive or trial expired.
  • 403 quota_exceeded — Your plan’s monthly assessment quota has been reached. Response body includes used and quota counts.

List assessments

GET /v1/assessments Returns all active (non-deleted) assessments for your organization, ordered by creation date ascending. Each entry includes linked issue details when an issueId was set. Response
{
  "assessments": [
    {
      "id": "...",
      "title": "Backend API Challenge",
      "role": "Senior Backend Engineer",
      "taskBrief": "...",
      "repoUrl": null,
      "issueId": null,
      "issue": null,
      "timeLimitMinutes": 90,
      "expiresInDays": 7,
      "createdAt": "2026-04-01T09:00:00.000Z"
    }
  ]
}

Get an assessment

GET /v1/assessments/:id Returns a single assessment with its linked issue (if any). This endpoint accepts both reviewer and candidate (API key) authentication so candidates can look up assessment details via the CLI. Responses
  • 200 — Returns { assessment: AssessmentObject } with an issue field (object or null).
  • 404 — Assessment not found or does not belong to your org.

Delete an assessment

DELETE /v1/assessments/:id Soft-deletes the assessment and all of its candidate keys. Deleted assessments and keys no longer appear in list or detail responses. Responses
  • 200 — Returns { ok: true, id: "<assessment-id>" }.
  • 404 — Assessment not found.

Generate candidate keys

POST /v1/assessments/:id/keys Generates one or more candidate keys for an assessment. Requires an active subscription. Request body
count
integer
required
Number of keys to generate. Must be between 1 and 50.
candidateEmails
string[]
Email addresses for each candidate. When provided, an invite email is sent to each address. Length must match count.
candidateNames
string[]
Display names for each candidate. Used in invite emails. Length must match candidateEmails.
orgName
string
Your company name, included in invite email copy.
Responses
  • 201 — Returns { keys: [KeyObject, ...] }. Each key includes its key string (PST-XXXX-XXXX), expiresAt, candidateEmail, and candidateName.
  • 400 — Invalid request body.
  • 402 — Subscription inactive.
  • 404 — Assessment not found.

List candidate keys

GET /v1/assessments/:id/keys Returns all active (non-revoked) candidate keys for an assessment, ordered by creation date ascending. Response
{
  "keys": [
    {
      "id": "...",
      "key": "PST-ABCD-1234",
      "status": "pending",
      "candidateEmail": "alice@example.com",
      "candidateName": "Alice",
      "sessionId": null,
      "expiresAt": "2026-04-08T09:00:00.000Z",
      "redeemedAt": null,
      "completedAt": null
    }
  ]
}

Revoke a candidate key

DELETE /v1/assessments/:id/keys/:keyId Soft-deletes a single candidate key. The candidate will no longer be able to authenticate with that key. Responses
  • 200 — Returns { ok: true, id: "<key-id>" }.
  • 404 — Key not found, already revoked, or does not belong to this assessment.

Get cohort statistics

GET /v1/assessments/:id/cohort-stats Returns aggregate performance metrics computed across all completed sessions for this assessment. Sessions with status completed, expired, or hired are included. Query parameters
sessionId
string
When provided, the response also includes percentile ranks for that specific session relative to the cohort. Percentiles are only computed when the cohort contains at least two sessions.
Response
{
  "cohortStats": {
    "sessionCount": 12,
    "metrics": {
      "avgDurationMs": 4320000,
      "avgPromptCount": 38.5,
      "avgCommandFailRate": 0.142,
      "avgVerifyIntensity": 0.61,
      "avgManualEditRatio": 0.33,
      "avgFirstChangeLatencyMs": 180000,
      "testPassRate": 75
    },
    "percentiles": {
      "durationMs": 0.727,
      "promptCount": 0.455,
      "commandFailRate": 0.818,
      "verifyIntensity": 0.636,
      "manualEditRatio": 0.727,
      "firstChangeLatencyMs": 0.364
    }
  }
}
Returns { cohortStats: null } when no completed sessions exist yet. Percentile values are between 0.0 and 1.0. Higher is better for all metrics except commandFailRate (lower fail rate → higher percentile).

List all candidates

GET /v1/candidates Returns a paginated list of all candidate keys across all assessments in your organization, joined with their parent assessment details. Query parameters
limit
integer
default:"50"
Maximum number of results to return. Clamped to 1–200. Defaults to 50.
offset
integer
default:"0"
Number of results to skip for pagination. Defaults to 0.
Response
{
  "candidates": [
    {
      "id": "...",
      "key": "PST-ABCD-1234",
      "candidateName": "Alice",
      "candidateEmail": "alice@example.com",
      "status": "completed",
      "sessionId": "...",
      "completedAt": "2026-04-02T14:30:00.000Z",
      "redeemedAt": "2026-04-02T09:00:00.000Z",
      "expiresAt": "2026-04-08T09:00:00.000Z",
      "assessmentId": "...",
      "assessmentTitle": "Backend API Challenge"
    }
  ],
  "total": 47,
  "limit": 50,
  "offset": 0
}