Skip to main content

👤🪪 Face and ID Card Verification for KYC

👤🪪 AI เปรียบเทียบใบจากรูป Selfie และ รูปบัตรประชาชน สำหรับงาน KYC

Version Status Production Production Production Legacy Legacy Legacy Legacy

Try Demo

Visit our API Portal to test the Face and ID Card Verification for KYC API with your own images.

Try Demo!

Selfie Example Images (Click to try)

Example 1

ID Card Example Images (Click to try)

Example 1

Getting Started

Face and ID Card Verification for KYC is an AI-powered service that compares a selfie photo with an ID card photo to verify identity for KYC (Know Your Customer) purposes.

Example

The service takes two inputs:

  1. ID card picture (Large picture)
  2. Selfie picture of ID card holder (Small picture)

It then analyzes and authenticates whether both pictures show the same person.

Features & Capabilities

Core Features

  • Face matching between selfie and ID card photo
  • High accuracy verification
  • Fast processing within 0.1 second
  • No data retention after processing (GDPR compliant)

Supported Fields

  • Image formats: JPG, JPEG, PNG, GIF
  • Image dimensions: 600px width x 400px height
  • Maximum file size: 10MB per image

Example

Face and ID card Verification For KYC Request

Image Preview

Image 1Image 2
    curl --location 'https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification' \
--header 'apikey: {{{YOUR API KEY}}}' \
--form 'file0=@"image1.png"' \
--form 'file1=@"image2.png"'

Face and ID card Verification For KYC Response

{
"idcard": { "confidence": 66.872, "isSamePerson": "true" },
"selfie": { "confidence": 86.04, "isSamePerson": "true" },
"time_process": 0.824,
"total": { "confidence": 76.456, "isSamePerson": "true" }
}

API Endpoints

EndpointMethodDescriptionCost
POST /v3/internal/ekyc/face-and-id-card-verification/v2
Legacy: /api/v2/ekyc
POSTFace + ID Verification1 IC per request
POST /v3/store/ekyc/face-and-id-card-verification
Legacy: /face-verify-id2
POSTFace + ID Verification1 IC per request
POST /v3/store/ekyc/face-and-id-card-verification/front
Legacy: /thai-national-id-card/v3/front/kyc
POSTFace and ID Card Verification for KYC (Front)1 IC per page
POST /v3/store/ekyc/face-and-id-card-verification/back
Legacy: /thai-national-id-card/v3/back/kyc
POSTFace and ID Card Verification for KYC (Back)1 IC per page

API Reference

Face and ID Card Verification Endpoints

1. Face + ID Verification (V2 API)

POST /v3/store/ekyc/face-and-id-card-verification/v2

Verifies if a selfie matches an ID card photo using the V2 API endpoint.


2. Face + ID Verification

POST /v3/store/ekyc/face-and-id-card-verification

Verifies if a selfie matches an ID card photo.


3. Face and ID Card Verification for KYC (Front)

POST /v3/store/ekyc/face-and-id-card-verification/kyc-front

Processes the front side of Thai National ID Card for KYC verification.


4. Face and ID Card Verification for KYC (Back)

POST /v3/store/ekyc/face-and-id-card-verification/kyc-back

Processes the back side of Thai National ID Card for KYC verification.


Request Parameters

NameTypeLocationRequiredDescription
apikeyStringheaderYesAPI authentication key
file0FilebodyYesID card image file
file1FilebodyYesSelfie image file

Responses

StatusDescription
200Successful verification response

API Error Message

Common Error Messages

Status CodeStatus MessageDescription
404no route matched with those values.No route matched with this URL. Please verify again.
405the method is not allowed for the requested URL.The method is not allowed for the requested URL.
413file is too large, more than 10 MB.The size of file is too large more than 10 MB.
415file extension is not allowed.The file extension is not allowed for this URL.

Specific Error Messages of Client

Status CodeStatus MessageDescription
420parameter not found in request. [file0, file1]The parameter not found in this request. Please enter parameter in request.
421(face, id card, face on id card) not found in image. [file0, file1]The id card or face not found in this image for API.
422face on (id card, selfie) not found in image. [file0, file1]The face on id card or selfie not found in image.
441too many images.Too many images in the parameter.
442image error, unsupported format.The format of image is not allowed.
461no file attached.No file attached.

