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

Customized API

List of APIs

Mix Compare faces between 2 images

1. Request

Client should call this API:

methodURLcontent-type
POST/v1/mix_compare_faces_syncapplication/json

Body:

go
{
    "image1": {
        "id": string,
        "base64": string,
        "label": string,
        "metadata": json,
    },
    "image2": {
        "id": string,
        "base64": string,
        "label": string,
        "metadata": json,
    }
}

Where:

keytyperequireddescription
image1ImageDatayesimage of the identity card's front side
image2ImageDatayesimage of the selfie

Which each image's parameters contains:

keytyperequireddescription
idstringnoID of them image in DB
base64stringnoBase64 encoded text of image data
labelstringnolabel of the image
metadatadictionarynoany key-value metadata to save with the image, both key and value should be string

Note:

  • If you use base64, label and metadata (label and metadata of the image as described at Upload Image API), omit parameter id.
  • If you use id (result id is returned from Upload Image API), omit parameter base64, label and metadata.

Clients can provide image data to the TrustVision API by specifying the ID the image by using upload API, or by sending the image data as base64-encoded text.

Authentication mechanism is described in Authentication.

Sample Request

bash
curl -X POST \
https://tv-staging.trustingsocial.com/api/v1/mix_compare_faces_sync \
-H 'Authorization: TV <YOUR ACCESS KEY>:<CREATED SIGNATURE>' \
-H 'X-TV-Timestamp: 2019-04-21T18:00:15+07:00' \
-H 'Content-Type: application/json' \
-d \
'
{
    "image1": {
        "id": "7db00808-0416-45cf-a5cb-3b6dfbd7bb74"
    },
    "image2": {
        "id": "a4facba3-334b-41fb-97e3-4766cb70ae29"
    }
}
'

2. Response

The response will be a JSON with following format:

go
{
    "data": {
        "status": string, // "success" or "failure"
        "transaction_id": string, // optional
        "image1": {
            "id": string,
            "transformed_image_id": string // optional, just in case the image is transformed
            "faces": [
                {
                    "id": string, // id of the face in image1
                    "bounding_box": {
                        "top": int, // the top edge of the box
                        "right": int, // the right edge of the box
                        "bottom": int, // the bottom edge of the box
                        "left": int, // the left edge of the box
                        "angle": int // the angle at which the box is rotated
                    }
                },
                ... // other faces in image1
            ],
        },
        "image2": {
            "id": string,
            "transformed_image_id": string // optional, just in case the image is transformed
            "faces": [
                {
                    "id": string, // id of the face in image2
                    "bounding_box": {
                        "top": int, // the top edge of the box
                        "right": int, // the right edge of the box
                        "bottom": int, // the bottom edge of the box
                        "left": int, // the left edge of the box
                        "angle": int // the angle at which the box is rotated
                    }
                },
                ... // other faces in image2
            ],
        },
        "compare_faces": [
            {
                "face1_id": string, // id of the face in image1
                "face2_id": string, // id of the face in image2
                "score": float, // how likely that face1 and face2 are matched (0-1)
                "result": string // "matched", "unmatched", "unsure"
            },
            ... // other pair of faces in image1 and image2
        ],
        "portrait_sanity": { // only return the first issue found if any
            "verdict": string, // good, image_too_blur, image_too_dark, image_too_bright, not_white_background, not_qualified, image_has_multiple_faces, image_has_no_faces, right, left, "open_eye,closed_eye", "closed_eye,open_eye", "open_eye,sunglasses", "sunglasses,open_eye", "closed_eye,closed_eye", "closed_eye,sunglasses", "sunglasses,closed_eye", "sunglasses,sunglasses"
            "score": float, // range 0-1, how much confidence about the verdict
        },
        "card_sanity": { // only return the first issue found if any
            "verdict": string, // good, image_too_blur, image_too_dark, image_too_bright, image_has_hole, image_has_cut, image_has_hole_and_cut
            "score": float, // range 0-1, how much confidence about the verdict
        },
        "liveness_check": {
            "is_live": bool, // the face is live or not
            "score": float // how likely that the face is live (0-1)
        },
    },
    "errors": [
        {
            "code": string,
            "message": string,
            "detail": {
                "field": string, // optional, which parameter is invalid.
                ... // any other information that can be useful for client
            },
        },
        ... // other errors
    ]
}

In case the request processing has been finished, the HTTP status code will be 200, and the data.status is either "success" or "failure" depending on whether the request has been successfully processed or not.

If the data.status is "failure", the "errors" field will tell you why it failed.

error codedescription
image_has_no_facesthe input image has no faces

In case of any other errors, the data field will be empty, and the server sends one of following HTTP status code with error code:

