• About TrustVision
  • Android SDK
  • iOS SDK
  • Flutter SDK
  • React Native SDK
  • Web SDK
  • API Client Libraries
  • Integration Case Studies
  • TS eKYC/FA App
TrustVision API Documentation

Standard API

Authentication mechanism

We use AES encryption to encrypt user identify of client and send it to eKYC Platform.

How it works:

1. AES key base64

A pair of:

  • Key: 256 bits (32 bytes)

  • IV (initialization vector): 16 bytes

TrustVision team will provide an (key, iv) pair and client_code for each customers before integration.

2. Client encrypt the user identify to do eKYC journey.

  • Encrypt user identify use AES-256 CBC with padding PKCS7.
  • Encode the Base64 URL of the above encrypted value.
  • Concatenate encrypted value with client_code.
  • Encode Base64 URL of the above-concatenated value.
  • Use the encoded value to send it to the eKYC Platform.

eg.

  1. Use Web or WebView via link
    Philippines: https://ekyc-platform-ph-staging.trustingsocial.com/lu/[ENCODED_VALUE]
    Vietnam: https://ekyc-platform-vn-staging.trustingsocial.com/lu/[ENCODED_VALUE]
    India: https://ekyc-platform-in-staging.trustingsocial.com/lu/[ENCODED_VALUE]
  2. Pass [ENCODED_VALUE] to init iOS/Android/Flutter/ReactNative SDK.

Pseudo code:

UserID    = "user_id"    // client-generated value
KeyBytes  = Base64StdDecode(aesKey) // Base64 Standard Decoding
IVBytes   = Base64StdDecode(aesIV)  // Base64 Standard Decoding
// Step 1
EncryptedUserID    = AES256CbcPkcs7PaddingEncrypt(UserID, KeyBytes, IVBytes)
// Step 2
EncodedBase64EncryptedValue = Base64UrlEncode(EncryptedUserID)
// Step 3
UniqueToken        = KeyID + ":" + EncryptedUserID
// Step 4
EncodedBase64Token = Base64UrlEncode(UniqueToken)  // Base64 URL Encoding
URL                = "https://ekyc-platform-ph-staging.trustingsocial.com/lu/" + EncodedBase64

Sample code:

Reference:

go
package main

import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/base64"
    "fmt"

    "github.com/zenazn/pkcs7pad"
)

func main() {

    key := "YOUR_KEY"
    iv := "YOUR_IV"
    keyID := "YOUR_KEY_ID"
    url := "YOUR_URL"

    keyBytes, err := base64.StdEncoding.DecodeString(key)
    if err != nil {
        panic(err)
    }

    ivBytes, err := base64.StdEncoding.DecodeString(iv)
    if err != nil {
        panic(err)
    }

    block, err := aes.NewCipher(keyBytes)
    if err != nil {
        panic(err)
    }

    userID := "PLiOA_EdK3xx1M4sJPsOlQZqgX"
    // Step 1: Padding userID and encrypt
    contentPadding := pkcs7pad.Pad([]byte(userID), block.BlockSize())
    encryptedValue := make([]byte, len(contentPadding))
    blockMode := cipher.NewCBCEncrypter(block, ivBytes)
    blockMode.CryptBlocks(encryptedValue, contentPadding)

    // Step 2: Encode encrypted value to base64
    encodedBase64EncryptedValue := base64.RawURLEncoding.EncodeToString(encryptedValue)
    // Step 3: Generate unique token
    uniqueToken := keyID + ":" + encodedBase64EncryptedValue
    // Step 4: Encode unique token to base64
    encodedBase64Token := base64.RawURLEncoding.EncodeToString([]byte(uniqueToken))
    fmt.Println(url + "/" + encodedBase64Token)
}

Portal API

API Authentication mechanism

1. Request

MethodPathContent-TypeRequest Body
POST/auth/users/loginapplication/json{"user_name":"user_name","password":"password"}

2. Response

