Liveness Check
Overview​
The liveness check system verifies that a self-service user is a real person (not a photo or replay attack) using a challenge-response face-capture flow from the mobile SDK. Results — including the captured face image in Base64 — are persisted per user and are available for admin review.
There are five APIs across two roles:
| Command | Role | Purpose |
|---|---|---|
SubmitLivenessCheckCommand | Customer (authenticated) | Submit a successful liveness result (creates record) |
UpdateLivenessCheckCommand | Customer (authenticated) | Submit any result (successful or not) — used by SDK |
CheckLivenessStatusQuery | Customer (authenticated) | Check whether the current user has passed liveness |
GetUserLivenessCheckQuery | Admin | Get full liveness record + face image for any user by ID |
RetrieveLivenessChecksQuery | Admin | Paginated list of liveness records (filter by user/session) |
All endpoints share the same base path: POST /api/BPMSelfService/commands/{CommandName}
1. Submit Liveness Check​
Endpoint: POST /api/BPMSelfService/commands/SubmitLivenessCheckCommand
If isSuccessful is false, the command returns an error immediately. Use UpdateLivenessCheckCommand to record any outcome.
The selfServiceUserId is resolved automatically from the bearer token — do not include it in the payload.
Request Body​
{
"sessionId": "sdk-session-abc123",
"isSuccessful": true,
"imageBase64": "data:image/jpeg;base64,/9j/4AAQSkZJRgAB...",
"imagePath": "/uploads/liveness/abc123.jpg",
"metadata": {
"timestamp": 1742680800000,
"completedAt": "2026-03-22T14:00:00Z",
"verificationResult": true,
"sessionDuration": 4200,
"lightingValue": 0.93,
"challengeCount": 3,
"completedChallenges": ["BLINK", "SMILE", "TURN_LEFT"],
"challenges": ["BLINK", "SMILE", "TURN_LEFT"],
"finalCapture": {
"verificationResult": true,
"sessionDuration": 1100,
"lightingValue": 0.95
}
},
"imageMetadata": {
"verificationResult": true,
"sessionDuration": 900,
"lightingValue": 0.91
}
}
Parameters​
| Field | Type | Required | Description |
|---|---|---|---|
sessionId | string | Yes | Unique session identifier from the liveness SDK |
isSuccessful | boolean | Yes | Must be true — failed checks are rejected |
imageBase64 | string | No | Base64-encoded face capture image (with or without data URI prefix) |
imagePath | string | No | Server-side path if image was uploaded separately |
metadata | object | No | Challenge + session metrics from the SDK |
metadata.timestamp | long | No | Unix epoch milliseconds |
metadata.completedAt | string | No | ISO 8601 datetime of completion |
metadata.verificationResult | boolean | No | SDK verification outcome |
metadata.sessionDuration | integer | No | Duration in milliseconds |
metadata.lightingValue | number | No | Lighting score (0–1) |
metadata.challengeCount | integer | No | Number of challenges presented |
metadata.completedChallenges | string[] | No | Challenges the user completed (e.g. ["BLINK","SMILE"]) |
metadata.challenges | string[] | No | All challenges presented |
metadata.finalCapture | object | No | Metrics for the final face capture |
imageMetadata | object | No | Metrics specific to the captured image |
Response​
{
"isSuccessful": true,
"statusCode": "00",
"message": "Liveness check completed successfully.",
"data": {
"id": 42,
"sessionId": "sdk-session-abc123",
"isSuccessful": true,
"verificationResult": true,
"challengeCount": 3,
"completedAt": "2026-03-22T14:00:00Z",
"createdAt": "2026-03-22T14:00:05Z"
}
}
2. Update Liveness Check​
Endpoint: POST /api/BPMSelfService/commands/UpdateLivenessCheckCommand
Records any liveness outcome (successful or failed). This is the command the mobile SDK should call directly, as it accepts isSuccessful: false without rejecting the request.
Request Body​
Identical structure to SubmitLivenessCheckCommand but isSuccessful can be false.
{
"sessionId": "sdk-session-abc123",
"isSuccessful": false,
"metadata": {
"verificationResult": false,
"sessionDuration": 8000,
"lightingValue": 0.42,
"challengeCount": 3,
"completedChallenges": ["BLINK"]
}
}
Response​
{
"isSuccessful": true,
"statusCode": "00",
"message": "Liveness check recorded but verification was not successful.",
"data": {
"id": 43,
"sessionId": "sdk-session-abc123",
"isSuccessful": false,
"verificationResult": false,
"challengeCount": 3,
"completedAt": null,
"createdAt": "2026-03-22T14:05:00Z"
}
}
3. Check Liveness Status​
Endpoint: POST /api/BPMSelfService/commands/CheckLivenessStatusQuery
Lightweight check — returns whether the currently authenticated user has at least one successful liveness record on file. No body required.
Request Body​
{}
Response​
{
"isSuccessful": true,
"statusCode": "00",
"message": "Liveness check has been completed.",
"data": {
"HasCompletedLivenessCheck": true,
"LivenessCheckDate": "2026-03-22T14:00:00Z",
"SessionId": "sdk-session-abc123"
}
}
When the user has not completed liveness:
{
"isSuccessful": true,
"statusCode": "00",
"message": "Liveness check has not been completed.",
"data": {
"HasCompletedLivenessCheck": false,
"LivenessCheckDate": null,
"SessionId": null
}
}
4. Get User Liveness Check (Admin)​
Endpoint: POST /api/BPMSelfService/commands/GetUserLivenessCheckQuery
This API requires an admin bearer token. It returns the full liveness record including the captured face image (ImageBase64) for display in the admin portal.
Request Body​
{
"userId": 1234
}
| Field | Type | Required | Description |
|---|---|---|---|
userId | long | Yes | The SelfServiceUser.Id to look up |
Response​
{
"isSuccessful": true,
"statusCode": "00",
"data": {
"UserId": 1234,
"EmailAddress": "customer@example.com",
"UserId2": "USR-00001234",
"FirstName": "Jane",
"LastName": "Doe",
"MiddleName": null,
"DisplayName": "Jane Doe",
"HasCompletedLivenessCheck": true,
"LivenessCheck": {
"Id": 42,
"SessionId": "sdk-session-abc123",
"IsSuccessful": true,
"VerificationResult": true,
"SessionDuration": 4200,
"LightingValue": 0.93,
"ChallengeCount": 3,
"CompletedChallenges": ["BLINK", "SMILE", "TURN_LEFT"],
"FinalCaptureVerificationResult": true,
"ImageBase64": "data:image/jpeg;base64,/9j/4AAQSkZJRgAB...",
"HasImage": true,
"ImagePath": null,
"ImageVerificationResult": true,
"CompletedAt": "2026-03-22T14:00:00Z",
"CreatedAt": "2026-03-22T14:00:05Z",
"DeviceInfo": "{\"userAgent\":\"...\",\"devicePlatform\":\"Android\",\"appVersion\":\"2.1.0\"}",
"ClientIp": "41.58.12.100"
}
}
}
When HasCompletedLivenessCheck is false, LivenessCheck will be null.
HasCompletedLivenessCheck Logic​
A user is considered to have completed liveness only when the latest record satisfies both:
IsSuccessful == trueVerificationResult == true
5. Retrieve Liveness Checks (Admin — Paginated)​
Endpoint: POST /api/BPMSelfService/commands/RetrieveLivenessChecksQuery
Paginated list of liveness check records. Useful for auditing or bulk review.
Request Body​
{
"selfServiceUserId": 1234,
"pageNumber": 1,
"pageSize": 20
}
| Field | Type | Required | Description |
|---|---|---|---|
preRegistrationId | long | No | Filter by pre-registration ID |
selfServiceUserId | long | No | Filter by self-service user ID |
sessionId | string | No | Filter by SDK session ID |
pageNumber | integer | No | Page number (default: 1) |
pageSize | integer | No | Page size (default: 20) |