HTTP codeerror codedescription
401access_denied_exceptionYou are not authorized to perform the action.
400invalid_parameter_exceptionInput parameter violates a constraint.
400request_time_too_skewedThe X-TV-Timestamp header is expired, need a newer one.
404request_not_found_exceptionThe request ID is not found in Memory Cache and DB.
429rate_limit_exceptionThe number of requests exceeded your throughput limit.
500internal_server_errorSome unexpected error occurs while processing the request

Sample Response

JSON
{
    "data": {
        "status": "success",
        "compare_faces": [
            {
                "face1_id": "abdba678-b680-4b62-bc4b-d9b8fb37e8e4",
                "face2_id": "d43bf504-f1a3-4799-9bda-e5709ae7aa69",
                "result": "matched",
                "score": 0.7381135644418032
            },
            {
                "face1_id": "ae7a6cd2-4f5b-45b3-955f-844b1bc6d95a",
                "face2_id": "d43bf504-f1a3-4799-9bda-e5709ae7aa69",
                "result": "unmatched",
                "score": 0.5098310116475188
            }
        ],
        "image1": {
            "faces": [
                {
                    "bounding_box": {
                        "angle": 0,
                        "bottom": 446,
                        "left": 357,
                        "right": 550,
                        "top": 172
                    },
                    "id": "abdba678-b680-4b62-bc4b-d9b8fb37e8e4"
                },
                {
                    "bounding_box": {
                        "angle": 0,
                        "bottom": 530,
                        "left": 57,
                        "right": 254,
                        "top": 263
                    },
                    "id": "ae7a6cd2-4f5b-45b3-955f-844b1bc6d95a"
                }
            ],
            "id": "f3f6f8b5-2ac0-4734-a4b5-836c6c300b0b",
            "transformed_image_id": ""
        },
        "image2": {
            "faces": [
                {
                    "bounding_box": {
                        "angle": 0,
                        "bottom": 369,
                        "left": 504,
                        "right": 559,
                        "top": 296
                    },
                    "id": "d43bf504-f1a3-4799-9bda-e5709ae7aa69"
                }
            ],
            "id": "639058a6-0631-4bfd-a718-bc72c2695daf",
            "transformed_image_id": ""
        },
        "portrait_sanity": {
            "score": 1,
            "verdict": "good"
        },
        "card_sanity": {
            "score": 1,
            "verdict": "good"
        },
        "liveness_check": {
            "is_live": true,
            "score": 0.9999999862517992
        }
    }
}

Read ID card info with sanity

The read id card api or ocr (optical character recognition) takes image_id as the input. Main function of this service is to extract text from supported legal documents. It also detects the location of the id card inside the uploaded image.

1. Request

Client should call this API:

methodURLcontent-type
POST/v1/read_id_card_info_with_sanityapplication/json

Body:

go
{
    "card_type": string
    "image1": {
        "id": string,
        "base64": string,
        "label": string,
        "metadata": json,
    },
    "image2": {
        "id": string,
        "base64": string,
        "label": string,
        "metadata": json,
    },
    "qr1_images": [{
        "id": string,
        "base64": string,
        "label": string,
        "metadata": json,
    }],
    "qr2_images": [{
        "id": string,
        "base64": string,
        "label": string,
        "metadata": json,
    }]
}

Where:

keytyperequireddescription
card_typestringyestype of identity card
image1ImageDatayesimage of the identity card's front side
image2ImageDatanoimage of the identity card's back side
qr1_imagesList of ImageDatanoimages of the QR code on the card's front side
qr2_imagesList of ImageDatanoimages of the QR code on the card's back side

card_type should be one of following values:

card_typedescription
in.aadhaarIndia Aadhaar card
in.panIndia PAN card
in.voterIndia voter card
in.passportIndia passport
in.national_idAny of India national ID versions
vn.national_idAny of Vietnam national ID versions

Which each image's parameters contains:

keytyperequireddescription
idstringnoID of them image in DB
base64stringnoBase64 encoded text of image data
labelstringnolabel of the image
metadatadictionarynoany key-value metadata to save with the image, both key and value should be string

Note:

  • If you use base64, label and metadata (label and metadata of the image as described at Upload Image API), omit parameter id.
  • If you use id (result id is returned from Upload Image API), omit parameter base64, label and metadata.

Clients can provide image data to the TrustVision API by specifying the ID the image by using upload API, or by sending the image data as base64-encoded text.

Authentication mechanism is described in Authentication.

Sample Request

bash
curl -X POST \
https://tv-staging.trustingsocial.com/api/v1/read_id_card_info_with_sanity \
-H 'Authorization: TV <YOUR ACCESS KEY>:<CREATED SIGNATURE>' \
-H 'X-TV-Timestamp: 2019-04-21T18:00:15+07:00' \
-H 'Content-Type: application/json' \
-d \
'
{
    "card_type": "vn.national_id",
    "image1": {
        "id": "7db00808-0416-45cf-a5cb-3b6dfbd7bb74"
    },
    "image2": {
        "id": "a4facba3-334b-41fb-97e3-4766cb70ae29"
    }
}
'