Code Example

Python

import requests

url = "https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification"

payload = {}
files=[
('file0',('{IMAGE FILE 1}',open('{IMAGE FILE PATH 1}','rb'),'image/png')),
('file1',('{IMAGE FILE 2}',open('{IMAGE FILE PATH 2}','rb'),'image/png'))
]
headers = {
'apikey': '{YOUR API KEY}'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)

JavaScript

const axios = require("axios")
const FormData = require("form-data")
const fs = require("fs")
let data = new FormData()
data.append("file0", fs.createReadStream("{IMAGE FILE PATH 1}"))
data.append("file1", fs.createReadStream("{IMAGE FILE PATH 2}"))

let config = {
method: "post",
maxBodyLength: Infinity,
url: "https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification",
headers: {
apikey: "{YOUR API KEY}",
...data.getHeaders(),
},
data: data,
}

axios
.request(config)
.then((response) => {
console.log(JSON.stringify(response.data))
})
.catch((error) => {
console.log(error)
})

PHP

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('file0'=> new CURLFILE('{IMAGE FILE PATH 1}'),'file1'=> new CURLFILE('{IMAGE FILE PATH 2}')),
CURLOPT_HTTPHEADER => array(
'apikey: {YOUR API KEY}'
),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

Swift

let parameters = [
[
"key": "file0",
"src": "{IMAGE FILE PATH 1}",
"type": "file"
],
[
"key": "file1",
"src": "{IMAGE FILE PATH 2}",
"type": "file"
]] as [[String: Any]]

let boundary = "Boundary-\(UUID().uuidString)"
var body = Data()
var error: Error? = nil
for param in parameters {
if param["disabled"] != nil { continue }
let paramName = param["key"]!
body += Data("--\(boundary)\r\n".utf8)
body += Data("Content-Disposition:form-data; name=\"\(paramName)\"".utf8)
if param["contentType"] != nil {
body += Data("\r\nContent-Type: \(param["contentType"] as! String)".utf8)
}
let paramType = param["type"] as! String
if paramType == "text" {
let paramValue = param["value"] as! String
body += Data("\r\n\r\n\(paramValue)\r\n".utf8)
} else {
let paramSrc = param["src"] as! String
let fileURL = URL(fileURLWithPath: paramSrc)
if let fileContent = try? Data(contentsOf: fileURL) {
body += Data("; filename=\"\(paramSrc)\"\r\n".utf8)
body += Data("Content-Type: \"content-type header\"\r\n".utf8)
body += Data("\r\n".utf8)
body += fileContent
body += Data("\r\n".utf8)
}
}
}
body += Data("--\(boundary)--\r\n".utf8);
let postData = body


var request = URLRequest(url: URL(string: "https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification")!,timeoutInterval: Double.infinity)
request.addValue("{YOUR API KEY}", forHTTPHeaderField: "apikey")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

request.httpMethod = "POST"
request.httpBody = postData

let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
return
}
print(String(data: data, encoding: .utf8)!)
}

task.resume()

Kotlin

val client = OkHttpClient()
val mediaType = "text/plain".toMediaType()
val body = MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file0","{IMAGE FILE 1}",
File("{IMAGE FILE PATH 1}").asRequestBody("application/octet-stream".toMediaType()))
.addFormDataPart("file1","{IMAGE FILE 2}",
File("{IMAGE FILE PATH 2}").asRequestBody("application/octet-stream".toMediaType()))
.build()
val request = Request.Builder()
.url("https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification")
.post(body)
.addHeader("apikey", "{YOUR API KEY}")
.build()
val response = client.newCall(request).execute()

Java

OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file0","{IMAGE FILE 1}",
RequestBody.create(MediaType.parse("application/octet-stream"),
new File("{IMAGE FILE PATH 1}")))
.addFormDataPart("file1","{IMAGE FILE 2}",
RequestBody.create(MediaType.parse("application/octet-stream"),
new File("{IMAGE FILE PATH 2}")))
.build();
Request request = new Request.Builder()
.url("https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification")
.method("POST", body)
.addHeader("apikey", "{YOUR API KEY}")
.build();
Response response = client.newCall(request).execute();