NameDescriptionStatus codeResponse Body
SuccessLogin successfully200{"data":{"access_token":"<JWT>"},"message":"login success","time":"2024-10-31T07:34:52Z","verdict":"success"}
Bad RequestInvalid username pattern400{"data":{"invalid_parameters":["user_name"],"parameter_formats":{"user_name":"[regex: ^[a-z0-9_]{1,63}$]"}},"message":"some parameters has invalid format","time":"2024-11-06T03:30:42Z","verdict":"invalid_parameters"}
UnauthorizedIncorrent username or password401{"data":{},"message":"username or password is incorrect","time":"2024-10-31T07:50:22Z","verdict":"invalid_credential"}
Invalid MethodInvalid URL or method405{"data":{},"message":"method is not correct for the requested route","time":"2024-11-06T03:23:26Z","verdict":"invalid_method"}
Too many requestsToo many failed login attempts429{"data":{},"message":"too many failed login attempts","time":"2024-11-06T03:33:43Z","verdict":"limit_exceeded"}
Internal Server ErrorInternal Server Error500{"data":{},"message":"Unexpected error. Error ID: ff4d5572d9df4560bb6dabc2eadd5a1e","time":"2024-11-06T03:32:09Z","verdict":"failure"}

API Application Detail

1. Request

MethodPathContent-TypeRequest Body
GET/portal/application/detail

Headers:

Header keyHeader ValueDescription
AuthorizationBearer <JWT>Include the JWT access token to support request authentication

Query Params:

Parameter keyDescription
application_idcorressponding with the application_id in the callback result
idcorressponding with the application_user_id in the callback result

2. Response