2. Response

The response will be a JSON with following format:

go
{
    "data": {
        "request_id": string, // ID of the request
        "status": string, // "success" or "failure"
        "image1": {
            "id": string,
            "transformed_image_id": string, // optional, just in case the image is transformed
            "card_box": {
                "top_left": { "x": float, "y": float },
                "top_right": { "x": float, "y": float },
                "bottom_left": { "x": float, "y": float },
                "bottom_right": { "x": float, "y": float },
            },
            "qr": {
                "parsed": [ // list of parsed information from QR code
                    {
                        "field": string, // uid, name, dateOfBirth, careOf, ...
                        "value": string,
                    },
                    ... // other fields
                ],
                "raw": string, // raw XML string decoded from QR code
            }
            "ocr": {
                "parsed": [ // list of parsed information from OCR
                    {
                        "field": string, // uid, name, dateOfBirth, careOf, ...
                        "value": string,
                    },
                    ... // other fields
                ],
                "raw": [ // list of raw OCR text boxes
                    {
                        "text": string, // detected text
                        "bounding_box": [
                            {
                                "x": float,
                                "y": float,
                            },
                            {
                                "x": float,
                                "y": float,
                            },
                            {
                                "x": float,
                                "y": float,
                            },
                            {
                                "x": float,
                                "y": float,
                            }
                        ],
                        "label": string, // label of the box
                        "line": int,
                        "group": int,
                    },
                    ... // other text boxes
                ]
            },
        },
        "image2": {
            "id": string,
            "transformed_image_id": string, // optional, just in case the image is transformed
            "card_box": {
                "top_left": { "x": float, "y": float },
                "top_right": { "x": float, "y": float },
                "bottom_left": { "x": float, "y": float },
                "bottom_right": { "x": float, "y": float },
            },
            "qr": {
                "parsed": [ // list of parsed information from QR code
                    {
                        "field": string, // uid, name, dateOfBirth, careOf, ...
                        "value": string,
                    },
                    ... // other fields
                ],
                "raw": string, // raw XML string decoded from QR code
            }
            "ocr": {
                "parsed": [ // list of parsed information from OCR
                    {
                        "field": string, // uid, name, dateOfBirth, careOf, ...
                        "value": string,
                    },
                    ... // other fields
                ],
                "raw": [ // list of raw OCR text boxes
                    {
                        "text": string, // detected text
                        "bounding_box": [
                            {
                                "x": float,
                                "y": float,
                            },
                            {
                                "x": float,
                                "y": float,
                            },
                            {
                                "x": float,
                                "y": float,
                            },
                            {
                                "x": float,
                                "y": float,
                            }
                        ],
                        "label": string, // label of the box
                        "line": int,
                        "group": int,
                    },
                    ... // other text boxes
                ]
            },
        },
        "card_information": [ // merged and normalized information from QR and OCR of both image1 and image2
            {
                "field": string, // field name ("identity_number", "full_name", "first_name, "middle_name", "last_name", "birth_date", "address_level_1_(city)", "address_level_1_(city)_code",...)
                "value": string, // value of the field ("123456789", "Sohit Gour", "1998-06-23")
                "confidence_verdict": string, // verdict of value ("SURE", "UNSURE", ""), empty mean Not Available. This field is shown if client enable 'enable_evaluate_confidence'
                "confidence_score": float, // confidence score of predict value. This field is shown if client enable 'enable_evaluate_confidence'
            },
            ... // other pair of card information
        ]
    },
    "errors": [
        {
            "code": string, // "unexpected_error", "image_too_dark", "image_too_bright", ...
            "message": string, // message to clarify the error code
            "detail": {
                ... // any information to help trace and debug
            }
        },
        ... // other errors
    ]
}

The data.status is either "success" or "failure" depending on whether the request has been successfully processed or not.

If the data.status is "failure", the "errors" field will tell you why it failed.

error codedescription
incorrect_card_typethe input image is not same type with selected card
nocard_or_multicard_imagethe input image is no card or multicard detected
image_too_blurthe input image is too blur
image_too_darkthe input image is too dark
image_too_brightthe input image is too bright (glare)
image_has_holethe input image has hole
image_has_cutthe input image has cut
image_has_hole_and_cutthe input image has hole and cut
bad_quality_card_imagethe input image is bad quality

In case of any other errors, the data field will be empty, and the server sends one of following HTTP status code with error code:

HTTP codeerror codedescription
401access_denied_exceptionYou are not authorized to perform the action.
400invalid_parameter_exceptionInput parameter violates a constraint.
400request_time_too_skewedThe X-TV-Timestamp header is expired, need a newer one.
404request_not_found_exceptionThe request ID is not found in Memory Cache and DB.
429rate_limit_exceptionThe number of requests exceeded your throughput limit.
500internal_server_errorSome unexpected error occurs while processing the request

