Face Authentication
I. Face Registration
I.1 Face registration from eKYC onboarding user
Use the face from eKYC onboarding to register for face authentication.
Required parameters:
| key | type | required | description | max length |
|---|---|---|---|---|
cus_user_id | string | yes | user id of customer | 256 |
faces | []image | no | selfie image from eKYC onboarding | 50 |
face_in_id_card | image | no | image of the face in id_card | |
face_type | string | no | type of face input (selfie, id_card) | |
selfie_type | string | no | flash_16: Android use SDK TS, flash_8: iOS use SDK TS, vendor_a: use SDK other vendor | 64 |
Parameter Selfie Type:
| param | Android | iOS | other_vendor |
|---|---|---|---|
selfie_type | flash_16 | flash_8 | vendor_a |
Use API directly: Face registration
Use Java SDK: Java API library
Sample code
// Face Auth Registration
String transactionID = "";
Map<String, String> headers = new HashMap<String, String>();
headers.put("X-Request-Id", "use as currently value limit 64 chars");
String cusUserID = "c1b3b3b3-1b3b-4b3b-8b3b-3b3b3b3b3b3b"; // Required
List<TVSyncImage> imagesFaceAuth = Arrays.asList(
TVSyncImage.createById("3e2693e7-1e8f-40f0-be68-2cf73b09c61b"));
String deviceId = "";
String appId = "";
Double lat = Double.valueOf(0d);
Double lng = Double.valueOf(0d);
String faceType = "selfie";
String selfieType = "flash_16";
TVSyncImage faceInIdCard = TVSyncImage.createById("e975bc8c-9d6e-4118-b905-da8c121636c9");
TVFaceAuthenRegistrationRequest faceAuthRegistrationRequest = TVFaceAuthenRegistrationRequest.builder(cusUserID)
.cusUserId(cusUserID).faces(imagesFaceAuth).selfieType(selfieType)
.deviceId(deviceId).appId(appId).lat(lat).lng(lng)
.faceType(faceType).faceInIdCard(faceInIdCard)
.build();
TVResponseData<TVFaceAuthenResponse> faceAuthRegistrationResponse = TVApi.getInstance().faceAuthenRegister(faceAuthRegistrationRequest, transactionID, headers);
if (faceAuthRegistrationResponse.hasErrors()) {
List<TVApiError> errors = faceAuthRegistrationResponse.getErrors();
System.out.println("Face Auth Registration error:" + errors.get(0).getMessage());
} else {
System.out.println("Face Auth Registration successful");
}
II. Face Authen
II.1 Recommended: UI Only. Client fully control
All APIs were called from the Bank's backend. No API calls at SDK.
Reference Scenario