NameDescriptionStatus codeResponse Body
Successrequest successfully200See the sample success response below
Bad RequestInvalid parameters400{"data":{},"message":"","verdict":"invalid_parameters"}
UnauthorizedInvalid authentication token401{"data":{},"message":"authorization header is missing","time":"2024-10-31T07:50:22Z","verdict":"missing_authorization"}
Not foundNot found404{{"data":{},"message":"applications not available","time":"2024-10-31T08:27:27Z","verdict":"record_not_found"}
Invalid MethodInvalid URL or method405{"data":{},"message":"method is not correct for the requested route","time":"2024-11-06T03:23:26Z","verdict":"invalid_method"}
Too many requestsToo many failed login attempts429{"data":{},"message":"too many failed login attempts","time":"2024-11-06T03:33:43Z","verdict":"limit_exceeded"}
Internal Server ErrorInternal Server Error500{"data":{},"message":"Unexpected error. Error ID: ff4d5572d9df4560bb6dabc2eadd5a1e","time":"2024-11-06T03:32:09Z","verdict":"failure"}

On success case: 200 OK

JSON Response

json
{
  "data": {
    "verdict": "pending|approve|review|reject",
    "application_id": 10,
    "application_unique_token": "ad083945-9620-486c-be7d-c3f5dab870a1",
    "application_user_id": "01234567889",
    "file_ids": {
      "gesture_images": [
        {
          "gesture": "frontal",
          "image_id": "fa9a4fee-41c3-4988-a126-1431c130aa94"
        },
        {
          "gesture": "frontal",
          "image_id": "3b02828e-1d99-4bfc-9b9c-8aec102a315d"
        }
      ],
      "id_back_img_uuid": "93cef1cd-2782-4264-9c65-cce78ce3f549",
      "id_front_img_uuid": "8fdcb17e-5d41-4814-8d4f-8c1bfb51df20",
      "liveness_transformed_video_id": "b5a23e55-773f-4cf2-985b-835b9b3d0077",
      "qr1_img_uuid": "",
      "selfie_image_uuid": "3b02828e-1d99-4bfc-9b9c-8aec102a315d",
      "sequence_frames": [
        {
          "file_id": "4591fd8b-578f-422f-92d4-3e54a66837d5",
          "file_size": 480965
        },
        {
          "file_id": "32e870ca-816f-46c0-b303-98bb89173843",
          "file_size": 486082
        },
        {
          "file_id": "078765c1-9e55-4740-a0fe-60b05ed2f348",
          "file_size": 487386
        },
        {
          "file_id": "5e129fb2-8c41-4e23-959b-958e607092c7",
          "file_size": 146095
        }
      ]
    },
    "ekyc_face": {
      "compare_score": 0.699894,
      "compare_status": "matched",
      "liveness_score": 0.99999946,
      "liveness_status": "success",
      "process_status": "success",
      "processed_at": "2024-09-26T18:11:54+07:00",
      "sanity_check_result": "good",
      "sanity_check_score": 1,
      "sanity_check_status": "success",
      "search_face_result": {
        "faces": [
          {
            "id_number": "3129326470849810",
            "image_id": "7db53bf6-2b20-45d0-a2c3-eaf63b142d9e",
            "metadata": {
              "phone_number": "",
              "unique_token": "UiZW2HrO"
            },
            "score": 0.86089295
          }
        ],
        "response": {
          "faces": [
            [
              {
                "id": "95e4db8d-448c-4a64-8799-b9701b08358c",
                "image_id": "7db53bf6-2b20-45d0-a2c3-eaf63b142d9e",
                "metadata": [
                  {
                    "confidence_score": 0,
                    "confidence_verdict": "",
                    "field": "national_id",
                    "value": "3129326470849810"
                  },
                  {
                    "confidence_score": 0,
                    "confidence_verdict": "",
                    "field": "phone_number",
                    "value": ""
                  },
                  {
                    "confidence_score": 0,
                    "confidence_verdict": "",
                    "field": "unique_token",
                    "value": "UiZW2HrO"
                  }
                ],
                "score": 0.86089295
              }
            ]
          ],
          "request_id": "3cf7723d-f13b-49a0-95f8-7e2e5f8f62fa",
          "status": "success"
        }
      },
      "search_face_status": "found"
    },
    "ekyc_ocr": {
      "card_info": {
        "card_info": [
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "crn",
            "value": "0123456789"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "last_name",
            "value": "SANTOS"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "first_name",
            "value": "JOSE"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "middle_name",
            "value": "CRUZ"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "date_of_birth",
            "value": "1990/01/01"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "gender",
            "value": "F"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "address",
            "value": "CABAROAN SAN ESTEBAN ILOCOS SUR PHL 2706"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "id",
            "value": "0123456789"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "card_type",
            "value": "ph.ump"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "card_label",
            "value": "ph.ump.front"
          },
          {
            "confidence_score": 0,
            "confidence_verdict": "",
            "field": "name",
            "value": "JOSE CRUZ SANTOS"
          }
        ],
        "converted_card_info": {
          "address": "CABAROAN SAN ESTEBAN ILOCOS SUR PHL 2706",
          "birth_date": "1990/01/01",
          "card_label": "ph.ump.front",
          "card_type": "ph.ump",
          "gender": "F",
          "id_number": "0123456789",
          "name": "JOSE CRUZ SANTOS"
        }
      },
      "process_status": "success",
      "processed_at": "2024-09-26T18:11:29+07:00",
      "sanity_check_result": "good",
      "sanity_check_score": 1,
      "sanity_check_status": "success",
      "search_face_result": null,
      "search_face_status": "disabled"
    },
    "form_data": {
      "contactInfo": {
        "familyAddress": "CABAROAN SAN ESTEBAN ILOCOS SUR PHL 2706"
      },
      "personalInfo": {
        "birthday": "1990/01/01",
        "fullName": "JOSE CRUZ SANTOS",
        "gender": "",
        "idCard": "0123456789"
      }
    },
    "id_tampering": {
      "score": 1,
      "verdict": "good"
    },
    "time": "2024-09-27T09:50:32+07:00"
  }
}

Which verdict response mapping:

verdictDescription
pendingThe user has not completed the flow
approveOur recommendation to approve this application
reviewOur recommendation to review this application
rejectOur recommendation to reject this application

Which file_ids response mapping:

keyDescription
id_front_img_uuidThe image id of front side
id_back_img_uuidThe image id of back side
qr1_img_uuidThe image id of QR code
selfie_image_uuidThe image id of selfie that use to compare faces
gesture_imagesList images during user do liveness
sequence_framesList frames video during user do liveness
liveness_transformed_video_idThe video id merge from sequence frames

