Proctoring SDK vs API vs LMS Plugin: Which Do You Need?

Use the LMS plugin if your exams already run in Moodle: it is a drop-in and you write no code. Use the browser SDK plus the REST API if you own a custom web application: your backend mints a session with one API call, and a small browser loader mounts the proctoring enclave. There is no camera-capture-over-API-only option. Capturing a candidate always needs the in-browser SDK; the API mints the session and returns the report. This guide is the hub for the ProctorLink SDK series: it maps each route to the situation it fits, with working code from the API reference.

Schedule a Demo

What are the three integration routes?

ProctorLink exposes three integration surfaces, and the right one depends almost entirely on where your exams already run:

  • LMS plugin. A drop-in for Moodle. An admin installs it and turns on proctoring per quiz. No developer wires up session minting or capture.
  • Browser SDK plus REST API. For software you own the code for. Your backend calls the API to mint a session, and a thin browser loader (around 3 KB gzipped) mounts the proctoring enclave and captures keyframes.
  • LTI 1.3. A standards-based launch for a non-Moodle LMS that already speaks LTI. You connect proctoring through configuration rather than application code.

The common confusion is treating “SDK” and “API” as competing choices. They are not. On the custom-application route you use both: the API is the server-to-server half, and the SDK is the in-browser half. If you are new to the field itself, start with What is online proctoring? and What is AI proctoring?, then come back here to choose an integration.

How does the SDK plus API route actually fit together?

Three moving parts, in order. Your backend mints a session, the browser runs it, and your backend reads the report. Here is the whole integration, using only calls from the documented ProctorLink API surface.

1. Mint a session on your backend
// Your backend. Your API key never enters the browser.
POST /v1/sessions
access-token: <YOUR_ACCESS_TOKEN>
secret-token: <YOUR_SECRET_TOKEN>
content-type: application/json

{
  "external_user_id": "candidate-123",
  "exam_id": "math-101-final",
  "attempt_id": "attempt-789",
  "allowed_origins": ["https://exams.yourcompany.com"]
}

// Response
{
  "session_id": "6a7b18df70e4f8ecf2597b6f",
  "session_jwt": "eyJhbGciOi...",
  "expires_at": 1786443201
}

The session_jwt is a short-lived token scoped to one attempt. It is the only thing you pass to the browser. Your access-token and secret-token stay on your server.

2. Start proctoring in the candidate browser
npm install @proctorlink/sdk@^0.1.4
import { ProctorLink } from '@proctorlink/sdk';

// jwt and sessionId come from the POST /v1/sessions response above
const session = ProctorLink.createSession({
  jwt: sessionJwt,   // session_jwt
  sessionId,         // session_id
});

session.on('permission', ({ camera }) => {
  if (camera === 'denied') { /* block or warn, your policy */ }
});
session.onEvent((event) => console.log(event.type, event));

await session.start();

// when the attempt finishes:
session.stop();
session.destroy();

In the default flow, recording begins as soon as the camera is granted and the first captured frame becomes the identity reference. That is the entire browser integration.

3. Read the report from your backend
GET /v1/sessions/6a7b18df70e4f8ecf2597b6f
access-token: <YOUR_ACCESS_TOKEN>
secret-token: <YOUR_SECRET_TOKEN>

// Fetch once status is "validated" (or integrity.analysis_complete is true).
// Before that, face_analysis counts are zero and identity_match is "pending".

Face analysis is deferred, not real-time, so fetch the report once status is validated. If your page sets a Content-Security-Policy, allow the enclave origin so the iframe can mount:

frame-src https://enclave.proctorlink.com;

The enclave origin is listed in the API reference, which is the canonical source if it ever changes.

Which route should you pick?

The decision is rarely about features, because all three run the same proctoring underneath and produce the same server-side integrity score. It is about where your exams live and how much you want to build.

DecisionLMS plugin (Moodle)Browser SDK + REST APILTI 1.3
Best forExams that already run in MoodleA custom web app or exam portal you own the code forA non-Moodle LMS that already speaks LTI 1.3
Code you writeNone. An admin installs it and enables proctoring per quizOne backend call to mint a session, plus a few lines of browser SDKLMS-side configuration, not application code
Where it runsInside MoodleYour backend (mint and report) and the candidate browser (capture)Launched from the host LMS
Camera captureHandled by the pluginThe in-browser SDK enclaveHandled by the launch
Reading the reportIn the Moodle interfaceGET /v1/sessions/:id from your backendThrough the LMS and gradebook
Server credentialsManaged for youaccess-token and secret-token on your server onlyConfigured once in the LMS

