@peepl/proctoring-server
v0.1.0
Published
Server-side integration helpers for client-owned proctoring analysis
Readme
@peepl/proctoring-server
Node.js 20+ backend SDK for client-owned camera analysis. It validates model results and submits them directly to PEEPL using an API key. It does not run inference, load models, or access cameras.
Use @peepl/proctoring-browser on your client page to capture
images and send them to your backend.
Install
bun add @peepl/proctoring-serverRegistry installation requires the package to be published there. To build from source, see the workspace guide.
Backend integration
PEEPL must enable external camera analysis for your client and issue an API key. Keep that key and your AI credentials on your server.
Your route must authenticate and authorize the candidate, apply request limits
and CSRF protection, and run inference on the received image. runClientModel
below represents your own backend inference function, not an SDK method.
import { submitCameraAnalysis } from '@peepl/proctoring-server'
import type { CameraAnalysisRequest, CameraAnalysisResult } from '@peepl/proctoring-server'
async function analyzeAuthorizedImage(input: CameraAnalysisRequest) {
const result: CameraAnalysisResult = await runClientModel(input.image)
await submitCameraAnalysis({
gatewayUrl: process.env.PEEPL_GATEWAY_URL!,
apiKey: process.env.PEEPL_ANALYSIS_API_KEY!,
request: {
sid: input.sessionId,
evidenceId: input.evidenceId,
capturedAt: input.capturedAt,
image: input.image,
},
result,
})
return { status: 'submitted' }
}| Backend setting | Value |
|---|---|
| PEEPL_GATEWAY_URL | HTTPS gateway base URL supplied by PEEPL; retain a trailing slash when it includes a path prefix. |
| PEEPL_ANALYSIS_API_KEY | API key issued for your client. |
The input is the browser request.
Return { "status": "submitted" } as JSON only after submission succeeds.
Propagate inference or submission failures as a non-success HTTP response.
Never submit a detection result supplied by the browser.
Model result contract
Normalize your model's output into this shape:
{
"model": "client-face-model",
"width": 320,
"height": 320,
"faces": [
{
"box": { "x": 80, "y": 40, "w": 120, "h": 160 },
"score": 0.95,
"landmarks": {
"left_eye": { "x": 110, "y": 85 },
"right_eye": { "x": 160, "y": 85 },
"nose": { "x": 135, "y": 110 },
"mouth_left": { "x": 115, "y": 140 },
"mouth_right": { "x": 155, "y": 140 }
}
}
]
}widthandheightmust match the submitted JPEG, not resized model input.- Coordinates use original-image pixels. Eye/mouth names are image-space:
left_eyeis the eye with the smaller x coordinate, not the person's left eye. - Boxes must stay within the image, with positive width and height.
- Scores must be finite numbers from 0 to 1. Each face needs all five landmarks; landmarks outside the image can represent an incomplete face.
- Return one entry per face, at most 10. No face is
faces: []. - Inference failure is an error, not
faces: [].
For external analysis, PEEPL records an incident unless there is exactly one face with score at least 0.7, all five landmarks inside the image, and a box more than 2 pixels from every edge.
AI compatibility
| AI implementation | Integration requirement |
|---|---|
| Existing nucleus-api-face-detector YuNet API | Use the successful response's data object. |
| Client or vendor face-detection API | Adapt its output to the result contract above. |
| ONNX/PyTorch/TensorFlow model | Run it in your backend runtime, then normalize its output. |
| Text-only analysis or face count only | Insufficient: boxes, scores, and landmarks are required. |
The SDK is provider-agnostic, not an automatic model loader. It does not add identity matching, liveness detection, or screen/object analysis.
Submission requirements
- The gateway verifies that the API key and candidate embed session belong to the same client, and validates the JPEG and analysis result.
capturedAtmust be within five minutes of PEEPL's clock; synchronize your backend clock. Evidence IDs are deduplicated for 12 hours.- An API key authenticates your backend, not model accuracy or video authenticity.
Other backend languages can submit directly with
POST {gateway}/embed/external-analysis, an x-api-key header, and a JSON body
containing sid, evidence_id, captured_at, image, and analysis.
analysis follows the model result contract above. The image must be a JPEG
data URL. This package itself runs only on Node.js.
API
| Member | Description |
|---|---|
| submitCameraAnalysis({ gatewayUrl, apiKey, request, result, fetchImpl?, signal? }) | Validate and submit a result. Resolves on success; throws on validation or HTTP failure. |
| validateCameraAnalysisResult(result) | Validate a model result without submitting. Throws if invalid. |
| fetchImpl | Optional custom fetch implementation. |
| signal | Optional abort signal for the submission request. |
TypeScript exports include CameraAnalysisRequest, CameraAnalysisResult,
AnalysisFace, SubmitCameraAnalysisRequest, and SubmitCameraAnalysisOptions.
