API Usage Guide¶
The IDLive® eKYC Toolkit provides a set of flexible API methods that support the implementation of key scenarios in eKYC systems.
Below is a detailed description of all methods, including their purpose, parameters, and expected responses.
You can also use the OpenAPI Specification available at http://host:port/v3/api-docs to explore the API or generate client libraries.
Tools like Postman or Swagger UI can be used to interact with the API; Swagger UI is accessible at http://host:port/swagger-ui/index.html.
Identity Check¶
POST /check
The POST /check
endpoint is a core part of the IDLive® eKYC Toolkit.
It performs identity verification by analyzing a user's selfie and a photograph of their identity document.
Depending on the parameters specified in the request, this method can perform a combination of the following checks:
- Face Presentation Attack Detection: Validates that the selfie was captured from a live person, detecting fraudulent attempts such as printed photos or screen replays.
- Document Presentation Attack Detection: Ensures that the document image was captured from a genuine physical document and not a reproduction or display.
- Deepfake Detection: Detects AI-generated synthetic faces in selfie images that attempt to impersonate a real person.
- Injection Attack Detection: Ensures that the image was captured securely and not tampered with.
- Face Matching: Compares the face in the selfie with the face on the identity document to confirm that both belong to the same person.
- Face Search: Searches the faces from the selfie and the document in a database to detect duplicates.
Query Parameters
Name | Type | Required | Default | Description |
---|---|---|---|---|
encrypted | boolean | No | true | Should be set to true if payload is encrypted, false if not. |
Request Body
Content-Type: multipart/form-data
Form Fields
Parameter | Type | Required | Description |
---|---|---|---|
checkModel | JSON | Yes | Configuration object specifying which checks to run. |
face | binary | No | Face image payload. |
doc | binary | No | Document image payload. |
{
"operations": ["FACE_CHECK", "DOC_CHECK", "FACE_MATCH_VALIDATION", "FACE_MATCH_SEARCH"],
"face_check_parameters": {
"domain": "GENERAL",
"pipelines": [
{"type": "PRESENTATION_ATTACK"},
{"type": "DEEPFAKE_ATTACK"},
{"type": "INJECTION_ATTACK"}
]
},
"document_check_parameters": {
"pipelines": [
{"type": "SCREEN_REPLAY_ATTACK"},
{"type": "PRINTED_COPY_ATTACK"},
{"type": "PORTRAIT_SUBSTITUTION_ATTACK"}
]
},
"face_search_parameters": {
"collections": ["default-collection"],
"limit": 5,
"max_faces": 1
}
}
Field | Type | Required | Description |
---|---|---|---|
operations | string[] | Yes | List of checks to perform. Possible values: FACE_CHECK , DOC_CHECK , FACE_MATCH_VALIDATION , FACE_MATCH_SEARCH . |
face_check_parameters | object | No | Settings for face checks. |
document_check_parameters | object | No | Settings for document checks. |
face_search_parameters | object | No | Settings for face search. |
[
"FACE_CHECK",
"DOC_CHECK",
"FACE_MATCH_VALIDATION",
"FACE_MATCH_SEARCH"
]
Operation | Description |
---|---|
FACE_CHECK | Performs analysis of the selfie image, including Presentation Attack, Deepfake, and Injection detection. |
DOC_CHECK | Performs analysis of the document photo to detect Screen Replay, Printed Copy, Portrait Substitution, and Digital Manipulation Attacks. |
FACE_MATCH_VALIDATION | Compares the face from the selfie to the face on the document. |
FACE_MATCH_SEARCH | Searches the faces from the selfie and the document in a database to detect duplicates. |
{
"domain": "GENERAL",
"pipelines": [
{
"type": "PRESENTATION_ATTACK",
"pipeline": "optional_pipeline_id",
"calibration": "REGULAR"
}
]
}
Field | Type | Required | Description |
---|---|---|---|
domain | string | No | Domain for face checks. Possible values: GENERAL , DESKTOP . |
pipelines | object[] | No | List of face checks to perform. Each item is an object described below. |
→ type | string | Yes | Type of check to perform. Supported values: PRESENTATION_ATTACK , DEEPFAKE_ATTACK , INJECTION_ATTACK . |
→ pipeline | string | No | Pipeline name to use for the check. If not set, default pipeline is used. |
→ calibration | string | No | Adjusting a system's balance between false acceptance and false rejection rates. Possible values: REGULAR (default), SOFT , HARD . |
{
"pipelines": [
{
"type": "SCREEN_REPLAY_ATTACK",
"pipeline": "optional_pipeline_id",
"calibration": "REGULAR"
}
]
}
Field | Type | Required | Description |
---|---|---|---|
pipelines | object[] | No | List of document checks to perform. Each item is an object described below. |
→ type | string | Yes | Type of check to perform. Supported values: SCREEN_REPLAY_ATTACK , PRINTED_COPY_ATTACK , PORTRAIT_SUBSTITUTION_ATTACK , DIGITAL_MANIPULATION_ATTACK . |
→ pipeline | string | No | Pipeline name to use for the check. If not set, default pipeline is used. |
→ calibration | string | No | Adjusting a system's balance between false acceptance and false rejection rates. Possible values: REGULAR (default), SOFT , HARD . |
{
"collections": ["default-collection"],
"limit": 5,
"max_faces": 1
}
Field | Type | Required | Description |
---|---|---|---|
collections | string[] | Yes | List of collection names to search in. |
limit | integer | No | Number of matching results to return. Default is 5. |
max_faces | integer | No | Maximum allowed number of faces in the image. If more faces are detected, an error will be returned. Default is 1. |
Response: 200 OK
Returns a JSON object with result sections corresponding to the requested operations in checkModel.operations
. Each section reflects the outcome of a specific check and includes either a success result or an error description.
{
"face_result": { ... },
"doc_result": { ... },
"face_validation_result": { ... },
"face_search_result": { ... }
}
Each section is described in detail in the sections below: face_result
, doc_result
, face_validation_result
, face_search_result
.
face_result
Returned when FACE_CHECK
is requested. Contains a results
array, where each entry corresponds to a specific check. The fields of each check are described below.
{
"results": [
{
"type": "PRESENTATION_ATTACK",
"pipeline": "pad-r-1",
"calibration": "REGULAR",
"probability": 0.95255303,
"quality": 0.9972526,
"status_code": "OK"
},
{
"type": "DEEPFAKE_ATTACK",
"pipeline": "dfd-1",
"calibration": "REGULAR",
"probability": 0.9324415,
"quality": 0.9972526,
"status_code": "OK"
},
{
"type": "INJECTION_ATTACK",
"probability": 1.0,
"status_code": "OK"
}
]
}
{
"results": [
{
"type": "PRESENTATION_ATTACK",
"pipeline": "pad-r-1",
"calibration": "REGULAR",
"error": "Failed to detect face",
"status_code": "FACE_NOT_FOUND"
},
{
"type": "DEEPFAKE_ATTACK",
"pipeline": "dfd-1",
"calibration": "REGULAR",
"error": "Failed to detect face",
"status_code": "FACE_NOT_FOUND"
},
{
"type": "INJECTION_ATTACK",
"error": "Bad Request",
"status_code": "FACE_NOT_FOUND"
}
]
}
Field | Type | Description |
---|---|---|
type | string | Check type. Supported values: PRESENTATION_ATTACK , DEEPFAKE_ATTACK , INJECTION_ATTACK . |
pipeline | string | Pipeline name used for the check. |
calibration | string | Calibration used. Supported values: REGULAR , SOFT , HARD . |
probability | number | It ranges from 0 (spoofed) to 1 (live). Threshold: 0.5. |
quality | number | Deprecated. |
status_code | string | Code indicating the result of the check. See explanation below. |
status_code
indicates the result of the check. Possible values:
OK
– the check was successfully completed and aprobability
value was returned.ERROR
– an internal error occurred during the check.- Validation error codes (e.g.,
FACE_NOT_FOUND
,FACE_TOO_SMALL
, etc.) – indicate why the image was rejected. You can find the complete list here.
doc_result
Returned when DOC_CHECK
is requested. Contains a results
array, where each entry corresponds to a specific check. The fields of each check are described below.
{
"results": [
{
"type": "SCREEN_REPLAY_ATTACK",
"pipeline": "default-sr",
"calibration": "REGULAR",
"probability": 0.0,
"quality_warnings": [],
"status_code": "OK"
},
{
"type": "PORTRAIT_SUBSTITUTION_ATTACK",
"pipeline": "default-ps",
"calibration": "REGULAR",
"probability": 0.830956,
"quality_warnings": [],
"status_code": "OK"
},
{
"type": "PRINTED_COPY_ATTACK",
"pipeline": "default-pc",
"calibration": "REGULAR",
"probability": 0.0,
"quality_warnings": [],
"status_code": "OK"
},
{
"type": "DIGITAL_MANIPULATION_ATTACK",
"pipeline": "default-dm",
"calibration": "REGULAR",
"probability": 0.1597147,
"quality_warnings": [],
"status_code": "OK"
}
]
}
{
"results": [
{
"type": "SCREEN_REPLAY_ATTACK",
"pipeline": "default-sr",
"calibration": "REGULAR",
"status_code": "DOCUMENT_NOT_FOUND"
},
{
"type": "PORTRAIT_SUBSTITUTION_ATTACK",
"pipeline": "default-ps",
"calibration": "REGULAR",
"status_code": "DOCUMENT_NOT_FOUND"
},
{
"type": "PRINTED_COPY_ATTACK",
"pipeline": "default-pc",
"calibration": "REGULAR",
"status_code": "DOCUMENT_CROPPED"
},
{
"type": "DIGITAL_MANIPULATION_ATTACK",
"pipeline": "default-dm",
"calibration": "REGULAR",
"status_code": "DOCUMENT_NOT_FOUND"
}
]
}
Field | Type | Description |
---|---|---|
type | string | Check type. Supported values: SCREEN_REPLAY_ATTACK , PRINTED_COPY_ATTACK , PORTRAIT_SUBSTITUTION_ATTACK , DIGITAL_MANIPULATION_ATTACK . |
pipeline | string | Pipeline name used for the check. |
calibration | string | Calibration used. Supported values: REGULAR , SOFT , HARD . |
probability | number | It ranges from 0 (spoofed) to 1 (live). Threshold: 0.5. |
quality_warnings | string[] | Image quality warnings. |
status_code | string | Code indicating the result of the check. See explanation below. |
status_code
indicates the result of the check. Possible values:
OK
– the check was successfully completed and aprobability
value was returned.ERROR
– an internal error occurred during the check.- Validation error codes (
DOCUMENT_NOT_FOUND
,DOCUMENT_PHOTO_NOT_FOUND
,DOCUMENT_CROPPED
) – indicate why the image was rejected. You can find the complete list here.
face_validation_result
Returned when FACE_MATCH_VALIDATION
is requested. Contains the result of comparing the face in the selfie with the face on the identity document. The fields of the result are described below.
{
"probability": 0.0048826,
"status_code": "OK"
}
{
"error": "Failed to detect face",
"status_code": "ERROR"
}
Field | Type | Description |
---|---|---|
probability | number | It ranges from 0 (different identities) to 1 (same identity). Threshold: 0.5. |
error | string | Error description. |
status_code | string | Code indicating the result of the face validation. See explanation below. |
status_code
indicates the result of the check. Possible values:
OK
– the validation was successfully completed and aprobability
value was returned.ERROR
– an internal error occurred during the check.
face_search_result
Returned when FACE_MATCH_SEARCH
is requested. Contains a results
array, where each entry represents a search performed using a specific face source (FACE
or DOCUMENT
). Each entry refers to the target collection and may contain a list of matched records with their probability
scores, the image source, and the status of the search. The fields of each search result are described below.
{
"results": [
{
"collection": "ekyc",
"results": [
{
"record_id": "16d33ecb-da91-4f39-afe5-46a8c846e40e",
"probability": 0.99999964
},
{
"record_id": "1395c0d0-186b-493e-87b1-cfcad9b42e83",
"probability": 0.56999912
}
],
"image_source": "FACE",
"status_code": "OK"
},
{
"collection": "ekyc",
"results": [
{
"record_id": "86094151-2e46-421e-969c-07bae1924c0b",
"probability": 0.9748826463
},
{
"record_id": "69be6f40-123b-459f-8230-893aa74230f8",
"probability": 0.0048826463
}
],
"image_source": "DOCUMENT",
"status_code": "OK"
}
]
}
{
"results": [
{
"collection": "ekyc",
"error": "Collection does not exist",
"image_source": "FACE",
"status_code": "ERROR"
},
{
"collection": "ekyc",
"error": "Collection does not exist",
"image_source": "DOCUMENT",
"status_code": "ERROR"
}
]
}
Field | Type | Description |
---|---|---|
collection | string | Name of the collection used for the search. |
image_source | string | Source of the face used for the search. Possible values: FACE (from selfie) or DOCUMENT (from ID photo). |
error | string | Error description. |
status_code | string | Code indicating the result of the face search. See explanation below. |
results | object[] | List of matched results, each with a record_id and probability . |
→ record_id | string | Identifier of the matched record in the collection. |
→ probability | number | It ranges from 0 (different identities) to 1 (same identity). Threshold: 0.9. |
status_code
indicates the result of the search. Possible values:
OK
– the search was successfully completed.ERROR
– an internal error occurred during the check.
Response: 400 Bad Request
Returned if request structure is invalid or a processing error occurs.
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X 'POST' \
'http://localhost:8080/check' \
-H 'accept: application/json' \
-H 'Content-Type: multipart/form-data' \
-F 'checkModel={"operations":["FACE_CHECK","DOC_CHECK","FACE_MATCH_VALIDATION"]};type=application/json' \
-F 'face=@/path/to/face-encrypted-data' \
-F 'doc=@/path/to/doc-encrypted-data'
import requests, json
headers = {
'Accept': 'application/json'
}
check_model = {
'operations': ['FACE_CHECK', 'DOC_CHECK', 'FACE_MATCH_VALIDATION']
}
with open('/path/to/face-encrypted-data', 'rb') as face_file, \
open('/path/to/doc-encrypted-data', 'rb') as doc_file:
files = {
'checkModel': ('checkModel', json.dumps(check_model), 'application/json'),
'face': ('face', face_file, 'application/octet-stream'),
'doc': ('doc', doc_file, 'application/octet-stream')
}
response = requests.post(
'http://localhost:8080/check',
headers=headers,
files=files
)
Collections¶
Create Collection¶
POST /collections
Creates a new biometric collection.
Query Parameters
Name | Type | Required | Description |
---|---|---|---|
collection | string | Yes | Name of the collection. |
Response: 201 OK
Collection was created successfully.
Response: 400 Bad Request
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X POST "http://localhost:8080/collections?collection=collection-name"
import requests
params = {
'collection': collection_name
}
response = requests.post(
'http://localhost:8080/collections',
params=params
)
Delete Collection¶
DELETE /collections
Removes a biometric collection.
Query Parameters
Name | Type | Required | Description |
---|---|---|---|
collection | string | Yes | Name of the collection to remove. |
force | boolean | No | If true, forcibly deletes the collection. |
Response: 204 No Content
Collection removed successfully.
Response: 400 Bad Request
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X DELETE "http://localhost:8080/collections?collection=collection-name&force=true"
import requests
params = {
'collection': collection_name,
'force': True
}
response = requests.delete(
'http://localhost:8080/collections',
params=params
)
Remove Record From Collection¶
DELETE /collections/remove-record
Removes a specific record from a collection.
Query Parameters
Name | Type | Required | Description |
---|---|---|---|
collection | string | Yes | Collection name. |
recordId | string | Yes | Record ID to remove. |
Response: 204 No Content
Record removed successfully.
Response: 400 Bad Request
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X DELETE "http://localhost:8080/collections/remove-record?collection=collection-name&recordId=record-id"
import requests
params = {
'collection': collection_name,
'recordId': record_id
}
response = requests.delete(
'http://localhost:8080/collections/remove-record',
params=params
)
Face Matching¶
Generate Template¶
POST /generate-template
Generates a biometric matching template from a single image.
Query Parameters
Name | Type | Required | Description |
---|---|---|---|
encrypted | boolean | Yes | Should be set to true if payload is encrypted, false if not. |
Request Body
Content-Type: application/octet-stream
Binary payload (image data).
Response: 201 OK
{
"template": "base64-encoded-template-string"
}
Response: 400 Bad Request
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X POST "http://localhost:8080/generate-template?encrypted=true" \
-H "Content-Type: application/octet-stream" \
--data-binary "@/path/to/encrypted-image"
import requests
headers = {
'Content-Type': 'application/octet-stream'
}
params = {
'encrypted': True
}
with open('/path/to/encrypted-image', 'rb') as image:
response = requests.post(
'http://localhost:8080/generate-template',
headers=headers,
params=params,
data=image
)
Match Over Template¶
POST /match-over-template
Compares a face image against a previously generated biometric template.
Query Parameters
Name | Type | Required | Description |
---|---|---|---|
encrypted | boolean | Yes | Should be set to true if the payload is encrypted. |
Request Body
Content-Type: multipart/form-data
Field | Type | Required | Description |
---|---|---|---|
file | binary | Yes | Face image to match. |
template | string | Yes | Base64-encoded template to compare to. |
Response: 200 OK
{
"score": 0.85
}
Response: 400 Bad Request
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X POST "http://localhost:8080/match-over-template?encrypted=true" \
-F "file=@/path/to/encrypted-image" \
-F "template=<BASE64_TEMPLATE>"
import requests
files = {
'file': ('file', open('/path/to/encrypted-image', 'rb'), 'application/octet-stream'),
'template': ('template', <BASE64_TEMPLATE>, 'application/octet-stream')
}
params = {
'encrypted': True
}
response = requests.post(
'http://localhost:8080/match-over-template',
files=files,
params=params
)
Add Template to Collection¶
POST /add-template
Adds one or more templates to a collection in the biometric database.
Query Parameters
Name | Type | Required | Description |
---|---|---|---|
collection | string | Yes | Target collection name (must already exist). |
Request Body
Content-Type: application/json
{
"templates": ["base64-template-1", "base64-template-2"]
}
Response: 201 OK
{
"record_ids": ["generated-record-id-1", "generated-record-id-2"]
}
Response: 400 Bad Request
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X POST "http://localhost:8080/add-template?collection=default" \
-H "Content-Type: application/json" \
-d '{"templates":["<BASE64_TEMPLATE>"]}'
import requests
params = {
'collection': collection_name
}
data = {
'templates': ["<BASE64_TEMPLATE>"]
}
response = requests.post(
'http://localhost:8080/add-template',
params=params,
json=data
)
Add Image to Collection¶
POST /add-image
Generates templates from an image and stores them in the target collection.
Query Parameters
Name | Type | Required | Description |
---|---|---|---|
collection | string | Yes | Target collection name (must already exist). |
maxFaces | integer | No | Maximum allowed number of faces in the image. If more faces are detected, an error will be returned. Default is 1. |
encrypted | boolean | Yes | Should be set to true if the payload is encrypted. |
Request Body
Content-Type: application/octet-stream
Binary payload (image data).
Response: 201 OK
{
"record_ids": ["generated-record-id"]
}
Response: 400 Bad Request
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X POST "http://localhost:8080/add-image?collection=default&encrypted=true" \
-H "Content-Type: application/octet-stream" \
--data-binary "@/path/to/encrypted-image"
import requests
headers = {
'Content-Type': 'application/octet-stream'
}
params = {
'collection': collection_name,
'maxFaces': max_faces,
'encrypted': encrypted
}
with open('/path/to/encrypted-image', 'rb') as image:
response = requests.post(
'http://localhost:8080/add-image',
headers=headers,
params=params,
data=image
)
Utilities¶
Decrypt Payload¶
POST /decrypt
Decrypts a previously encrypted payload.
Request Body
Content-Type: application/octet-stream
Binary payload (encrypted data).
Response: 200 OK
Returns decrypted image data (Content-Type: image/jpeg
).
Response: 400 Bad Request
{
"status": 400,
"message": "Exception message"
}
Example Request
curl -X POST "http://localhost:8080/decrypt" \
-H "Content-Type: application/octet-stream" \
--data-binary "@/path/to/encrypted-image" \
-o "/path/to/decrypted-image.jpg"
import requests
headers = {
'Content-Type': 'application/octet-stream'
}
with open('/path/to/encrypted-image', 'rb') as encrypted_image:
response = requests.post(
'http://localhost:8080/decrypt',
headers=headers,
data=encrypted_image
)
with open('/path/to/decrypted-image.jpg', 'wb') as decrypted_image:
decrypted_image.write(response.content)