@invigile/sdk
v0.4.21
Published
Invigile browser proctoring SDK — embed integrity monitoring into your exam or interview page.
Downloads
917
Maintainers
Readme
@invigile/sdk
Browser proctoring SDK for Invigile — embed integrity monitoring into your own exam or interview page.
Invigile runs in ghost mode: it flags tab switches, clipboard use, multi-face / gaze events, identity mismatches, and optional OS signals without showing warnings to the candidate. Results land in the Invigile Evidence Room.
Requirements
- A modern browser (
window/ DOM). This package is browser-only — do not import it in Node or edge runtimes. - An Invigile account and API key (
sk_invigile_…) - An interview whose
external_idmatches your ATS exam ID (or useinterviewId)
Install
npm install @invigile/sdk
# or
yarn add @invigile/sdk
# or
pnpm add @invigile/sdkSetup (once)
- In the Invigile dashboard, create an interview and set
external_idto your ATS assessment ID. - Create an API key under Dashboard → Integrations.
- Point
apiBaseUrlat your Invigile app host (production:https://app.invigile.com). - Allow your ATS origin in Invigile’s
INVIGILE_CORS_ORIGINS(comma-separated).
# Your ATS / exam app
INVIGILE_API_KEY=sk_invigile_...
INVIGILE_API_BASE_URL=https://app.invigile.comPrefer keeping the API key server-side when you can. If the browser must call
initInvigilewithapiKey, use a dedicated key and rotate it regularly.
Quick start
import { initInvigile, stopInvigile } from "@invigile/sdk";
await initInvigile({
apiKey: process.env.INVIGILE_API_KEY!,
apiBaseUrl: "https://app.invigile.com",
externalId: "your-exam-id", // must match interview.external_id
candidate: {
email: "[email protected]",
externalId: "ats-user-123", // optional ATS user id
},
});
// When the session ends (or on React unmount)
await stopInvigile();initInvigile opens a session, loads the interview policy, and starts listeners. Call stopInvigile() when the assessment ends.
React / Next.js (client component)
"use client";
import { useEffect } from "react";
import { initInvigile, stopInvigile } from "@invigile/sdk";
export function ExamProctoring({
examExternalId,
candidateEmail,
}: {
examExternalId: string;
candidateEmail: string;
}) {
useEffect(() => {
let active = true;
void initInvigile({
apiKey: process.env.NEXT_PUBLIC_INVIGILE_API_KEY!,
apiBaseUrl: process.env.NEXT_PUBLIC_INVIGILE_API_BASE_URL!,
externalId: examExternalId,
candidate: { email: candidateEmail },
}).catch((err) => {
if (active) console.error("Invigile could not start:", err);
});
return () => {
active = false;
void stopInvigile();
};
}, [examExternalId, candidateEmail]);
return null;
}Recommended flow: Pre-gate → monitor
Use pre-gate on the welcome / intro screen (permissions, identity, OS Agent when required). Use init only on the assessment screen (no modal).
import { preGateInvigile, initInvigile, stopInvigile } from "@invigile/sdk";
const candidate = {
email: "[email protected]",
externalId: "ats-user-123",
};
// 1) Welcome screen
const gate = await preGateInvigile({
apiKey: process.env.INVIGILE_API_KEY!,
apiBaseUrl: "https://app.invigile.com",
externalId: "your-exam-id",
candidate,
});
// 2) Assessment screen — reuse camera / identity / agent link from the gate
await initInvigile({
apiKey: process.env.INVIGILE_API_KEY!,
apiBaseUrl: "https://app.invigile.com",
externalId: "your-exam-id",
candidate,
camera: gate.cameraStream ?? undefined,
diditSessionId: gate.diditSessionId ?? undefined,
agentLinkToken: gate.agentLinkToken ?? undefined,
});
await stopInvigile();When identity, vision, and OS signals are all off in the interview policy, preGateInvigile returns immediately without a modal.
Configuration
Pass either externalId or interviewId — not both.
| Option | Type | Required | Description |
| ------ | ---- | -------- | ----------- |
| apiKey | string | yes* | Invigile API key (sk_invigile_…) |
| apiBaseUrl | string | yes | Invigile app base URL |
| externalId | string | one of | Your ATS exam / assessment id |
| interviewId | string | one of | Invigile interview UUID |
| candidate.email | string | yes | Candidate email |
| candidate.externalId | string | no | Your ATS user id |
| camera | MediaStream \| HTMLVideoElement \| false | no | Reuse an existing camera, or false to skip |
| diditSessionId | string | no | From preGateInvigile (identity continuity) |
| agentLinkToken | string | no | From preGateInvigile (OS Agent signals) |
| resume | boolean | no | Reopen a finished session (default true) |
| debug | boolean | no | Verbose console logs (or localStorage.invigile_debug=1) |
| sessionToken | string | yes* | Advanced: skip session open and attach with a server-issued token |
*Use either the apiKey + candidate flow or a sessionToken from your backend.
Camera (vision)
When multi_face, gaze_escape, or identity_verify are enabled on the interview, the SDK requests the camera itself. Raw video never leaves the browser — only signal metadata (and optional blurred evidence frames when opted in) is sent.
// Default: SDK calls getUserMedia when vision is enabled
await initInvigile({ apiKey, apiBaseUrl, externalId, candidate });
// ATS already has a stream — no second permission prompt
await initInvigile({ ..., camera: existingMediaStream });
// Disable camera entirely
await initInvigile({ ..., camera: false });
import { setCameraMonitoring } from "@invigile/sdk";
setCameraMonitoring(false); // pause inference without stopping tracksSubpath exports
| Import | Use case |
| ------ | -------- |
| @invigile/sdk | initInvigile, stopInvigile, preGateInvigile, camera helpers |
| @invigile/sdk/pre-gate | Welcome modal only |
| @invigile/sdk/agent | OS Agent pairing / status helpers |
| @invigile/sdk/agent-link | Agent link create / attach / revoke |
| @invigile/sdk/vision | Vision tuning / lab |
Debug
await initInvigile({ ..., debug: true });
// or in DevTools:
localStorage.setItem("invigile_debug", "1");Documentation
- Product: invigile.com
- Full integration guide (API, webhooks, troubleshooting): sign in → Dashboard → Integrations → Docs
License
UNLICENSED — proprietary software. See your Invigile agreement for usage terms.