Which form_data response object:

json
{
  "contactInfo": {
    "familyAddress": "CABAROAN SAN ESTEBAN ILOCOS SUR PHL 2706"
  },
  "personalInfo": {
    "birthday": "1990/01/01",
    "fullName": "JOSE CRUZ SANTOS",
    "gender": "",
    "idCard": "0123456789"
  }
}

API Download file

1. Request

MethodPathContent-TypeRequest Body
GET/portal/document/download_ekyc_file

Headers:

Header keyHeader ValueDescription
AuthorizationBearer <JWT>Include the JWT access token to support request authentication

Query Params:

Parameter keyDescription
application_idcorressponding with the application_id in the callback result
idcorressponding with the file_ids in the callback result

2. Response

NameDescriptionStatus codeResponse Body
Successrequest successfully200See the sample success response below
Bad RequestInvalid parameters400{"data":{},"message":"","verdict":"invalid_parameters"}
UnauthorizedInvalid authentication token401{"data":{},"message":"authorization header is missing","time":"2024-10-31T07:50:22Z","verdict":"missing_authorization"}
Not foundNot found404{{"data":{},"message":"applications not available","time":"2024-10-31T08:27:27Z","verdict":"record_not_found"}
Invalid MethodInvalid URL or method405{"data":{},"message":"method is not correct for the requested route","time":"2024-11-06T03:23:26Z","verdict":"invalid_method"}
Too many requestsToo many failed login attempts429{"data":{},"message":"too many failed login attempts","time":"2024-11-06T03:33:43Z","verdict":"limit_exceeded"}
Internal Server ErrorInternal Server Error500{"data":{},"message":"Unexpected error. Error ID: ff4d5572d9df4560bb6dabc2eadd5a1e","time":"2024-11-06T03:32:09Z","verdict":"failure"}

On success case: the HTTP status code will be 200, and server will send the file as binary content.

API Index Faces

1. Request

MethodPathContent-Type
POST/portal/ekyc/index_facesapplication/json

Headers:

Header keyHeader ValueDescription
AuthorizationBearer <JWT>Include the JWT access token to support request authentication

Body:

JSON
{
    "image_base64": string,
    "collection": string,
    "label": string,
    "metadata": JSON
}

Where

keytyperequireddescription
image_base64stringyesencode base64 of binary image without prefix eg. data:image/jpeg;base64,
labelstringyeslabel of the image as described at Label table
metadatajsonyesmore information of image. eg client_uid, phone_number, dob, name ... client_uid should be not empty
collectionstringnoindex faces to this collection. case-sensitive

Which each metadata's parameters contains:

keytyperequireddescription
client_uidstringyesID of an user or application or any unique token
national_idstringnoid number of ID Card of an user
unique_tokenstringnothe token application_unique_token from application detail

2. Response

NameDescriptionStatus codeResponse Body
Successrequest successfully200See the sample success response below
Bad RequestInvalid parameters400{"data":{},"message":"","verdict":"invalid_parameters"}
UnauthorizedInvalid authentication token401{"data":{},"message":"authorization header is missing","time":"2024-10-31T07:50:22Z","verdict":"missing_authorization"}
Not foundNot found404{{"data":{},"message":"applications not available","time":"2024-10-31T08:27:27Z","verdict":"record_not_found"}
Invalid MethodInvalid URL or method405{"data":{},"message":"method is not correct for the requested route","time":"2024-11-06T03:23:26Z","verdict":"invalid_method"}
Too many requestsToo many failed login attempts429{"data":{},"message":"too many failed login attempts","time":"2024-11-06T03:33:43Z","verdict":"limit_exceeded"}
Internal Server ErrorInternal Server Error500{"data":{},"message":"Unexpected error. Error ID: ff4d5572d9df4560bb6dabc2eadd5a1e","time":"2024-11-06T03:32:09Z","verdict":"failure"}

On success case: the HTTP status code will be 200, and server will send the file as binary content.