Step 1: Get settings from Backend
- Define
flow_idto use for your business: eg.face_authorreset_password
Use API directly: Get client settings
Use Java SDK: Java API library
Sample code
// Get client settings
String flowID = "face_auth"
TVResponseData<TVClientSettings> response = TVApi.getInstance().getClientSettings(flowID);
if (response.hasErrors()) {
List<TVApiError> errors = response.getErrors();
System.out.println("Get client settings error:" + errors.get(0).getMessage());
} else {
System.out.println("Get client settings successful");
}
System.out.println(response.getRawJSON());
Step 2: Init SDK with settings from Step 1
Pass settings string from step 1 to parameter jsonConfigurationByServer
Android: Init SDK
iOS: Init SDK
Sample code
TVInitializeConfiguration config = new TVInitializeConfiguration.Build()
.setJsonConfigurationByServer(jsonConfigurationByServer)
.setLanguageCode(languageCode)
.setTheme(theme)
.build();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TrustVisionSDK.INSTANCE.init(context, config, new BaseTrustVisionSDK.TVInitializeListener() {
@Override
public void onInitSuccess() {
// Start Face Authen
// eg. startFaceAuthentication(....)
}
@Override
public void onInitError(@NonNull TVDetectionError error) {
// Handle errors
}
});
}
Step 3: Start face authentication after init SDK successfully.
Android: Start Face Authentication
iOS: Start Face Authentication
Parameters:
| param | Android | iOS |
|---|---|---|
authMode | authMode = TVAuthMode.flash16(selfieConfiguration) | method: TVFaceAuthenMethod.flash8 |
Sample code
TVSelfieConfiguration selfieConfiguration = new TVSelfieConfiguration.Builder()
.setCameraOption(TVSDKConfiguration.TVCameraOption.FRONT)
.setEnableSound(false)
.setLivenessMode(TVLivenessMode.PASSIVE)
.setEnableVerticalChecking(false)
.setSkipConfirmScreen(false)
.setEnableUploadFrames(false)
.setEnableUploadImages(false)
.setEnableSanityCheck(false)
.setEnableVerifyLiveness(false)
.build();
TVFaceAuthenticationConfiguration configuration = TVFaceAuthenticationConfiguration.builder()
.setCusUserId("")
.setAuthType(AuthType.AUTH)
.setAuthMode(TVAuthMode.flash16(selfieConfiguration))
.setEnableFaceAuthentication(false)
.setEnableFaceRegistration(false)
.build();
TrustVisionSDK.INSTANCE.startFaceAuthentication(activity, configuration, new TVCapturingCallBack() {
@Override
public void onNewFrameBatch(FrameBatch frameBatch) {
}
@Override
public void onError(TVDetectionError error) {
}
@Override
public void onSuccess(TVDetectionResult result) {
}
@Override
public void onCanceled(){
}
});
Step 4: Mobile App receives result images, frames videos from SDK
Android: Handle results from SDK
iOS: Handle results from SDK
- SDK output result images, and frames videos.
- Mobile App upload images and frames videos to server.
- To upload image use API Upload image
- To upload frames video use API Upload frames
- After upload all images, frames videos finish go to step 5.
Note: frames video were batched and sent to host app via method onNewFrameBatch to upload async.
Sample code
Map<String, String> selfieFrameBatchIdsDictionary = new HashMap<String, String>();
TrustVisionSDK.INSTANCE.startFaceAuthentication(activity, configuration, new TVCapturingCallBack() {
// If frameBatch is uploaded to server by the SDK, the host app does not need to override this method
@Override
public void onNewFrameBatch(FrameBatch frameBatch) {
Gson gson = new Gson();
String framesStr = gson.toJson(frameBatch.getFrames());
Map<String, Object> params = new HashMap<>();
params.put("frames", framesStr);
params.put("metadata", frameBatch.getMetadata());
params.put("label", "video");
String jsonToBeUploaded = gson.toJson(map);
// upload frame batch to server using this api:
// /ekyc-core/image-file/upload-video-audio-frames/
YourResponseObject uploadingResult = yourMethodToUploadFrameBatch(jsonToBeUploaded);
// Keep the id that generated by the SDK corresponding with the one responded from server
selfieFrameBatchIdsDictionary.put(
key = frameBatch.getId(),
value = uploadingResult.fileId
);
}
@Override
public void onError(TVDetectionError error) {
}
@Override
public void onSuccess(TVDetectionResult result) {
List<TVSyncFile> faceIds = new ArrayList();
List<TVGestureImage> gestureFaces = new ArrayList();
List<TVVideoFile> videoIds = new ArrayList();
String cusUserId = "1";
String selfieType = "selfie";
String authType = "transfer";
for (TVImageClass face: result.getFaces()) {
faceIds.add(TVSyncFile.createById(face.getImageId());
}
for (TVGestureFace gesture: result.getGestureFaces()) {
String gestureName = gesture.getGesture();
List<TVSyncFile> ids = new ArrayList();
for (TVImageClass img: gesture.getImages()) {
ids.add(TVSyncFile.createById(img.getImageId()));
}
gestureFaces.add(new TVGestureImage(gesture, ids));
}
// If frameBatch is uploaded to server by the SDK
for (String id: result.getLivenessFrameBatchIds()) {
videoIds.add(TVVideoFile.createById(id));
}
// If frameBatch is uploaded to server by the host app
for (String id : selfieFrameBatchIdsDictionary.values()) {
videoIds.add(TVVideoFile.createById(id));
}
// SDK uploads images to the server and returns the image IDs to the host app
// call api to verify face authentication
// /api-docs/face-authentication-api/authenticate/
yourMethodToCallFaceAuthenticationAPI(
cusUserId,
faceIds,
gestureFaces,
videoIds,
selfieType,
authType
);
}
@Override
public void onCanceled(){
}
});
Step 5: Integrate client's backend call TS's backend
Use API directly: Request face authentication
Use Java SDK: Face Auth
Parameters:
| param | Android | iOS | other_vendor |
|---|---|---|---|
auth_type | transfer | transfer | transfer |
selfie_type | flash_16 | flash_8 | vendor_a |
client_transaction_id is your transaction ID to identify for reconciling or tracing between 2 systems
Sample code
String cusUserID = "c1b3b3b3-1b3b-4b3b-8b3b-3b3b3b3b3b3b"; // Required
String authType = TVFaceAuthAuthTypeConstant.TRANSFER;
String selfieType ="flash_16";// "flash_16" for android, "flash_8" for iOS, the value should get from SDK.
String clientTransactionID = "a9c9a80a-8ae8-4de9-8dab-d85a85d1882e"; // your transaction ID to identify for reconciling or tracing between 2 systems
List<TVSyncImage> imagesFaceAuth = Arrays.asList(
TVSyncImage.createById("3e2693e7-1e8f-40f0-be68-2cf73b09c61b"),
TVSyncImage.createById("36dc7bd6-ed04-4bd3-bd32-61cb9ac4837c"),
TVSyncImage.createById("15b0db75-d238-4a4b-bea9-4897c7af0a08"),
TVSyncImage.createById("d8c330d4-5c7a-4f8e-a0f0-44efffb0cfc6"));
List<TVGestureImages> gestureImagesFaceAuth = Arrays.asList(
new TVGestureImages("right", Arrays.asList(TVSyncImage.createById("99bbe3b5-23e8-41d6-a496-956d7e5c3ed5"))),
new TVGestureImages("down", Arrays.asList(TVSyncImage.createById("fe140383-81ff-47e3-930f-154272e7da6c"))),
new TVGestureImages("left", Arrays.asList(TVSyncImage.createById("dd553b55-5b02-48e3-b2bf-ecfa45c9119b")))
);
List<TVSyncVideo> videos = Arrays.asList(
TVSyncVideo.createById("dfb4a246-09df-42fc-be41-0faafc8dc5bc")
);
TVResponseData<TVFaceAuthenResponse> faceAuthResponse = TVApi.getInstance().faceAuthen(faceAuthRequest,"", headers);
if (faceAuthResponse.hasErrors()) {
List<TVApiError> errors = faceAuthResponse.getErrors();
System.out.println("Face Auth error:" + errors.get(0).getMessage());
} else {
System.out.println("Face Auth successful");
}
II.2 Hybrid: Share APIs called for both SDK and client's backend.
There are some APIs called from SDK. There are some APIs called from the client's backend.
Reference Scenario

Step 1: Create temporary credentials with a verified session token.
Use API directly: Create temporary credential
Use Java SDK: Create temporary credentials
Sample code
// Create temporary credentials
int durationInSeconds = 900;
String transactionID = "";
String xRequestID = "";
String xRequestID2 = "";
Map<String, String> headers = new HashMap<String, String>();
headers.put("X-Request-Id", xRequestID);
headers.put("X-Request-Id2", xRequestID2);
TVTemporaryCredentialRequest request = new TVTemporaryCredentialRequest(durationInSeconds);
TVResponseData<TVTemporaryCredentialResponse> response = TVApi.getInstance().createTemporaryCredential(request, transactionID, headers);
System.out.println("TVTemporaryCredentialResponse: " + GsonUtils.toJson(response));
if (response.hasErrors()) {
List<TVApiError> errors = response.getErrors();
System.out.println("Create temporary credentials error:" + errors.get(0).getMessage());
} else {
System.out.println("Create temporary credentials successful");
}
Secure X-Request-ID2 to return SDK
Use Java SDK: Reference
Return Mobile values to init SDK
| props | description |
|---|---|
x-request-id | API reconciliation. Reference |
x-request-id2 | Hash(x-request-id2). Reference |
access_key | the value from API temporary credentials. Reference |
secret_key | the value from API temporary credentials. Reference |
face_auth_endpoint | the value from TS's administrator |
Step 2: Init SDK with temporary credential from Step 1
Android: Init SDK
iOS: Init SDK
Parameters:
The flowId parameter is defined for each use-case differently
| flowId | description |
|---|---|
face_authen | Authenticate with face for all flows |
reset_password | Authenticate to reset password flow |
login | Use face to replace text password |
payment | Authenticate payment |
transfer | Authenticate transfer |
transfer_type_A | Authenticate transfer type A |
transfer_type_B | Authenticate transfer type B |
transfer_type_C | Authenticate transfer type C |
transfer_type_D | Authenticate transfer type D |
... | You can define any authentication type based on your business |
Other parameters:
| parameter | description |
|---|---|
endpoint | From step 1. eg. https://tv-staging.trustingsocial.com/api |
accessKeyId | From step 1 |
accessKeySecret | From step 1 |
xRequestId | From step 1 |
xRequestId2 | From step 1 |
Sample code
TVInitializeConfiguration config = new TVInitializeConfiguration.Build()
.setEndpoint(endpoint)
.setAccessKeyId(accessKeyId)
.setAccessKeySecret(accessKeySecret)
.setXRequestId(xRequestId)
.setXRequestId2(xRequestId2)
.setFlowId(flowId)
.setLanguageCode(languageCode)
.setTheme(theme)
.build();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TrustVisionSDK.INSTANCE.init(context, config, new BaseTrustVisionSDK.TVInitializeListener() {
@Override
public void onInitSuccess() {
// Start Face Authen
// eg. startFaceAuthentication(....)
}
@Override
public void onInitError(@NonNull TVDetectionError error) {
// Handle errors
}
});
}
Step 3: Start face authentication after init SDK successfully.
Android: Start Face Authentication
iOS: Start Face Authentication
Parameters:
| param | Android | iOS |
|---|---|---|
authMode | authMode = TVAuthMode.flash16(selfieConfiguration) | method: TVFaceAuthenMethod.flash8 |
Sample code
TVSelfieConfiguration selfieConfiguration = new TVSelfieConfiguration.Builder()
.setCameraOption(TVSDKConfiguration.TVCameraOption.FRONT)
.setEnableSound(false)
.setLivenessMode(TVLivenessMode.PASSIVE)
.setEnableVerticalChecking(false)
.setSkipConfirmScreen(false)
.setEnableUploadFrames(true)
.setEnableUploadImages(true)
.setEnableSanityCheck(false)
.setEnableVerifyLiveness(false)
.build();
TVFaceAuthenticationConfiguration configuration = TVFaceAuthenticationConfiguration.builder()
.setCusUserId("")
.setAuthType(AuthType.AUTH)
.setAuthMode(TVAuthMode.flash16(selfieConfiguration))
.setEnableFaceAuthentication(false)
.setEnableFaceRegistration(false)
.build();
TrustVisionSDK.INSTANCE.startFaceAuthentication(activity, configuration, new TVCapturingCallBack() {
@Override
public void onNewFrameBatch(FrameBatch frameBatch) {
}
@Override
public void onError(TVDetectionError error) {
}
@Override
public void onSuccess(TVDetectionResult result) {
}
@Override
public void onCanceled(){
}
});
Step 4: Mobile App receives result images ID, frames videos ID from SDK
Android: Handle results from SDK
iOS: Handle results from SDK
Sample code
TrustVisionSDK.INSTANCE.startFaceAuthentication(activity, configuration, new TVCapturingCallBack() {
@Override
public void onError(TVDetectionError error) {
}
@Override
public void onSuccess(TVDetectionResult result) {
List<TVSyncFile> faceIds = new ArrayList();
List<TVGestureImage> gestureFaces = new ArrayList();
List<TVVideoFile> videoIds = new ArrayList();
String cusUserId = "1";
String selfieType = "selfie";
String authType = "transfer";
for (TVImageClass face: result.getFaces()) {
faceIds.add(TVSyncFile.createById(face.getImageId());
}
for (TVGestureFace gesture: result.getGestureFaces()) {
String gestureName = gesture.getGesture();
List<TVSyncFile> ids = new ArrayList();
for (TVImageClass img: gesture.getImages()) {
ids.add(TVSyncFile.createById(img.getImageId()));
}
gestureFaces.add(new TVGestureImage(gesture, ids));
}
for (String id: result.getLivenessFrameBatchIds()) {
videoIds.add(TVVideoFile.createById(id));
}
// SDK uploads images to the server and returns the image IDs to the host app
// call api to verify face authentication
// /api-docs/face-authentication-api/authenticate/
yourMethodToCallFaceAuthenticationAPI(
cusUserId,
faceIds,
gestureFaces,
videoIds,
selfieType,
authType
);
}
@Override
public void onCanceled(){
}
});
Step 5: Integrate client's backend call TS's backend
Use API directly: Request face authentication
Use Java SDK: Face Auth
Parameters:
| param | Android | iOS | other_vendor |
|---|---|---|---|
auth_type | transfer | transfer | transfer |
selfie_type | flash_16 | flash_8 | vendor_a |
client_transaction_id is your transaction ID to identify for reconciling or tracing between 2 systems
Sample code
String cusUserID = "c1b3b3b3-1b3b-4b3b-8b3b-3b3b3b3b3b3b"; // Required
String authType = TVFaceAuthAuthTypeConstant.TRANSFER;
String selfieType ="flash_16";// "flash_16" for android, "flash_8" for iOS, the value should get from SDK.
String clientTransactionID = "a9c9a80a-8ae8-4de9-8dab-d85a85d1882e"; // your transaction ID to identify for reconciling or tracing between 2 systems
List<TVSyncImage> imagesFaceAuth = Arrays.asList(
TVSyncImage.createById("3e2693e7-1e8f-40f0-be68-2cf73b09c61b"),
TVSyncImage.createById("36dc7bd6-ed04-4bd3-bd32-61cb9ac4837c"),
TVSyncImage.createById("15b0db75-d238-4a4b-bea9-4897c7af0a08"),
TVSyncImage.createById("d8c330d4-5c7a-4f8e-a0f0-44efffb0cfc6"));
List<TVGestureImages> gestureImagesFaceAuth = Arrays.asList(
new TVGestureImages("right", Arrays.asList(TVSyncImage.createById("99bbe3b5-23e8-41d6-a496-956d7e5c3ed5"))),
new TVGestureImages("down", Arrays.asList(TVSyncImage.createById("fe140383-81ff-47e3-930f-154272e7da6c"))),
new TVGestureImages("left", Arrays.asList(TVSyncImage.createById("dd553b55-5b02-48e3-b2bf-ecfa45c9119b")))
);
List<TVSyncVideo> videos = Arrays.asList(
TVSyncVideo.createById("dfb4a246-09df-42fc-be41-0faafc8dc5bc")
);
TVResponseData<TVFaceAuthenResponse> faceAuthResponse = TVApi.getInstance().faceAuthen(faceAuthRequest,"", headers);
if (faceAuthResponse.hasErrors()) {
List<TVApiError> errors = faceAuthResponse.getErrors();
System.out.println("Face Auth error:" + errors.get(0).getMessage());
} else {
System.out.println("Face Auth successful");
}
If the client allows calls API Face Authen from SDK. The client's backend calls API to cross-check the result.
Use API directly: Get result of the request
Sample code
curl -X GET \
https://tv-staging.trustingsocial.com/api/v1/requests_by_req_id/a4facba3-334b-41fb-97e3-4766cb70ae29 \
-H 'Authorization: TV <YOUR ACCESS KEY>:<CREATED SIGNATURE>' \
-H 'X-TV-Timestamp: 2019-04-21T18:00:15+07:00' \
-H 'Content-Type: application/json'
Sample response
{
"data": {
"status": "success",
"auth_check": {
"score": 0.9999999862517992,
"result": "matched"
},
"request_id": "cfc7b8d5-f2e2-437b-80e5-d600dfad26e2",
"user_metadata": {
"key1": "value1",
"key2": 2
},
"validate_faces_result": {
"sanity_verdict": "good",
"is_live": true,
"sanity_check": {
"portrait_sanity": {
"score": 1,
"verdict": "good"
},
"request_id": "9f89377f-4bb4-4ecb-884c-f46f1d7d6099",
"status": "success"
},
"liveness_check": {
"images": null,
"is_live": true,
"request_id": "baee3d03-8af4-421b-8968-a0f6172b4df8",
"score": 1,
"status": "success"
}
},
"auth_id": "d4f99f9b-4862-437f-a9c9-608e050d06c6",
"histories": [
{
"id": "f1ca6795-cbd4-4eec-821f-b4ac646db627",
"client_id": "0ef0f7e9-7f2f-4767-84b8-f76da7701c46",
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"face_auth_id": "887249dc-681c-4231-aff9-67734833aca7",
"id_card_face_id": "4f959f4a-f5de-4b50-8724-224e709d06c2",
"live_face_id": "009161c9-9c89-4573-8119-8f513de4449c",
"created_at": "2023-12-27T03:33:06.307977Z",
"auth_action": "login",
"status": "success",
"result": "",
"face_type": "selfie"
},
{
"id": "8c23af95-aaa0-4448-bfba-68acce31236e",
"client_id": "0ef0f7e9-7f2f-4767-84b8-f76da7701c46",
"cus_user_id": "3b4bf7b6-088b-4931-9279-9259f5c34fe3",
"face_auth_id": "",
"id_card_face_id": "4f959f4a-f5de-4b50-8724-224e709d06c2",
"live_face_id": "009161c9-9c89-4573-8119-8f513de4449c",
"created_at": "2023-12-21T07:24:19.829484Z",
"auth_action": "login",
"status": "failure",
"result": "image is not liveness",
"face_type": "id_card"
}
]
}
}