Dart

var headers = {
'apikey': '{YOUR API KEY}'
};
var request = http.MultipartRequest('POST', Uri.parse('https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification'));
request.files.add(await http.MultipartFile.fromPath('file0', '{IMAGE FILE PATH 1}'));
request.files.add(await http.MultipartFile.fromPath('file1', '{IMAGE FILE PATH 2}'));
request.headers.addAll(headers);

http.StreamedResponse response = await request.send();

if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}

Accuracy and Performance

  • False Rejection Rate (FRR < 3%)
  • False Acceptance Rate (FAR < 0.1%)

Code Examples

Curl

curl -X POST https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification \
-H "apikey: YOUR_API_KEY" \
-F "file=@/path/to/face.jpg"

Python

import requests

url = "https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification"
files = {"file": ("("/path/to/face.jpg", "rb"))}
headers = {"apikey": "YOUR_API_KEY"}

response = requests.post(url, headers=headers, files=files)
print(response.json())

JavaScript

const axios = require("axios");
const FormData = require("form-data");
const fs = require("fs");

let data = new FormData();
data.append("file", fs.createReadStream("/path/to/face.jpg"));

let config = {
method: "post",
url: "https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification",
headers: {
apikey: "YOUR_API_KEY",
...data.getHeaders(),
},
data: data,
};

axios(config)
.then((response) => console.log(response.data))
.catch((error) => console.log(error));

PHP

<?php
$curl = curl_init();

curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => array(
'file'=> new CURLFILE('/path/to/face.jpg')
),
CURLOPT_HTTPHEADER => array(
'apikey: YOUR_API_KEY'
),
));

$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>

Swift

import Foundation

let url = URL(string: "https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("YOUR_API_KEY", forHTTPHeaderField: "apikey")

let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

var body = Data()
body.append("--\(boundary)\r\n".data(using: .utf8)!)
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"file.jpg\"\r\n".data(using: .utf8)!)
body.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)

if let fileData = try? Data(contentsOf: URL(fileURLWithPath: "/path/to/face.jpg")) {
body.append(fileData)
}
body.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)

request.httpBody = body

let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
print(String(data: data, encoding: .utf8)!)
}
}
task.resume()

Kotlin

import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File

val client = OkHttpClient()

val file = File("/path/to/face.jpg")
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.name, file.asRequestBody("image/jpeg".toMediaTypeOrNull()))
.build()

val request = Request.Builder()
.url("https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification")
.addHeader("apikey", "YOUR_API_KEY")
.post(requestBody)
.build()

client.newCall(request).execute().use { response ->
println(response.body?.string())
}

Java

import okhttp3.*;
import java.io.File;

OkHttpClient client = new OkHttpClient();

File file = new File("/path/to/face.jpg");

RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("image/jpeg"), file))
.build();

Request request = new Request.Builder()
.url("https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification")
.addHeader("apikey", "YOUR_API_KEY")
.post(requestBody)
.build();

try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}

Dart

import 'package:http/http.dart' as http;

var request = http.MultipartRequest(
'POST',
Uri.parse('https://api.iapp.co.th/v3/store/ekyc/face-and-id-card-verification')
);

request.files.add(await http.MultipartFile.fromPath(
'file',
'/path/to/face.jpg'
));

request.headers.addAll({
'apikey': 'YOUR_API_KEY'
});

var response = await request.send();
var responseBody = await response.stream.bytesToString();
print(responseBody);

Pricing

OperationProduction PathLegacy PathIC CostUnitOn-Premise
Face + ID Verification (V2 API)/v3/store/ekyc/face-and-id-card-verification/v2/api/v2/ekyc1 ICper 1 requestContact us
Face + ID Verification/v3/store/ekyc/face-and-id-card-verification/face-verify-id21 ICper 1 request
Face and ID Card Verification for KYC (Front)/v3/store/ekyc/face-and-id-card-verification/kyc-front/thai-national-id-card/v3/front/kyc1 ICper 1 page
Face and ID Card Verification for KYC (Back)/v3/store/ekyc/face-and-id-card-verification/kyc-back/thai-national-id-card/v3/back/kyc1 ICper 1 page