👤🪪 Face and ID Card Verification for KYC
👤🪪 AI เปรียบเทียบใบจากรูป Selfie และ รูปบัตรประชาชน สำหรับงาน KYC
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)

ID Card Example Images (Click to try)

Demo key is limited to 10 requests per day per IP
Click here to get your API key
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:
- ID card picture (Large picture)
- 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


curl --location 'https://api.iapp.co.th/face-verify-id2/facecheck' \
--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 Reference
Endpoint
POST
https://api.iapp.co.th/face-verify-id/facecheck
Request Parameters
Name | Type | Location | Required | Description |
---|---|---|---|---|
apikey | String | header | Yes | API authentication key |
file0 | File | body | Yes | ID card image file |
file1 | File | body | Yes | Selfie image file |
Responses
Status | Description |
---|---|
200 | Successful verification response |
API Error Message
Common Error Messages
Status Code | Status Message | Description |
---|---|---|
404 | no route matched with those values. | No route matched with this URL. Please verify again. |
405 | the method is not allowed for the requested URL. | The method is not allowed for the requested URL. |
413 | file is too large, more than 10 MB. | The size of file is too large more than 10 MB. |
415 | file extension is not allowed. | The file extension is not allowed for this URL. |
Specific Error Messages of Client
Status Code | Status Message | Description |
---|---|---|
420 | parameter 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. |
422 | face on (id card, selfie) not found in image. [file0, file1] | The face on id card or selfie not found in image. |
441 | too many images. | Too many images in the parameter. |
442 | image error, unsupported format. | The format of image is not allowed. |
461 | no file attached. | No file attached. |
Code Example
Python
import requests
url = "https://api.iapp.co.th/face-verify-id2/facecheck"
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/face-verify-id2/facecheck",
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/face-verify-id2/facecheck',
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/face-verify-id2/facecheck")!,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/face-verify-id2/facecheck")
.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/face-verify-id2/facecheck")
.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/face-verify-id2/facecheck'));
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%)
Pricing
AI API Service Name | Endpoint | IC Per Minute | On-Premise |
---|---|---|---|
Face and ID card Verification For KYC | iapp_face_verification_v1 | 1 IC/Minute | Contact |