Sample Response

JSON
{
  "data": {
    "card_information": [
      {
        "confidence_score": 1,
        "confidence_verdict": "SURE",
        "digit_confidence_scores": [
          1,
          1,
          1,
          1,
          1,
          1,
          1,
          1,
          1,
          1,
          1,
          1
        ],
        "field": "id",
        "value": "012345678910"
      },
      {
        "confidence_score": 1,
        "confidence_verdict": "SURE",
        "field": "name",
        "value": "NGUYỄN VĂN A"
      },
      {
        "confidence_score": 1,
        "confidence_verdict": "SURE",
        "field": "dob",
        "value": "01/01/2001"
      },
      {
        "confidence_score": 1,
        "confidence_verdict": "SURE",
        "field": "gender",
        "value": "NAM"
      },
      {
        "confidence_score": 1,
        "confidence_verdict": "SURE",
        "field": "address",
        "value": "132 HÀM NGHI, PHƯỜNG BẾN THÀNH, QUẬN 1, TP.HỒ CHÍ MINH"
      },
      {
        "confidence_score": 1,
        "confidence_verdict": "SURE",
        "field": "expiry_date",
        "value": "01/01/2026"
      },
      {
        "confidence_score": 1,
        "confidence_verdict": "SURE",
        "field": "issue_date",
        "value": "25/07/2022"
      },
      ...,
      {
        "field": "card_type",
        "value": "vn.cccd_new"
      },
      {
        "field": "card_label",
        "value": "vn.cccd_new.front"
      },
      {
        "field": "nationality",
        "value": "VIỆT NAM"
      }
    ],
    "image1": {
      "card_box": {
        "bottom_left": {
          "x": 108.75621096603572,
          "y": 532.4366315092892
        },
        "bottom_right": {
          "x": 808.5273808091879,
          "y": 518.4647938594222
        },
        "top_left": {
          "x": 119.84309555403888,
          "y": 122.66592678334564
        },
        "top_right": {
          "x": 785.999680519104,
          "y": 111.78477731919848
        }
      },
      "id": "8c72e2b0-b0d9-4c4d-bb76-5ca6262af103",
      "mrz": {
        "parsed": null,
        "raw": null
      },
      "nfc": {
        "parsed": null,
        "raw": null
      },
      "ocr": {
        "parsed": [
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "digit_confidence_scores": [
              1,
              1,
              1,
              1,
              1,
              1,
              1,
              1,
              1,
              1,
              1,
              1
            ],
            "field": "id",
            "value": "012345678910"
          },
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "name",
            "value": "NGUYỄN VĂN A"
          },
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "dob",
            "value": "01/01/2001"
          },
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "gender",
            "value": "NAM"
          },
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "address",
            "value": "132 HÀM NGHI, PHƯỜNG BẾN THÀNH, QUẬN 1, TP.HỒ CHÍ MINH"
          },
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "expiry_date",
            "value": "01/01/2026"
          },
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "issue_date",
            "value": "25/07/2022"
          },
          ...
        ],
        "raw": [
          {
            "bounding_box": [
              {
                "x": 281.2383117675781,
                "y": 166.15625
              },
              {
                "x": 518.7890625,
                "y": 166.15625
              },
              {
                "x": 518.7890625,
                "y": 198.109375
              },
              {
                "x": 281.2383117675781,
                "y": 198.109375
              }
            ],
            "char_probs": [
              -0.000690460205078125,
              -0.0007172819459810853,
              -0.0007648453465662897,
              -0.0007659182301722467,
              -0.0007841570768505335,
              -0.0008823807002045214,
              -0.0008858377696014941,
              -0.0008965665474534035,
              -0.0009963397169485688,
              -0.0009986046934500337,
              -0.000998962321318686,
              -0.0010205389698967338,
              -0.001036274479702115,
              -0.001036274479702115
            ],
            "entropy": 0.004665346350520849,
            "group": 0,
            "label": 1,
            "line": 0,
            "text": "012345678910"
          },
          ...
        ]
      },
      "qr": {
        "parsed": [
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "id",
            "value": "012345678910"
          },
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "id_1",
            "value": ""
          },
          {
            "confidence_score": 1,
            "confidence_verdict": "SURE",
            "field": "name",
            "value": "NGUYỄN VĂN A"
          },
          ...
        ],
        "raw": "012345678910||NGUYỄN VĂN A|01012001|Nam|132 Hàm Nghi, Phường Bến Thành, Quận 1, TP.Hồ Chí Minh|25072022"
      },
      "transformed_image_id": "0133973f-e0ea-43e1-97fe-6377eff3a4ff"
    },
    "image2": null,
    "status": "success"
  }
}