ID Card · Standard API · eKYC Core

Read ID card info

POST/v1/read_id_card_info_sync

Reads one or two ID card images and returns the text parsed from the card, together with where the card sits inside each image.

Request

MethodPOST
Path/v1/read_id_card_info_sync
Content-Typeapplication/json
Auth requiredYes — HMAC signing

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.

NameTypeRequiredDescription
card_typestringRequiredtype of identity card, described at Card type table
image1ImageDataRequiredimage of the identity card's front side or back side (incase image2 empty)
image2ImageDataOptionalimage of the identity card's back side
qr1_imagesList of ImageDataOptionalimages of the QR code on the card's front side
qr2_imagesList of ImageDataOptionalimages of the QR code on the card's back side
qr1_videos[]videoOptionalarray of video recording QR code when capture ID Chip frontside on SDK.

Which each video's parameters contains:

NameTypeRequiredDescription
idstringOptionalID of video is returned from API Upload
metadatastring_jsonOptionalkey-value string, key should be string, value should be string, int, float, bool. Example "{\"id\":\"123456789\",\"type\":1}"
frames[]FrameDataOptionallist of video frames to be uploaded

Which FrameData's parameters contains:

NameTypeRequiredDescription
base64stringOptionalbase64 encoded text of image data
labelstringOptionallabel of the image as described at Label table
indexintOptionalthe index of this frame in the video
  • If you use base64, label and metadata, omit parameter id.
  • If you use id (result id is returned from Upload Image API), omit parameter base64, label and metadata.

The ImageData shape — id, base64, label and metadata — is defined once on Common objects.

JSON
{
    "card_type": string,
    "image1": {
        "id": string,
        "base64": string,
        "label": string,
        "metadata": string_json,
    },
    "image2": {
        "id": string,
        "base64": string,
        "label": string,
        "metadata": string_json,
    },
    "qr1_images": [{
        "id": string,
        "base64": string,
        "label": string,
        "metadata": string_json,
    }],
    "qr2_images": [{
        "id": string,
        "base64": string,
        "label": string,
        "metadata": string_json,
    }],
    "qr1_videos": [
            {
                "id": string,
                "metadata": string_json,
                "frames": [
                    {
                        "base64": string,
                        "label": string,
                        "index": int,
                    },
                    {
                        "base64": string,
                        "label": string,
                        "index": int,
                    },
                    // other frames
                ],
            },
            {
                "id": string,
                "metadata": string_json,
                "frames": [
                    {
                        "base64": string,
                        "label": string,
                        "index": int,
                    },
                    {
                        "base64": string,
                        "label": string,
                        "index": int,
                    },
                    // other frames
                ],
            }
       ],
}

Sample request

curl -X POST \
https://tv-staging.trustingsocial.com/api/v1/read_id_card_info_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 \
'
{
    "card_type": "vn.national_id",
    "image1": {
        "id": "7db00808-0416-45cf-a5cb-3b6dfbd7bb74"
    },
    "image2": {
        "id": "a4facba3-334b-41fb-97e3-4766cb70ae29"
    }
}
'

Response

data.card_information carries the merged and normalized information from the QR and OCR of both image1 and image2, and each image also comes back with the corner coordinates of the card found inside it. The data.status is either "success" or "failure" depending on whether the request has been successfully processed or not.

JavaScript
{
    "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,
                "face_image_id": string, // the extracted image from Secure QR, it's available for India only
            }
            "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
                ]
            },
            "mrz": {
                "parsed": [ // list of parsed information from mrz
                    {
                        "field": string, // id no, name, dateOfBirth,...
                        "value": string,
                    },
                    ... // other fields
                ],
                "raw": [ // list of raw OCR text boxes of MRZ's area
                    {
                        "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
                "face_image_id": string, // the extracted image from Secure QR, it's available for India only
            }
            "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
                ]
            },
            "mrz": {
                "parsed": [ // list of parsed information from mrz
                    {
                        "field": string, // id no, name, dateOfBirth,...
                        "value": string,
                    },
                    ... // other fields
                ],
                "raw": [ // list of raw OCR text boxes of MRZ's area
                    {
                        "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
        ],
        "request_id": string // return request id to the client and can use request-id to check logs.
    },
    "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
    ]
}

A read of the front of a Vietnamese chip ID card comes back like this:

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"
  }
}

Failure codes

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

Error codeDescriptionSupported countries
nocard_or_multicard_imagethe input image is no cardall
grayscale_cardthe input image is grayscaleindia
bad_quality_card_imagethe input image has bad qualityindia
incorrect_card_typethe input image is not same type with selected cardindia
incorrect_card_sidethe input card side is incorrectindia

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.
404image_not_found_exceptionThe image ID is not found in DB.
404request_not_found_exceptionThe request ID is not found when polling result by id
408request_timeout_exceptionRequest takes too long to process
429rate_limit_exceptionThe number of requests exceeded your throughput limit.
500internal_server_errorSome unexpected error occurs while processing the request

The codes above are the ones documented for this endpoint. Response errors on the Overview lists the codes for the eKYC Core surface as a whole — the two lists do not match on every endpoint.