ProctorSafe Liveness Integration Guide

This guide explains how to add standalone liveness checks to your website or application using the ProctorSafe SDK.

It is written for developers integrating our SDK and APIs, and focuses on how to use the SDK, not on internal implementation details.

  • If you want full exam proctoring (continuous monitoring, marks/sections, trust score, network monitoring, etc.), see the main ProctorSafe Integration Guide.
  • If you only need to verify that a user is present and matches a reference (for onboarding, identity verification, or high‑risk actions), this liveness guide is for you.

Table of Contents

  1. What is liveness and when to use it
  2. Prerequisites
  3. SDK installation
  4. Quick start: run a liveness check
  5. Frontend integration
  6. Backend verification (optional but recommended)
  7. Dashboard access and APIs
  8. Configuration options
  9. Troubleshooting
  10. Next steps and related docs

What is liveness and when to use it

Liveness checks help you confirm that:

  • There is a real person in front of the camera (not a static photo or replay).
  • The person follows on‑screen instructions (e.g. tilt head left/right/up/down).
  • Optionally, the person matches a reference image and/or their estimated age is within an expected range.

Typical use cases:

  • Onboarding / KYC: Verify that the person creating an account is real and matches an identity document.
  • High‑risk actions: Step‑up verification when users change sensitive data or perform high‑value operations.
  • Exam / session unlock: Verify liveness once before granting access to a protected flow.

If you later decide you also need continuous exam monitoring, you can combine liveness with the full proctoring integration described in the main integration guide.


Prerequisites

Before integrating liveness, make sure you have:

  1. Tenant name (slug) – Provided by your tenant administrator, e.g. your-tenant-slug.
  2. Liveness feature enabled for your tenant – In the dashboard, an admin must enable “Liveness check” in the tenant feature settings. If this is disabled, attempts to start a liveness session will be rejected.
  3. Allowed origins configured – Your web application’s domain(s) must be added to the tenant’s allowed origins list so the SDK and APIs can be called from your site (see the CORS guidance in the main integration guide).
  4. Optionally: Signature configuration – Either use your own ECDSA key pair or the create API helper (POST /api/proctor/create) so you can pass signature and timestamp when starting liveness (if your tenant requires signatures).
  5. User environment requirements – A modern browser with camera access and reasonable lighting conditions.

The SDK will run basic environment checks and show a preflight screen if enabled.


SDK installation

Liveness is part of the same ProctorSafe SDK used for proctoring sessions. If you already installed the SDK for the main integration guide, you can reuse that setup.

1. Include the SDK script (required)

Add the ProctorSafe SDK to your HTML page:

<!DOCTYPE html> <html> <head> <title>Your Application</title> </head> <body> <!-- Your application content --> <!-- ProctorSafe SDK (auto-loads all dependencies) --> <script src="https://test.proctorsafe.eu/sdk/proctor.iife.js"></script> <!-- Your application scripts --> <script src="your-app.js"></script> </body> </html>

The SDK automatically loads its internal dependencies when needed. You don’t need to include any extra scripts yourself.

2. Optional: TypeScript support

If you are using TypeScript, you can reuse the same proctor.d.ts file described in the main integration guide:

  1. Download https://test.proctorsafe.eu/sdk/proctor.d.ts
  2. Place it in a types/ directory in your project
  3. Add the directory to your tsconfig.json include section

This gives you full type support for the window.Proctor object, including LivenessConfig and LivenessResult types.


Quick start: run a liveness check

This is the simplest way to run a liveness check from your frontend.

// Ensure the SDK is loaded (script tag present and window.Proctor available) const proctor = window.Proctor; async function runLiveness() { if (!proctor) { alert('ProctorSafe SDK not loaded'); return; } // Replace with your own values const tenantName = 'your-tenant-slug'; const applicationReference = 'onboarding-v1'; // Optional: signature + timestamp if your tenant requires signatures const { signature, timestamp } = await generateSignatureForTenant( tenantName, applicationReference ); const result = await proctor.liveness({ tenantName, applicationReference, signature, timestamp, ageCheck: false, showPreflight: true, }); if (result.livenessOk) { console.log('Liveness passed:', result); } else { console.log('Liveness failed:', result); } }

What this does:

  • Shows an optional preflight dashboard (camera/mic/lighting check).
  • Guides the user through looking straight and tilting their head in random directions.
  • Returns a LivenessResult object with:
    • livenessOk: whether the liveness check passed.
    • Optional estimatedAge.
    • Optional likenessPercentage and referenceImageSha256 (if you use a reference image).
    • livenessSessionId and resultBinding (for backend verification).

The following sections explain how to integrate this into your UI and backend.


Frontend integration

1. Prepare configuration

