API reference
Generated from the running server — API v1, OpenAPI 3.0.0.
Authentication
Public API endpoints take an organization API key as a bearer token. Everything else is reached by the portal or by a desktop agent with its own session token.
Authorization: Bearer sk_…
Privacy-first, consent-based interview-integrity platform for secure remote interviews and technical assessments.
Public API (`/v1/api/*`)
Authenticate with an org API key: Authorization: Bearer sk_…. A key's authority is exactly its scope set — it holds no org role. Keys are created in the portal under Developers → API keys and the secret is shown once.
Environments. A sk_test_… key is a sandbox credential: every session it creates is flagged sandbox and every read it makes is filtered to sandbox rows. Live and test data never meet.
Versioning. v1 is additive-only: new endpoints and new optional request/response fields may appear at any time and are not breaking — ignore response fields you do not know. A change that would remove or re-type an existing field ships as a new version instead.
Deprecation. Every response carries X-Proctor-Api-Version. When something is deprecated its responses also carry Deprecation: true and a Sunset date at least 180 days out. It keeps working, unchanged, until that date.
Rate limits. 120 requests/60s per key and 600/60s per org. Every response reports RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset and RateLimit-Scope (which ceiling is closest); a 429 adds Retry-After.
Idempotency. Send Idempotency-Key: <unique> on any write. A retry with the same key and the same body replays the first response (Idempotency-Replayed: true); the same key with a different body is refused with idempotency_key_reuse. Keys are remembered for 24h.
Pagination. Lists take limit (default 20, max 100) and offset, and answer with { items, total, limit, offset }.
Errors. { success: false, error: { code, message }, requestId } — branch on code, never on the message. Codes: invalid_request, unauthorized, insufficient_scope, forbidden, not_found, conflict, idempotency_key_reuse, rate_limited, service_unavailable, internal_error.
Events, webhooks and the stream. The same catalog is delivered two ways: signed webhook POSTs to endpoints you register (/v1/api/webhooks), and a live SSE subscription (/v1/api/events/stream). Both carry the same envelope with the same id, so dedupe on the event id — delivery is at-least-once — and ignore event types you do not know.
Webhook signatures. Every delivery carries X-Proctor-Signature: t=<unix>,v1=<hex> — an HMAC-SHA256 over "<timestamp>.<raw body>" keyed by the endpoint's secret. Verify it, and reject any timestamp more than 300s from your clock.
Webhook retries. 6 attempts, waiting 10s, 60s, 300s, 1800s, 7200s between them, then a dead letter you can replay from the delivery log. An endpoint that dead-letters 10 deliveries in a row is disabled and its org admins are emailed.
What this API will not do. It reports observations — event counts, evidence, transcripts — and never a verdict about a candidate. Scoring or judging a person from these signals is the integrator's own act, taken on its own authority; a human decides (PRD hard rule 4).
Node SDK
@proctor/sdk v1.0.0 — a typed client whose types are generated from this document, so a shape that compiles is a shape the API serves. It handles retries, idempotency keys, pagination and webhook signature verification for you.
Install
One API key, one base URL. The client speaks API v1 and reports its rate-limit budget on every response.
pnpm add @proctor/sdk export PROCTOR_API_KEY=sk_test_… export PROCTOR_BASE_URL=http://localhost:4000
Schedule a session and fetch its results
examples/schedule-and-fetch.ts
/**
* Schedule a session, hand out its join link, and read the results.
*
* Run: PROCTOR_API_KEY=sk_test_… PROCTOR_BASE_URL=http://localhost:18410 tsx schedule-and-fetch.ts
*/
import { Proctor } from "@proctor/sdk";
const proctor = new Proctor({
apiKey: process.env.PROCTOR_API_KEY ?? "",
baseUrl: process.env.PROCTOR_BASE_URL ?? "http://localhost:18410",
});
// 1 — Schedule it. `externalId` is your own handle (a requisition, a ticket); we never invent one.
const { session } = await proctor.sessions.create({
externalId: `req-${Date.now()}`,
candidateLabel: "Candidate A",
config: { retentionDays: 30, capture: { enabled: true } },
});
console.log(`session ${session.id} · ${session.state}`);
// 2 — Mint a single-use link. The candidate's desktop agent redeems it; consent is asked there.
const link = await proctor.sessions.createJoinLink(session.id, {
role: "candidate",
});
console.log(`join code ${link.joinCode} · expires ${link.expiresAt}`);
// 3 — Wait for it to end. Production would use a webhook; a script can poll.
const finished = await proctor.sessions.waitForState(session.id, ["ended"], {
timeoutMs: Number(process.env.PROCTOR_WAIT_MS ?? 120_000),
throwOnTimeout: false,
});
console.log(`state ${finished.state} · ${finished.eventCount} integrity events`);
// 4 — Read what came out. Counts and artifacts: observations, never a verdict — a human decides.
const report = await proctor.sessions.report(session.id);
console.log(`report · ${report.signalTotal} signals · ${report.inventoryObjects} objects`);
for await (const evidence of proctor.sessions.iterateEvidence(session.id)) {
console.log(`evidence ${evidence.id} · ${evidence.evidenceType} · ${evidence.sizeBytes} bytes`);
}
Receive and verify a webhook
examples/webhook-receiver.ts
/**
* A webhook receiver: verify the signature, then act on the event.
*
* Run: PROCTOR_WEBHOOK_SECRET=whsec_… tsx webhook-receiver.ts (listens on PORT, default 4300)
*/
import { createServer } from "node:http";
import { constructWebhookEvent, ProctorWebhookSignatureError } from "@proctor/sdk";
import { WEBHOOK_SIGNATURE } from "@proctor/protocol";
const secret = process.env.PROCTOR_WEBHOOK_SECRET ?? "";
const seen = new Set<string>();
createServer((req, res) => {
// The signature covers the RAW bytes — verify before parsing, never after.
const chunks: Buffer[] = [];
req.on("data", (chunk: Buffer) => chunks.push(chunk));
req.on("end", () => {
const body = Buffer.concat(chunks).toString("utf8");
const signature = req.headers[WEBHOOK_SIGNATURE.header.toLowerCase()];
let event;
try {
event = constructWebhookEvent(body, String(signature ?? ""), secret);
} catch (error) {
// A body that cannot prove where it came from is not a body. 400, and nothing else happens.
if (error instanceof ProctorWebhookSignatureError) {
console.warn(`rejected delivery: ${error.reason}`);
res.writeHead(400).end();
return;
}
throw error;
}
// Delivery is at-least-once and a stream resume can repeat one: dedupe on the event id.
if (!seen.has(event.id)) {
seen.add(event.id);
console.log(`${event.type} · session ${event.sessionId ?? "—"} · ${event.createdAt}`);
}
// Answer 2xx immediately; do the slow work elsewhere, or the retry policy becomes your queue.
res.writeHead(200).end();
});
}).listen(Number(process.env.PORT ?? 4300), () => {
console.log(`listening on :${process.env.PORT ?? 4300}`);
});
Tail the live event stream
examples/stream-events.ts
/**
* Tail the live event stream and reconcile anything missed while the process was down.
*
* Run: PROCTOR_API_KEY=sk_test_… tsx stream-events.ts
*/
import { Proctor } from "@proctor/sdk";
const proctor = new Proctor({
apiKey: process.env.PROCTOR_API_KEY ?? "",
baseUrl: process.env.PROCTOR_BASE_URL ?? "http://localhost:18410",
});
// Where we stopped last time. A real receiver persists this; a script starts from the last event.
const [latest] = (await proctor.events.list({ limit: 1 })).items;
let cursor = latest?.id;
const stop = AbortSignal.timeout(Number(process.env.PROCTOR_STREAM_MS ?? 600_000));
// Resuming replays what was published while we were away, then goes live at the same seam.
for await (const event of proctor.events.stream({
lastEventId: cursor,
signal: stop,
})) {
cursor = event.id;
console.log(`${event.type} · session ${event.sessionId ?? "—"} · ${event.createdAt}`);
}
console.log(`stream closed · resume from ${cursor ?? "the beginning"}`);
The SDK moves observations, evidence and transcripts between this API and your systems. It never scores or judges a candidate — that decision is yours, and a human makes it.
Events, webhooks and the stream
The push side of the API. Every event below is delivered identically by webhook and by the live stream — same envelope, same id. Catalog version 2026-09-04; new types may appear at any time, so ignore ones you do not recognise rather than failing.
| Type | What it means |
|---|---|
| session.scheduled | webhooks.events.session.scheduled |
| session.started | webhooks.events.session.started |
| session.ended | webhooks.events.session.ended |
| evidence.ready | webhooks.events.evidence.ready |
| companion.paired | webhooks.events.companion.paired |
| companion.placement_confirmed | webhooks.events.companion.placement_confirmed |
| companion.recording_started | webhooks.events.companion.recording_started |
| companion.recording_stopped | webhooks.events.companion.recording_stopped |
| companion.interrupted | webhooks.events.companion.interrupted |
| companion.resumed | webhooks.events.companion.resumed |
| source.health_changed | webhooks.events.source.health_changed |
| report.finalized | webhooks.events.report.finalized |
| report.stale | webhooks.events.report.stale |
| webhook.test | webhooks.events.webhook.test |
Delivery and retries
Delivery is at-least-once: dedupe on the event id. A failed delivery is retried up to 6 times, waiting 10s, 60s, 300s, 1800s, 7200s between attempts, then kept as a dead letter you can replay. An endpoint that dead-letters 10 deliveries in a row is disabled and its org admins are emailed.
Every delivery carries: X-Proctor-Signature, X-Proctor-Event-Id, X-Proctor-Event-Type, X-Proctor-Delivery-Id, X-Proctor-Delivery-Attempt.
Verifying a delivery
Check X-Proctor-Signature before you trust a body. It is an HMAC-SHA256 over "<timestamp>.<raw body>" keyed by the endpoint's signing secret, presented as t=<unix>,v1=<hex>. Reject anything whose timestamp is more than 300 seconds from your clock — that is what makes a captured delivery useless to replay. Ignore key/value pairs you do not know; that is how a future scheme version ships without breaking you.
import { createHmac, timingSafeEqual } from "node:crypto";
// body must be the RAW request bytes, before any JSON parsing.
export function verify(body, header, secret) {
const parts = new Map(header.split(",").map((p) => p.trim().split("=")));
const timestamp = Number(parts.get("t"));
const presented = parts.get("v1");
if (!Number.isFinite(timestamp) || !presented) return false;
// Reject anything older than the tolerance — this is what stops a captured replay.
const age = Math.abs(Math.floor(Date.now() / 1000) - timestamp);
if (age > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${timestamp}.${body}`)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(presented);
return a.length === b.length && timingSafeEqual(a, b);
}Live stream
The same catalog as Server-Sent Events, authenticated by the same API key with the events:read scope. Filter with ?types= and ?sessionId=. Reconnect with Last-Event-ID to replay what you missed, up to 200 events — further behind than that, reconcile over GET /v1/api/events instead.
curl -N "http://localhost:4000/v1/api/events/stream?types=session.started,session.ended" \ -H "Authorization: Bearer $PROCTOR_API_KEY"
health
- GET
/v1/healthPortal / agentLiveness probe
- GET
/v1/health/readyPortal / agentReadiness probe
storage
- GET
/v1/orgs/{orgId}/storagePortal / agentWhere this org's evidence is stored (owner/admin only)
Parameters: orgId (path, required)
- PUT
/v1/orgs/{orgId}/storagePortal / agentSet the storage provider. Validated against the provider before it is accepted.
Parameters: orgId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/storage/validatePortal / agentRe-probe the stored configuration and record whether it still works
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/storage/migratePortal / agentRun or resume the move of existing evidence to the current provider (bounded per call)
Parameters: orgId (path, required) — Takes a JSON body.
- GET
/v1/orgs/{orgId}/storage/migrationPortal / agentThe latest migration's progress
Parameters: orgId (path, required)
orgs
- GET
/v1/orgsPortal / agentList the orgs the caller belongs to
- POST
/v1/orgsPortal / agentCreate an org (caller becomes owner)
Takes a JSON body.
- GET
/v1/orgs/{orgId}Portal / agentOrg detail (members only)
Parameters: orgId (path, required)
- GET
/v1/orgs/{orgId}/membersPortal / agentList org members (members only)
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/membersPortal / agentAdd/provision a member (owner/admin only)
Parameters: orgId (path, required) — Takes a JSON body.
- PATCH
/v1/orgs/{orgId}/members/{membershipId}Portal / agentChange a member's role and/or active status (owner/admin only)
Parameters: orgId (path, required) · membershipId (path, required) — Takes a JSON body.
- GET
/v1/orgs/{orgId}/invitesPortal / agentList invites, any status (owner/admin only)
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/invitesPortal / agentInvite a member by email (owner/admin only)
Parameters: orgId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/invites/{inviteId}/resendPortal / agentRotate + resend a pending invite (owner/admin only)
Parameters: orgId (path, required) · inviteId (path, required)
- DELETE
/v1/orgs/{orgId}/invites/{inviteId}Portal / agentRevoke a pending invite (owner/admin only)
Parameters: orgId (path, required) · inviteId (path, required)
- POST
/v1/invites/acceptPortal / agentAccept an org invite by token
Takes a JSON body.
roles
- GET
/v1/orgs/{orgId}/rolesPortal / agentThe org's custom roles plus the permission matrix they compose from
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/rolesPortal / agentDefine a custom role
Parameters: orgId (path, required) — Takes a JSON body.
- PATCH
/v1/orgs/{orgId}/roles/{roleId}Portal / agentEdit a custom role's name, description or permissions
Parameters: orgId (path, required) · roleId (path, required) — Takes a JSON body.
- DELETE
/v1/orgs/{orgId}/roles/{roleId}Portal / agentDelete a custom role — holders return to their built-in role, they are not locked out
Parameters: orgId (path, required) · roleId (path, required)
- PUT
/v1/orgs/{orgId}/roles/assignments/{membershipId}Portal / agentAssign a custom role to a member, or clear it back to their built-in role
Parameters: orgId (path, required) · membershipId (path, required) — Takes a JSON body.
billing
- GET
/v1/billing/plansPortal / agentSelf-serve plan ladder, priced for a billing country
Parameters: country (query, required)
- GET
/v1/billing/statusPortal / agentConfigured provider per billing leg
- GET
/v1/orgs/{orgId}/billing/entitlementsPortal / agentPlan limits, usage against them, and warn/block state
Parameters: orgId (path, required)
- GET
/v1/orgs/{orgId}/billing/subscriptionPortal / agentThe org's current subscription
Parameters: orgId (path, required)
- GET
/v1/orgs/{orgId}/billing/historyPortal / agentCharges raised against this org, newest first
Parameters: orgId (path, required) · limit (query) · offset (query)
- POST
/v1/orgs/{orgId}/billing/checkoutPortal / agentOpen a hosted checkout — routed to Razorpay (India) or PayPal (rest of world)
Parameters: orgId (path, required) — Takes a JSON body.
- PATCH
/v1/orgs/{orgId}/billing/planPortal / agentUpgrade or downgrade the current subscription
Parameters: orgId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/billing/cancelPortal / agentCancel — at period end by default, so paid time is kept
Parameters: orgId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/billing/metering/runPortal / agentMeter the closed period and push overage to the provider
Parameters: orgId (path, required)
usage
- GET
/v1/orgs/{orgId}/usagePortal / agentStorage usage for an org — totals, per-type breakdown, daily trend, heaviest sessions
Parameters: orgId (path, required) · from (query) · to (query)
audit
- GET
/v1/orgs/{orgId}/audit-logsPortal / agentBrowse an org's immutable audit trail — newest first, filterable by action/session/member/date
Parameters: orgId (path, required) · limit (query) · offset (query) · action (query) · sessionId (query) · userId (query) · from (query) · to (query)
- GET
/v1/orgs/{orgId}/audit-logs/verifyPortal / agentVerify the trail's hash chain — recomputes every row and names the first that does not hold
Parameters: orgId (path, required)
- GET
/v1/orgs/{orgId}/audit-logs/exportPortal / agentStream the org's audit trail as JSON Lines for a SIEM, cursored by chain sequence
Parameters: orgId (path, required) · afterSeq (query) · limit (query) · action (query) · sessionId (query) · from (query) · to (query)
auth
- POST
/v1/auth/loginPortal / agentLog in (sets httpOnly auth cookies)
Takes a JSON body.
- POST
/v1/auth/refreshPortal / agentRotate tokens from the refresh cookie
- POST
/v1/auth/logoutPortal / agentLog out (clears auth cookies + server session)
- GET
/v1/auth/mePortal / agentCurrent user identity
- POST
/v1/auth/password/forgotPortal / agentAsk for a password-reset link (same answer whether or not the address has an account)
Takes a JSON body.
- POST
/v1/auth/password/resetPortal / agentSet a new password from a reset link (signs the account out everywhere)
Takes a JSON body.
sessions
- GET
/v1/orgs/{orgId}/sessionsPortal / agentList org sessions (members only)
Parameters: orgId (path, required) · limit (query) · offset (query) · state (query) · from (query) · to (query) · provisionedBy (query) · sandbox (query)
- POST
/v1/orgs/{orgId}/sessionsPortal / agentProvision a session + mint the agent join token (owner/admin/interviewer; idempotent with `Idempotency-Key`)
Parameters: orgId (path, required) — Takes a JSON body.
- PUT
/v1/orgs/{orgId}/sessions/{id}/meetingPortal / agentLink the Zoom/Meet meeting this session is held in (owner/admin/interviewer) — the agent is told which app to expect on its platform
Parameters: orgId (path, required) · id (path, required) — Takes a JSON body.
- DELETE
/v1/orgs/{orgId}/sessions/{id}/meetingPortal / agentRemove the meeting link — the required apps the interviewer chose are left untouched
Parameters: orgId (path, required) · id (path, required)
- PATCH
/v1/orgs/{orgId}/sessions/{id}/configPortal / agentUpdate a session's capture policy (owner/admin/interviewer) — the agent picks it up on its next GET /config
Parameters: orgId (path, required) · id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}Portal / agentSession detail (org member)
Parameters: id (path, required)
- POST
/v1/sessionsPortal / agentRegister a session (consent-gated) — agent join token
Takes a JSON body.
- POST
/v1/sessions/{id}/eventsPortal / agentIngest integrity events (batch, idempotent) — agent join token
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/configPortal / agentSession config — agent join token
Parameters: id (path, required)
- POST
/v1/sessions/{id}/endPortal / agentEnd a session — agent join token
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/access-logPortal / agentWho has read this session's evidence (owner/admin/reviewer) — newest first
Parameters: id (path, required) · limit (query) · offset (query)
- GET
/v1/sessions/{id}/exportPortal / agentExport this session's timeline as a JSON bundle
Parameters: id (path, required)
- POST
/v1/sessions/joinPortal / agentRedeem a single-use join ticket for a scoped session token
Takes a JSON body.
- POST
/v1/sessions/{id}/joinPortal / agentMint a single-use join ticket for a session role (owner/admin/interviewer)
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/livePortal / agentA session's live snapshot — state, recent signals, permission states, latest frame. Poll with `since` when the realtime channel is unavailable.
Parameters: id (path, required) · since (query) · limit (query)
- GET
/v1/orgs/{orgId}/sessions/{id}/schedulingPortal / agentThe session's schedule and invitations
Parameters: orgId (path, required) · id (path, required)
- PUT
/v1/orgs/{orgId}/sessions/{id}/schedulePortal / agentSet or move the appointment; a live invitation is re-sent with a new link (session managers)
Parameters: orgId (path, required) · id (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/sessions/{id}/schedule/cancelPortal / agentCancel the appointment and tell the invited candidate (session managers)
Parameters: orgId (path, required) · id (path, required)
- GET
/v1/orgs/{orgId}/sessions/{id}/schedule.icsPortal / agentThe appointment as an iCalendar file (no candidate link)
Parameters: orgId (path, required) · id (path, required)
- POST
/v1/orgs/{orgId}/sessions/{id}/invitationsPortal / agentInvite the candidate by email (session managers)
Parameters: orgId (path, required) · id (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/sessions/{id}/invitations/{invitationId}/resendPortal / agentResend the invitation with a new link; earlier links stop working
Parameters: orgId (path, required) · id (path, required) · invitationId (path, required)
- POST
/v1/orgs/{orgId}/sessions/{id}/invitations/{invitationId}/revokePortal / agentRevoke the invitation's link without emailing anyone (idempotent)
Parameters: orgId (path, required) · id (path, required) · invitationId (path, required)
- GET
/v1/sessions/{id}/reportPortal / agentOne session summarized — durations, signal counts, evidence inventory, reviewer notes
Parameters: id (path, required)
- GET
/v1/sessions/{id}/report/exportPortal / agentDownload this session's report as PDF or JSON (owner/admin)
Parameters: id (path, required) · format (query)
- POST
/v1/sessions/{id}/report/revisionsPortal / agentSign off the report as a new revision — the review's owner or a queue manager; supersedes the previous revision (PRO-2107)
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/notesPortal / agentThis session's reviewer notes, oldest first
Parameters: id (path, required)
- POST
/v1/sessions/{id}/notesPortal / agentAttach a note, optionally anchored to a moment — anyone who can see the session, with their role frozen onto it; notes are never edited or deleted
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/coveragePortal / agentExpected versus observed collection per lane, the moments worth opening, and what humans wrote about them
Parameters: id (path, required) · limit (query) · offset (query)
- POST
/v1/sessions/{id}/coverage/annotationsPortal / agentExplain one moment — benign, or needing context. Attributed, audited, and never edited.
Parameters: id (path, required) — Takes a JSON body.
session-policies
- GET
/v1/orgs/{orgId}/policiesPortal / agentList the org's integrity policies (active by default)
Parameters: orgId (path, required) · limit (query) · offset (query) · state (query)
- POST
/v1/orgs/{orgId}/policiesPortal / agentSave a new integrity policy as version 1
Parameters: orgId (path, required) — Takes a JSON body.
- GET
/v1/orgs/{orgId}/policies/{policyId}Portal / agentOne policy with its version history (newest first)
Parameters: orgId (path, required) · policyId (path, required)
- PATCH
/v1/orgs/{orgId}/policies/{policyId}Portal / agentRename or re-describe a policy (content changes are new versions)
Parameters: orgId (path, required) · policyId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/policies/{policyId}/versionsPortal / agentEdit a policy by writing its next version — existing sessions keep theirs
Parameters: orgId (path, required) · policyId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/policies/{policyId}/duplicatePortal / agentCopy a policy's latest version into a new policy
Parameters: orgId (path, required) · policyId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/policies/{policyId}/archivePortal / agentStop offering a policy for new sessions — every version stays readable
Parameters: orgId (path, required) · policyId (path, required) — Takes a JSON body.
pairings
- POST
/v1/pairings/{joinCode}/claimPortal / agentPair a mobile companion to a session by join code
Parameters: joinCode (path, required) — Takes a JSON body.
- POST
/v1/pairings/{sessionId}/consentPortal / agentRecord companion side-view consent — companion token
Parameters: sessionId (path, required) — Takes a JSON body.
- POST
/v1/pairings/{sessionId}/presencePortal / agentReport companion presence (batch, idempotent) — companion token
Parameters: sessionId (path, required) — Takes a JSON body.
- POST
/v1/pairings/{sessionId}/unpairPortal / agentUnpair the companion — companion token
Parameters: sessionId (path, required)
screenshots
- GET
/v1/sessions/{id}/screenshotsPortal / agentList a session's screenshots (org members)
Parameters: id (path, required) · limit (query) · offset (query)
- POST
/v1/sessions/{id}/screenshotsPortal / agentUpload a screenshot (consent-gated, policy-checked) — agent join token
Parameters: id (path, required) — Takes a JSON body.
audio
- GET
/v1/sessions/{id}/audio-chunksPortal / agentList a session's audio chunks (org members)
Parameters: id (path, required) · limit (query) · offset (query)
- POST
/v1/sessions/{id}/audio-chunksPortal / agentUpload an audio chunk (consent-gated, policy-checked) — agent join token
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/transcriptPortal / agentRead a session's assembled transcript — ordered, gap-aware, pollable (org members)
Parameters: id (path, required) · since (query) · limit (query) · offset (query)
- POST
/v1/sessions/{id}/transcriptPortal / agentUpsert transcript segments (consent-gated, policy-checked) — agent join token
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/timelinePortal / agentRead a session's unified timeline — speech turns + screenshots + events (org members)
Parameters: id (path, required) · kind (query) · limit (query) · offset (query)
system-audio
- GET
/v1/sessions/{id}/system-audio-chunksPortal / agentList a session's system-audio chunks (org members)
Parameters: id (path, required) · limit (query) · offset (query)
- POST
/v1/sessions/{id}/system-audio-chunksPortal / agentOpen a resumable system-audio chunk upload (consent-gated, policy-checked) — agent join token
Parameters: id (path, required) — Takes a JSON body.
camera
- GET
/v1/sessions/{id}/camera/framesPortal / agentList a session's webcam photos (org members)
Parameters: id (path, required) · limit (query) · offset (query)
- POST
/v1/sessions/{id}/camera/framesPortal / agentUpload a webcam photo (consent-gated, policy-checked) — agent join token
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/camera/clipsPortal / agentList a session's webcam clips (org members)
Parameters: id (path, required) · limit (query) · offset (query)
- POST
/v1/sessions/{id}/camera/clipsPortal / agentUpload a webcam clip (consent-gated, policy-checked) — agent join token
Parameters: id (path, required) — Takes a JSON body.
evidence
- GET
/v1/sessions/{id}/evidencePortal / agentList a session's evidence (org members)
Parameters: id (path, required) · limit (query) · offset (query) · evidence_type (query)
- POST
/v1/sessions/{id}/evidencePortal / agentBegin (or dedupe) a chunked evidence upload — agent join token
Parameters: id (path, required) — Takes a JSON body.
- POST
/v1/uploads/{uploadId}/partsPortal / agentUpload one chunk (resume-safe) — agent join token
Parameters: uploadId (path, required) — Takes a JSON body.
- GET
/v1/uploads/{uploadId}Portal / agentResume/status read — which chunks survived a crash
Parameters: uploadId (path, required)
- POST
/v1/uploads/{uploadId}/completePortal / agentFinalize: reassemble, verify sha256, encrypt, store
Parameters: uploadId (path, required)
- POST
/v1/uploads/{uploadId}/abortPortal / agentDiscard an in-flight upload and its temp chunks
Parameters: uploadId (path, required)
- GET
/v1/evidence/{id}Portal / agentRead one evidence object's metadata (org members, audited)
Parameters: id (path, required)
- GET
/v1/evidence/{id}/contentPortal / agentDownload one evidence object's decrypted bytes (org members, audited)
Parameters: id (path, required)
session-compositions
- GET
/v1/sessions/{id}/compositionsPortal / agentList post-session picture-in-picture compositions (org reviewers)
Parameters: id (path, required)
- POST
/v1/sessions/{id}/compositions/{compositionId}/renderPortal / agentRequest a PIP composition render (org reviewers with evidence export)
Parameters: id (path, required) · compositionId (path, required)
- GET
/v1/sessions/{id}/compositions/{compositionId}/contentPortal / agentDownload one ready PIP composition (explicit evidence export)
Parameters: compositionId (path, required)
session-reviews
- GET
/v1/orgs/{orgId}/reviewsPortal / agentThe org's review queue — open work, oldest backlog first
Parameters: orgId (path, required) · state (query) · assignee (query) · readiness (query) · sessionId (query) · sort (query) · limit (query) · offset (query)
- GET
/v1/orgs/{orgId}/reviews/assigneesPortal / agentMembers this queue may be assigned to, with their open workload
Parameters: orgId (path, required)
- GET
/v1/orgs/{orgId}/reviews/{reviewId}Portal / agentOne review work item
Parameters: orgId (path, required) · reviewId (path, required)
- POST
/v1/orgs/{orgId}/reviews/{reviewId}/assignmentPortal / agentAssign, claim or hand back a review (409 on a lost race)
Parameters: orgId (path, required) · reviewId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/reviews/{reviewId}/statePortal / agentMove a review's workflow state — always an explicit human action, never inferred
Parameters: orgId (path, required) · reviewId (path, required) — Takes a JSON body.
companion
- GET
/v1/sessions/{id}/companionPortal / agentSide-view status for this session — agent or companion session token
Parameters: id (path, required)
- POST
/v1/sessions/{id}/companion/placementPortal / agentConfirm the side-view placement (steps + confirmation photo) — companion token
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/sessions/{id}/companion/previewPortal / agentThe newest side-view preview still (org members)
Parameters: id (path, required)
- POST
/v1/sessions/{id}/companion/previewPortal / agentPush a live side-view preview still (consent-gated, never stored) — companion token
Parameters: id (path, required) — Takes a JSON body.
rooms
- POST
/v1/rooms/{sessionId}/consentPortal / agentRecord the browser room's webcam-still consent — room token. Nothing is accepted before it.
Parameters: sessionId (path, required) — Takes a JSON body.
- POST
/v1/rooms/{sessionId}/releasePortal / agentRelease the room device — room token. Idempotent.
Parameters: sessionId (path, required)
retention
- GET
/v1/orgs/{orgId}/retentionPortal / agentThe org's retention policy, the window actually in force, and the plan ceiling (owner/admin)
Parameters: orgId (path, required)
- PUT
/v1/orgs/{orgId}/retentionPortal / agentSet the org's default retention window. A window longer than the plan allows is stored and reported as capped, never silently rewritten.
Parameters: orgId (path, required) — Takes a JSON body.
- PUT
/v1/orgs/{orgId}/retention/legal-holdPortal / agentPlace or release an org-wide legal hold — blocks every deletion while on
Parameters: orgId (path, required) — Takes a JSON body.
- PUT
/v1/orgs/{orgId}/retention/sessions/{sessionId}/legal-holdPortal / agentPlace or release a legal hold on one session's evidence
Parameters: orgId (path, required) · sessionId (path, required) — Takes a JSON body.
- GET
/v1/orgs/{orgId}/retention/previewPortal / agentWhat the next sweep would delete inside the given horizon, held sessions included
Parameters: orgId (path, required) · days (query) · limit (query) · offset (query)
- POST
/v1/orgs/{orgId}/retention/runPortal / agentRun (or resume) the deletion sweep, bounded per call. Explicitly triggered — never on a timer.
Parameters: orgId (path, required) — Takes a JSON body.
- GET
/v1/orgs/{orgId}/retention/sweepPortal / agentThe latest sweep's outcome
Parameters: orgId (path, required)
invitations
- POST
/v1/invitations/inspectPortal / agentWhat an invitation link is for: the appointment
Takes a JSON body.
- POST
/v1/invitations/calendarPortal / agentThe appointment as an iCalendar file
Takes a JSON body.
- POST
/v1/invitations/ticketPortal / agentA single-use join ticket for the desktop app — the only credential a link yields
Takes a JSON body.
- POST
/v1/invitations/readinessPortal / agentHow far the candidate's preparation has got — server-held facts only (PRO-2104)
Takes a JSON body.
- POST
/v1/invitations/declinePortal / agentDecline the invitation — the link stops working
Takes a JSON body.
- POST
/v1/invitations/contactPortal / agentWrite to the hiring team (accommodation, question, new time) — emailed, not stored
Takes a JSON body.
api-keys
- GET
/v1/orgs/{orgId}/api-keysPortal / agentList the org's API keys (owner/admin) — never the secrets
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/api-keysPortal / agentMint an API key — the plaintext token is returned once and never again
Parameters: orgId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/api-keys/{keyId}/rotatePortal / agentReplace a key's secret in place — the previous token stops working immediately
Parameters: orgId (path, required) · keyId (path, required)
- DELETE
/v1/orgs/{orgId}/api-keys/{keyId}Portal / agentRevoke a key (idempotent; the row is kept as a tombstone)
Parameters: orgId (path, required) · keyId (path, required)
public-api
- GET
/v1/api/orgs/selfAPI keyThe org this API key belongs to
Requires:org:read
- GET
/v1/api/meAPI keyIntrospect the presented API key — its org, label, environment and granted scopes
Requires:org:read
- GET
/v1/api/sessionsAPI keyList this org's sessions (newest first)
Requires:sessions:read
Parameters: limit (query) · offset (query) · state (query) · from (query) · to (query) · provisionedBy (query) · sandbox (query)
- POST
/v1/api/sessionsAPI keySchedule a session and mint its agent join token (idempotent with `Idempotency-Key`)
Requires:sessions:write
Takes a JSON body.
- GET
/v1/api/sessions/{id}API keyOne session's state, config and consent summary
Requires:sessions:read
Parameters: id (path, required)
- PATCH
/v1/api/sessions/{id}API keyUpdate a session's capture / audio / camera / side-view policy (partial; the agent picks it up on its next config read)
Requires:sessions:write
Parameters: id (path, required) — Takes a JSON body.
- POST
/v1/api/sessions/{id}/endAPI keyEnd a session (idempotent — a re-end is the same answer)
Requires:sessions:write
Parameters: id (path, required) — Takes a JSON body.
- POST
/v1/api/sessions/{id}/eraseAPI keyErase a session's captured evidence for a data-subject request — idempotent; 409 while live or under legal hold
Requires:sessions:write
Parameters: id (path, required)
- POST
/v1/api/sessions/{id}/join-linksAPI keyMint a single-use join link for a candidate or companion device
Requires:sessions:write
Parameters: id (path, required) — Takes a JSON body.
- POST
/v1/api/sessions/{id}/room-devicesAPI keyMint the browser interview room's camera-only device credential
Requires:sessions:write
Parameters: id (path, required) — Takes a JSON body.
- GET
/v1/api/sessions/{id}/eventsAPI keyA session's integrity events plus whole-session counts per kind — observations, never a verdict
Requires:sessions:read
Parameters: id (path, required) · limit (query) · offset (query)
- GET
/v1/api/sessions/{id}/transcriptAPI keyThe session's assembled transcript — ordered, gap-aware, pollable
Requires:sessions:read
Parameters: id (path, required) · since (query) · limit (query) · offset (query)
- GET
/v1/api/sessions/{id}/evidenceAPI keyThe session's evidence objects. Fetch bytes via `POST /v1/api/evidence/:id/download-url`.
Requires:evidence:read
Parameters: id (path, required) · limit (query) · offset (query) · evidence_type (query)
- GET
/v1/api/sessions/{id}/compositionsAPI keyPost-session picture-in-picture composition status and integrity metadata.
Requires:evidence:read
Parameters: id (path, required)
- GET
/v1/api/sessions/{id}/system-audio-chunksAPI keyThe session's system-audio chunks in playback order, with duration and codec. A separate lane from the microphone: this is the machine's output audio, consented under `system_audio`, and it is never mixed into the transcript or the audio listing.
Requires:evidence:read
Parameters: id (path, required) · limit (query) · offset (query)
- GET
/v1/api/sessions/{id}/review-statusAPI keyWhere the session's human review stands — the approved status and revision, and what evidence remains. No notes, no observations, no verdict.
Requires:sessions:read
Parameters: id (path, required)
- GET
/v1/api/sessions/{id}/reportAPI keyThe session's report — counts, inventory and reviewer notes. Assistive: it states what was observed, never a conclusion.
Requires:reports:read
Parameters: id (path, required)
- GET
/v1/api/evidence/{id}API keyOne evidence object's metadata (audited)
Requires:evidence:read
Parameters: id (path, required)
- POST
/v1/api/evidence/{id}/download-urlAPI keyMint a short-lived, self-authenticating download URL for this evidence object
Requires:evidence:read
Parameters: id (path, required)
- GET
/v1/api/evidence/{id}/contentPortal / agentDownload an evidence object's bytes using a download link token
Parameters: id (path, required) · token (query, required)
- GET
/v1/api/compositions/{id}API keyOne post-session PIP composition's status and integrity metadata (audited)
Requires:evidence:read
Parameters: id (path, required)
- POST
/v1/api/compositions/{id}/renderAPI keyRequest a render of a post-session PIP composition (rendered on demand, kept for a fixed lifetime)
Requires:evidence:read
Parameters: id (path, required)
- POST
/v1/api/compositions/{id}/download-urlAPI keyMint a short-lived, self-authenticating download URL for a ready PIP composition
Requires:evidence:read
Parameters: id (path, required)
- GET
/v1/api/compositions/{id}/contentPortal / agentDownload a PIP composition's bytes using a download link token
Parameters: id (path, required) · token (query, required)
- GET
/v1/api/webhooksAPI keyList this key's environment's webhook endpoints
Requires:webhooks:read
- POST
/v1/api/webhooksAPI keyRegister an endpoint. The signing secret is returned once and never again.
Requires:webhooks:write
Takes a JSON body.
- GET
/v1/api/webhooks/{id}API keyOne endpoint's configuration and delivery health
Requires:webhooks:read
Parameters: id (path, required)
- PATCH
/v1/api/webhooks/{id}API keyUpdate the URL, the subscribed types, or the status (re-enabling clears the failure count)
Requires:webhooks:write
Parameters: id (path, required) — Takes a JSON body.
- DELETE
/v1/api/webhooks/{id}API keyDelete an endpoint. Queued deliveries stop.
Requires:webhooks:write
Parameters: id (path, required)
- POST
/v1/api/webhooks/{id}/rotate-secretAPI keyReplace the signing secret — the previous one stops signing immediately
Requires:webhooks:write
Parameters: id (path, required)
- POST
/v1/api/webhooks/{id}/testAPI keyPublish a `webhook.test` event — a real, signed delivery, so a receiver can be verified before a real session exists
Requires:webhooks:write
Parameters: id (path, required)
- GET
/v1/api/webhooks/{id}/deliveriesAPI keyThis endpoint's delivery log — every attempt, its outcome, and when the next one is due
Requires:webhooks:read
Parameters: id (path, required) · limit (query) · offset (query) · status (query) · eventType (query)
- POST
/v1/api/webhooks/{id}/deliveries/{deliveryId}/replayAPI keyRe-send a finished delivery as a new one — the original's history is kept
Requires:webhooks:write
Parameters: id (path, required) · deliveryId (path, required)
- GET
/v1/api/eventsAPI keyThe org's published events, newest first — the catalog as a bounded, filterable list
Requires:events:read
Parameters: types (query) · sessionId (query) · limit (query) · offset (query)
- GET
/v1/api/events/streamAPI keyServer-Sent Events over the same catalog. Resume with `Last-Event-ID`; dedupe on the event id.
Requires:events:read
Parameters: types (query) · sessionId (query) · lastEventId (query)
webhooks
- GET
/v1/orgs/{orgId}/webhooksPortal / agentList the org's webhook endpoints (owner/admin) — never the secrets
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/webhooksPortal / agentRegister an endpoint — the signing secret is shown once
Parameters: orgId (path, required) — Takes a JSON body.
- PATCH
/v1/orgs/{orgId}/webhooks/{endpointId}Portal / agentUpdate an endpoint's URL, subscriptions or status
Parameters: orgId (path, required) · endpointId (path, required) — Takes a JSON body.
- DELETE
/v1/orgs/{orgId}/webhooks/{endpointId}Portal / agentDelete an endpoint (queued deliveries stop)
Parameters: orgId (path, required) · endpointId (path, required)
- POST
/v1/orgs/{orgId}/webhooks/{endpointId}/rotate-secretPortal / agentReplace the signing secret — the previous one stops signing immediately
Parameters: orgId (path, required) · endpointId (path, required)
- POST
/v1/orgs/{orgId}/webhooks/{endpointId}/testPortal / agentSend a real, signed `webhook.test` delivery to this endpoint
Parameters: orgId (path, required) · endpointId (path, required)
- GET
/v1/orgs/{orgId}/webhooks/{endpointId}/deliveriesPortal / agentThis endpoint's delivery log, newest first
Parameters: orgId (path, required) · endpointId (path, required) · limit (query) · offset (query) · status (query) · eventType (query)
- POST
/v1/orgs/{orgId}/webhooks/{endpointId}/deliveries/{deliveryId}/replayPortal / agentRe-send a finished delivery — the original's history is kept
Parameters: orgId (path, required) · endpointId (path, required) · deliveryId (path, required)
compliance
- GET
/v1/orgs/{orgId}/compliance/data-processingPortal / agentWhat this deployment collects about a candidate, who can read it, where it goes and for how long — generated from the protocol registry and the org's live configuration
Parameters: orgId (path, required)
sso
- POST
/v1/auth/sso/discoverPortal / agentResolve the SSO entry point for an email address
Takes a JSON body.
- GET
/v1/auth/sso/{orgSlug}/loginPortal / agentStart an SP-initiated SSO login
Parameters: orgSlug (path, required)
- GET
/v1/auth/sso/{orgSlug}/metadataPortal / agentSAML SP metadata for an organization
Parameters: orgSlug (path, required)
- POST
/v1/auth/sso/ldapPortal / agentSign in against an organization's LDAP directory
Takes a JSON body.
- GET
/v1/auth/sso/{orgSlug}/logout-urlPortal / agentThe IdP's single-logout URL, if one is configured
Parameters: orgSlug (path, required)
- GET
/v1/orgs/{orgId}/ssoPortal / agentThe org's SSO configuration (owner only)
Parameters: orgId (path, required)
- PUT
/v1/orgs/{orgId}/ssoPortal / agentCreate or replace the org's SSO connection
Parameters: orgId (path, required) — Takes a JSON body.
- PUT
/v1/orgs/{orgId}/sso/enforcementPortal / agentRequire single sign-on, or make it optional again
Parameters: orgId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/sso/domainsPortal / agentClaim an email domain (inert until verified)
Parameters: orgId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/sso/domains/{domain}/verifyPortal / agentCheck the org's proof of control over a claimed domain
Parameters: orgId (path, required) · domain (path, required)
- DELETE
/v1/orgs/{orgId}/sso/domains/{domain}Portal / agentDrop a claimed domain
Parameters: orgId (path, required) · domain (path, required)
- POST
/v1/orgs/{orgId}/sso/testPortal / agentProbe the configured IdP or directory
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/sso/scim/tokenPortal / agentIssue or rotate the SCIM provisioning token
Parameters: orgId (path, required)
- DELETE
/v1/orgs/{orgId}/sso/scim/tokenPortal / agentTurn SCIM off and destroy the token
Parameters: orgId (path, required)
branding
- GET
/v1/orgs/{orgId}/branding/logoPortal / agentThe org's logo (public — rendered before sign-in)
Parameters: orgId (path, required)
- PUT
/v1/orgs/{orgId}/branding/logoPortal / agentUpload or replace the org's logo (base64, raster only)
Parameters: orgId (path, required) — Takes a JSON body.
- DELETE
/v1/orgs/{orgId}/branding/logoPortal / agentRemove the org's logo (idempotent)
Parameters: orgId (path, required)
- GET
/v1/orgs/{orgId}/branding/publicPortal / agentThe org's brand as a candidate sees it (public). An unbranded org answers with the product's.
Parameters: orgId (path, required)
- GET
/v1/orgs/{orgId}/brandingPortal / agentThe org's branding config and what it resolves to (members)
Parameters: orgId (path, required)
- PUT
/v1/orgs/{orgId}/brandingPortal / agentReplace the branding config. A palette below the contrast minimum is refused with the failing pairs.
Parameters: orgId (path, required) — Takes a JSON body.
integrations
- GET
/v1/orgs/{orgId}/integrations/ats/capabilitiesPortal / agentWhich ATS providers this deployment can connect, and whether it is configured to
- GET
/v1/orgs/{orgId}/integrations/atsPortal / agentThe org's ATS integrations — never their credentials or inbound secrets
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/integrations/atsPortal / agentConnect an ATS — the inbound webhook secret is shown once
Parameters: orgId (path, required) — Takes a JSON body.
- PATCH
/v1/orgs/{orgId}/integrations/ats/{configId}Portal / agentUpdate credentials, settings, trigger stages, mapping or status
Parameters: orgId (path, required) · configId (path, required) — Takes a JSON body.
- DELETE
/v1/orgs/{orgId}/integrations/ats/{configId}Portal / agentDisconnect (the sync log is kept — it records real sessions' provenance)
Parameters: orgId (path, required) · configId (path, required)
- POST
/v1/orgs/{orgId}/integrations/ats/{configId}/rotate-secretPortal / agentRe-mint the inbound webhook secret — the previous one stops verifying immediately
Parameters: orgId (path, required) · configId (path, required)
- POST
/v1/orgs/{orgId}/integrations/ats/{configId}/testPortal / agentProbe the connection with a read — changes nothing in the ATS
Parameters: orgId (path, required) · configId (path, required)
- GET
/v1/orgs/{orgId}/integrations/ats/{configId}/syncPortal / agentThe integration's sync log, newest first
Parameters: orgId (path, required) · configId (path, required) · status (query) · direction (query) · limit (query) · offset (query)
- POST
/v1/orgs/{orgId}/integrations/ats/{configId}/sync/{syncId}/replayPortal / agentRe-run a failed outbound push — the original's history is kept
Parameters: orgId (path, required) · configId (path, required) · syncId (path, required)
- GET
/v1/orgs/{orgId}/integrations/comms/capabilitiesPortal / agentWhich chat platforms this deployment can install, and whether it is configured to
- GET
/v1/orgs/{orgId}/integrations/commsPortal / agentThe org's chat apps — never their workspace tokens
Parameters: orgId (path, required)
- POST
/v1/orgs/{orgId}/integrations/comms/installPortal / agentBegin an install — returns where to send the admin's browser to approve it
Parameters: orgId (path, required) — Takes a JSON body.
- GET
/v1/orgs/{orgId}/integrations/comms/{integrationId}/channelsPortal / agentThe channels this app can post into — the picker's options
Parameters: orgId (path, required) · integrationId (path, required)
- PATCH
/v1/orgs/{orgId}/integrations/comms/{integrationId}Portal / agentChoose the channel, which events are announced, and the review threshold
Parameters: orgId (path, required) · integrationId (path, required) — Takes a JSON body.
- DELETE
/v1/orgs/{orgId}/integrations/comms/{integrationId}Portal / agentDisconnect — revokes at the provider where that is possible, and says so when it is not
Parameters: orgId (path, required) · integrationId (path, required)
- GET
/v1/orgs/{orgId}/integrations/comms/{integrationId}/deliveriesPortal / agentWhat was announced, and what failed to be — newest first
Parameters: orgId (path, required) · integrationId (path, required) · status (query) · limit (query) · offset (query)
- POST
/v1/orgs/{orgId}/integrations/comms/{integrationId}/deliveries/{deliveryId}/replayPortal / agentRe-send a finished notification — the original's history is kept
Parameters: orgId (path, required) · integrationId (path, required) · deliveryId (path, required)
updates
- GET
/v1/updates/manifestPortal / agentThe signed update manifest for one app and channel — latest build, the operator's minimum supported version, and the recent builds that remain installable
Parameters: app (query, required) · channel (query)
security-policy
- GET
/v1/security-policyPortal / agentThe signed pin kill-switch policy — whether certificate pinning should stay enforced
access-requests
- POST
/v1/access-requests/owner-invite/inspectPortal / agentDescribe an owner invitation link for its holder
Takes a JSON body.
- POST
/v1/access-requests/owner-invite/acceptPortal / agentAccept an owner invitation: create the organization and its owner (signs a new account in)
Takes a JSON body.
- POST
/v1/access-requests/owner-invite/renewPortal / agentSend a fresh invitation for an expired one
Takes a JSON body.
- GET
/v1/access-requests/insightsPortal / agentAccess-desk activation funnel (access-desk operators only)
Parameters: from (query) · to (query)
- GET
/v1/access-requests/availabilityPortal / agentWhether the public request form is open in this deployment
- GET
/v1/access-requestsPortal / agentThe review queue (access-desk operators only)
Parameters: status (query) · limit (query) · cursor (query)
- POST
/v1/access-requestsPortal / agentRequest access for a new organization (public, rate-limited)
Takes a JSON body.
- POST
/v1/access-requests/{id}/approvePortal / agentApprove a pending request and email its first-owner invitation
Parameters: id (path, required) — Takes a JSON body.
- POST
/v1/access-requests/{id}/declinePortal / agentDecline a pending request
Parameters: id (path, required) — Takes a JSON body.
- POST
/v1/access-requests/{id}/resend-invitePortal / agentRotate and resend an approved request's owner invitation
Parameters: id (path, required)
insights
- GET
/v1/orgs/{orgId}/insightsPortal / agentActivation milestones, the session funnel, invitation outcomes and review turnaround/backlog
Parameters: orgId (path, required) · from (query) · to (query)
candidate-requests
- POST
/v1/candidate-requests/linksPortal / agentEmail a request link to the address a candidate was invited with — answers the same either way
Takes a JSON body.
- POST
/v1/candidate-requests/links/invitationPortal / agentExchange a live invitation handle for a request link — no second email needed
Takes a JSON body.
- POST
/v1/candidate-requests/viewPortal / agentThe candidate's requests for the link's session
Takes a JSON body.
- POST
/v1/candidate-requests/submitPortal / agentSend a context statement or a data request — an open request of the same kind is returned instead of duplicated
Takes a JSON body.
- POST
/v1/candidate-requests/exportPortal / agentDownload an approved access copy (JSON) while it has not expired
Takes a JSON body.
- GET
/v1/orgs/{orgId}/candidate-requestsPortal / agentThe org's candidate requests, newest first (open by default)
Parameters: orgId (path, required) · status (query) · kind (query) · limit (query) · offset (query)
- GET
/v1/orgs/{orgId}/candidate-requests/{requestId}Portal / agentCandidateRequestQueueController_get
Parameters: orgId (path, required) · requestId (path, required)
- POST
/v1/orgs/{orgId}/candidate-requests/{requestId}/acknowledgePortal / agentCandidateRequestQueueController_acknowledge
Parameters: orgId (path, required) · requestId (path, required)
- POST
/v1/orgs/{orgId}/candidate-requests/{requestId}/respondPortal / agentWrite to the candidate; they are emailed a fresh link to read it
Parameters: orgId (path, required) · requestId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/candidate-requests/{requestId}/approvePortal / agentApprove an access copy or an erasure — erasure goes through the retention erasure service
Parameters: orgId (path, required) · requestId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/candidate-requests/{requestId}/declinePortal / agentCandidateRequestQueueController_decline
Parameters: orgId (path, required) · requestId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/candidate-requests/{requestId}/completePortal / agentMark a context statement as read
Parameters: orgId (path, required) · requestId (path, required) — Takes a JSON body.
- POST
/v1/orgs/{orgId}/candidate-requests/{requestId}/reopen-reviewPortal / agentReopen the session's signed-off review for this statement (needs session.review.assign)
Parameters: orgId (path, required) · requestId (path, required) — Takes a JSON body.
- GET
/v1/orgs/{orgId}/session-candidate-context/{sessionId}Portal / agentThe candidate's context statements on one session (evidence.view)
Parameters: orgId (path, required) · sessionId (path, required)