A short version: if the exam runs in Moodle, take the plugin and see Best Moodle proctoring plugin. If it runs in another LMS that speaks LTI, use LTI 1.3. If it runs in your own application, use the SDK plus API.

Why is there no API-only proctoring?

A backend call cannot see the candidate. A browser tab cannot be recorded from your server, so capturing the camera and the browser events always needs code running in the tab. That code is the SDK, which mounts a cross-origin iframe enclave served from ProctorLink’s own domain. The REST API does the two things a server can do: mint the session before the exam, and return the finished report after it.

This has a practical consequence worth stating plainly. If your goal is proctoring with no browser code at all, the API on its own will not get you there. The route for that is the LMS plugin, which bundles the browser half for you. The camera permission binds to the enclave origin rather than your domain, which is why a candidate who has already granted it on one exam is not prompted again on another site that embeds ProctorLink.

How much can a browser-only integration detect?

The SDK route is Tier 1: it runs entirely in the browser with no install. That covers the signals a tab can legitimately observe. Deeper inspection needs more privileged software, which is why the tiers exist. Pick the tier that matches your risk, not the deepest one available.

TierCandidate installWhat it can observe
Tier 1: Browser SDKNoneCamera, microphone, focus and blur, fullscreen state, clipboard, device changes
Tier 2: Browser extensionExtensionAdds tab enumeration, per-application focus, and download blocking
Tier 3: Desktop agentDesktop appProcess inspection, display enumeration, screen-recording detection, and full lockdown

A browser tab cannot see other applications, a second device, a virtual machine, or a remote-desktop session. That is a property of the web platform, not a gap in any one vendor, and it is exactly why the extension and desktop tiers exist. For how browser signals feed the verdict, see Moodle proctoring plugin comparison.

Common mistakes when choosing and wiring a route

  • Putting your API key in browser JavaScript. The access-token and secret-token are server-side credentials. Anyone holding them can mint sessions billed to your account and read your reports. Fix: mint on your backend and pass only the session_jwt to the SDK.
  • Generating a random attempt_id on page load. Resume keys off attempt_id, so a new value on every refresh splits one exam into several sessions and bills the attempt more than once. Fix: derive attempt_id from your own attempt record so it is stable for the attempt.
  • Fetching the report the instant the exam ends. Face analysis is deferred, so an immediately fetched report has zero face counts and identity_match of pending. That is an unfinished result, not a clean one. Fix: fetch when status is validated, polling on a sensible interval rather than a tight loop.
  • Forgetting the CSP frame-src rule. If your page sets a Content-Security-Policy and does not allow the enclave origin, the iframe cannot mount and capture never starts. Fix: add the enclave origin to frame-src.
  • Refreshing a token by tearing the session down. Calling stop() or destroy() to get a new token ends the attempt server-side, so the next mint creates a separate session: two reports for one attempt, billed twice. Fix: handle the token-expired event and call updateToken() with a freshly minted token for the same attempt_id.

Where does each route keep your credentials safe?

The security model is the same whichever route you pick, and it is worth understanding before you build. Your API key is server-side only. The browser receives a short-lived, origin-bound session token, and that token lives inside the enclave rather than in host-page JavaScript. The integrity score is computed server-side only, so the client cannot influence the verdict. That last property is the core anti-tamper guarantee: a candidate cannot edit their own score no matter what they do in the browser.

Across published deployments, ProctorLink has supported more than one million proctored exam sessions (methodology note below). Full cohort sizes and outcomes are documented on the case studies page.

What customers say on G2

Institutions evaluating proctoring tools often look for independent feedback outside vendor case studies. ProctorLink is listed on G2, where Moodle administrators and training teams share verified product reviews.

Read ProctorLink reviews on G2 →

Frequently Asked Questions

For a custom web application you use both, because they do different jobs. The REST API runs on your backend: you call POST /v1/sessions with your access-token and secret-token to mint a short-lived session token, and later call GET /v1/sessions/:id to read the integrity report. The SDK runs in the candidate's browser: ProctorLink.createSession({ jwt, sessionId }).start() mounts the enclave, requests the camera, and captures keyframes. Neither replaces the other. The API cannot see or record the candidate, and the SDK never holds your server credentials. If your exams instead run inside Moodle, the plugin bundles both halves for you and you write no integration code at all.

Sources & references

Deployment statistics and product behaviour described in this guide link to the sources below.

Next steps

Ready to add proctoring to software you already own? Start with a walkthrough, then pick the route that matches where your exams run.

More Proctoring Guides

Add Proctoring to Your Own Application

Your backend mints a session, a small browser loader runs it, and you read a server-side integrity score. Pilot the SDK on a real exam and check the reviewer workload before you commit.