At a minimum, you must provide:

  • tenantName: your tenant slug.
  • applicationReference: a string that identifies the flow (e.g. onboarding-v1, kyc-step-2).

If your tenant requires signatures, you must also provide:

  • signature: base64 signature for your tenant + reference + timestamp.
  • timestamp: the timestamp used in the signature payload.

See the Signature section of the main integration guide for details and full examples. You can reuse the same signature generation logic for both proctoring and liveness.

2. Call Proctor.liveness(...)

Basic example:

async function startLivenessCheck() { const tenantName = 'your-tenant-slug'; const applicationReference = 'kyc-onboarding-2024'; // Optional: obtain signature and timestamp if required const { signature, timestamp } = await generateSignatureForTenant( tenantName, applicationReference ); const result = await window.Proctor.liveness({ tenantName, applicationReference, signature, timestamp, ageCheck: true, // enable age estimation showPreflight: true, // show preflight camera/mic/lighting screen }); if (!result.livenessOk) { // Liveness failed (e.g. user did not follow instructions) showError('Liveness check failed. Please try again.'); return; } // Liveness passed – you can now proceed console.log('Liveness result:', result); }

3. Optional: reference image for face match

If you want to verify that the user matches a specific face image (for example, a selfie from a previous session or a document scan), you can pass a base64 encoded reference image:

async function startLivenessWithReference(referenceImageBase64) { const result = await window.Proctor.liveness({ tenantName: 'your-tenant-slug', applicationReference: 'kyc-onboarding-2024', ageCheck: true, showPreflight: true, referenceImageBase64, // data URL: e.g. "data:image/jpeg;base64,...." }); if (result.likenessPercentage != null) { console.log('Likeness percentage:', result.likenessPercentage, '%'); } if (!result.livenessOk) { showError('Liveness or face match failed. Please try again.'); return; } // Use resultBinding + livenessSessionId for backend verification }

The SDK will:

  • Sample likeness throughout the interaction.
  • Return a likeness percentage (0–100) when available.
  • Return the SHA‑256 hash of the reference image.

You can use these values in your own business rules (for example, require a minimum likeness score).


For many use cases, it is enough to:

  1. Run Proctor.liveness(...) on the frontend.
  2. Check result.livenessOk.
  3. Store the high‑level outcome in your own system.

If you need stronger guarantees (for example, for regulated flows), you can use the liveness result verification endpoint from your backend to make sure the result:

  • Comes from ProctorSafe.
  • Has not been tampered with.
  • Matches the session and reference you expect.

1. Data returned to the frontend

The LivenessResult object includes:

  • livenessOk: overall success/failure.
  • livenessSessionId: unique session identifier.
  • resultBinding: a verification token (HMAC) bound to the session and result.
  • Optional metadata (estimatedAge, likenessPercentage, referenceImageSha256).

Your frontend should send at least the following to your backend:

{ "livenessSessionId": "lsn_123...", "livenessOk": true, "resultBinding": "hex-hmac-value", "likenessPercentage": 92, "referenceImageSha256": "abc123...", "estimatedAge": 27 }

2. Verify result on your backend

On your backend, you call the ProctorSafe liveness result API:

  • Method: POST
  • Path: /api/proctor/liveness/result

This endpoint verifies the result binding and returns a simple JSON status.

Example (Node.js / server‑side):

import fetch from 'node-fetch'; async function verifyLivenessResult(result) { const response = await fetch('https://test.proctorsafe.eu/api/proctor/liveness/result', { method: 'POST', headers: { 'Content-Type': 'application/json', // If authentication headers are required for your tenant, add them here }, body: JSON.stringify({ liveness_session_id: result.livenessSessionId, liveness_ok: result.livenessOk, likeness_percentage: result.likenessPercentage ?? null, reference_image_sha256: result.referenceImageSha256 ?? null, estimated_age: result.estimatedAge ?? null, result_binding: result.resultBinding, }), }); if (!response.ok) { const error = await response.json().catch(() => ({})); throw new Error(error.error || 'Liveness result verification failed'); } const data = await response.json(); return data.ok === true; }

Typical flow:

  1. Frontend runs Proctor.liveness(...).
  2. Frontend sends LivenessResult to your backend.
  3. Backend calls /api/proctor/liveness/result.
  4. If verification succeeds, your backend can safely accept the liveness result and continue the flow.

Time limits and validity window

There are a few important time-related limits to be aware of:

  • Signature timestamp window (if signatures are required)
    When you pass signature and timestamp in the liveness config, the backend will only accept the timestamp if:

    • It is not more than 15 minutes in the past, and
    • It is not in the future.
      In practice, this means you should generate the signature right before you call liveness init and avoid reusing old signatures.
  • Liveness session validity (server-side verification window)
    After a successful liveness init, the server creates a per-session secret that is used to verify the resultBinding. This secret:

    • Is valid for 15 minutes from liveness init.
    • Can be used to verify the result multiple times during that window.
      Within the TTL, repeated calls to /api/proctor/liveness/result with the same session and same payload will succeed (idempotent verification). If your backend calls the endpoint after the 15‑minute window, the server will clear the key and return an error such as “Session key expired” or “Result already verified or session key expired”, and you must run a new liveness check.
  • User-facing attempts and timeouts (SDK behavior)
    The SDK itself enforces sensible limits to avoid liveness checks running forever:

    • Each step (look straight / tilt) has a step timeout (about 15 seconds). If the user does not complete the instruction in time, the engine restarts the flow for another attempt.
    • The engine allows a limited number of attempts (by default 3 attempts). After that, the check ends with livenessOk: false and you should decide how your application handles the failure (e.g. allow retry later, route to manual review, etc.).
      These limits are handled automatically by the SDK; you do not need to configure them for a typical integration.

You do not need to implement any cryptography yourself; the endpoint handles verification for you.

Note: If your deployment uses a different base URL than https://test.proctorsafe.eu, adjust the hostname accordingly.


Dashboard access and APIs

View liveness sessions in the dashboard

In the dashboard, liveness sessions appear in a dedicated Liveness sessions view. There you can:

  • Filter liveness sessions by tenant, application reference, and date.
  • Inspect high‑level results and metadata.
  • Confirm that your integration is working and that sessions are being recorded.

(The URL and navigation are the same dashboard you use for proctoring sessions; liveness is just a separate section.)

Programmatic access

For most integrations, you do not need a separate liveness API beyond the result verification endpoint described above. If you already use the standard ProctorSafe session APIs described in the main integration guide, you can continue to use them alongside liveness.

If you have specific reporting or export requirements, please contact support so we can recommend the best approach for your use case.


Configuration options

The Proctor.liveness call accepts a configuration object. The most important fields for integrators are:

  • Tenant and identification

    • tenantName (string, required): Your tenant slug.
    • applicationReference (string, required): Identifies the flow (onboarding, reset, etc.).
  • Security

    • signature (string, optional but required if your tenant enforces signatures): See main guide.
    • timestamp (number, optional): Milliseconds since Unix epoch, used with signature.
  • User experience

    • showPreflight (boolean, default true): Show a preflight dashboard before the check starts, so users can confirm camera, microphone and lighting.
  • Additional checks

    • ageCheck (boolean, default false): Enable age estimation; result includes a trimmed‑mean estimated age.
    • referenceImageBase64 (string, optional): Data URL of a reference image to compare against (e.g. data:image/jpeg;base64,...). Enables likeness scoring and reference image hashing.

We intentionally do not document every low‑level option here to keep the guide focused on the most relevant settings for integrators. If you need to tune advanced behavior, contact support and we can advise on best practices.


Troubleshooting

“Liveness check not enabled in configuration”

  • The tenant has liveness disabled.
  • Ask a tenant administrator to enable “Liveness check” in the tenant settings.

“SDK not loaded” or window.Proctor is undefined

  • Make sure the SDK script tag is present and loaded before your code runs.
  • Verify you are using the correct script URL and that no ad‑blocker or CSP is blocking it.

CORS or “Origin not allowed” errors

  • Your application origin is not in the tenant’s allowed origins list.
  • Ask an administrator to add your domain (production, staging, and local development) to the allowed origins, as described in the main integration guide.

User cannot start camera or preflight fails

  • The browser may have blocked camera/mic permissions.
  • Ask the user to enable camera access for your site.
  • Recommend good lighting and a stable internet connection.

Liveness fails repeatedly

Common causes:

  • The user does not follow the head‑movement instructions.
  • Lighting is too poor or the face is partially outside the frame.

Recommendations:

  • Show a clear error message and offer a retry button.
  • Provide brief tips (e.g. “Center your face in the frame and try again”).

Result verification fails on the backend

  • Ensure you are passing the exact livenessSessionId and resultBinding values returned by the SDK.
  • Check that you are calling the correct base URL for your environment.
  • Log the error response from /api/proctor/liveness/result for more detail and contact support if needed.

  • Full proctoring integration: For continuous exam monitoring with a trust score and rich timeline, see the main ProctorSafe Integration Guide.
  • Upgrading from liveness‑only to full proctoring:
    • Keep your existing liveness flow for onboarding or high‑risk actions.
    • Add Proctor.start(...) sessions for exams or long‑running activities, reusing your tenant configuration and signature setup.
  • Support:
    • Email: support@proctorsafe.eu
    • Dashboard: https://test.proctorsafe.eu/dashboard

If you are unsure whether you should use liveness only or full proctoring, start with this liveness guide for single‑step verification, and add full proctoring later for ongoing monitoring.