Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The Liveness detection algorithm is intended to detect a real living person in a media.
You're authorized.
You have already created a folder and added your media marked by correct tags into this folder.
For API 4.0.8 and below, please note: the Liveness analysis works with videos and shotsets, images are ignored. If you want to analyze an image, upload it as a shotset (archive) with a single image and mark with the video_selfie_blank tag.
1. Initiate the analysis for the folder: POST /api/folders/{{folder_id}}/analyses/
If you want to use a webhook for response, add it to the payload at this step, as described .
You'll need analysis_id or folder_id from response.
2. If you use a webhook, just wait for it to return the information needed. Otherwise, initiate polling:
GET /api/analyses/{{analysis_id}} – for the analysis_id you have from the previous step.
GET api/folders/{{folder_id}}/analyses/ – for all analyses performed on media in the folder with the folder_id you have from the previous step.
Repeat the check until theresolution_status and resolution fields change status to any other except PROCESSING and treat this as a result.
{
"analyses": [
{
"type": "quality",
"source_media": ["1111aaaa-11aa-11aa-11aa-111111aaaaaa"], // optional; omit to include all media from the folder
...
}
]
}Action shot is a frame from a video where the user performs a gesture, e.g., closed eyes for blinking. A separate frame is saved for each gesture.
API – 5.3.1,
Web SDK – 1.6.15,
Web UI – 1.3.4,
Mobile SDK (iOS, Android, Flutter) – 8.14.
In the , set extract_action_shot to True.
Add the extract_action_shot parameter with the true value to params (iOS) / analysisParams (Android) of the Analysis structure when running the analysis.
In the API response (API 6.6.1 and newer): analyses[].results_media[].output_images[]. Action shot has original_name = ResultImageActionShot.jpeg.
In the report: a frame for each gesture. Generate the report via Web UI (the PDF button in the order) or API (POST /api/folders/{{folder_id}}/reports/).
Analysis.init(media: results,
type: .quality,
mode: .serverBased,
params: ["extract_best_shot" : true, "extract_action_shot": true])val analysisParams = mapOf(
"extract_best_shot" to true,
"extract_action_shot" to true
)
AnalysisScenario.Liveness
-> addAnalysis(
Analysis(
Analysis.Type.QUALITY,
analysisMode,
media,
analysisParams,
sizeReductionStrategy
)
)Please find the Flutter repository here.
Add the lines below to pubspec.yaml of the project you want to add the plugin to.
For 8.22 or newer:
ozsdk: ^10.0.0For 8.21 and below:
ozsdk:
git:
url: https://gitlab.com/oz-forensics/oz-mobile-flutter-plugin.git
ref: '8.8.2'Add the license file (e.g., license.json or forensics.license) to the Flutter application/assets folder. In pubspec.yaml, specify the Flutter asset:
assets
- assets/license.json // please note that the license file name must match to the one placed in assetsFor Android, add the Oz repository to /android/build.gradle, allprojects → repositories section:
allprojects {
repositories {
google()
mavenCentral()
maven { url ‘https://ozforensics.jfrog.io/artifactory/main’ } // repository URL
}
}For Flutter 8.24.0 or newer or Android Gradle plugin 8.0.0 or newer, add to android/gradle.properties:
android.nonTransitiveRClass=falseThe minimum Android SDK (API Level) version should be 24 or higher:
defaultConfig {
...
minSDKVersion 24
...
}For iOS, set the minimum platform to 13 or higher in the Runner → Info → Deployment target → iOS Deployment Target.
In ios/Podfile, comment the use_frameworks! line (#use_frameworks!).
Initialize SDK by calling the init plugin method. Note that the license file name and path should match the ones specified in pubspec.yaml (e.g., assets/license.json).
Use the API credentials (login, password, and API URL) that you’ve received from us.
In production, instead of hard-coding the login and password inside the application, it is recommended to get the access token on your backend via the API auth method, then pass it to your application:
By default, logs are saved along with the analyses' data. If you need to keep the logs distinct from the analysis data, set up the separate connection for as shown below:
or
To start recording, use the startLiveness method to obtain the recorded media:
Please note: for versions 8.11 and below, the method name is executeLiveness, and it returns the recorded media.
To obtain the media result, subscribe to livenessResult as shown below:
To run the analyses, execute the code below.
Create the Analysis object:
Execute the formed analysis:
If you need to run an analysis for a particular folder, pass its ID:
The analysisResult list of objects contains the result of the analysis.
If you want to use media captured by another SDK, the code should look like this:
The whole code block will look like this:
The "Best shot" algorithm is intended to choose the most high-quality and well-tuned frame with a face from a video record. This algorithm works as a part of the analysis, so here, we describe only the best shot part. Starting with API v6.0.1, the best shot is extracted and returned in the API response by default unless disabled for a specific purpose.
1. Initiate the analysis similar to , but make sure that extract_best_shot is set to true as shown below, or this line is omitted (for API 6.0.1 and newer):
If you want to use a webhook for response, add it to the payload at this step, as described .
2. Check and interpret results in the same way as for the pure analysis.
3. The URL to the best shot is located in the analyses.results_media -> output_images -> original_url
Oz Mobile SDK stands for the Software Developer’s Kit of the Oz Forensics Liveness and Face Biometric System, providing seamless integration with customers’ mobile apps for login and biometric identification.
Liveness is checking that a person on a video is a real living person.
LivenessBiometry compares two or more faces from different media files and shows whether the faces belong to the same person or not.
Biometry (Face Matching)Best shot is an addition to the Liveness check. The system chooses the best frame from a video and saves it as a picture for later use.
Best ShotBlacklist checks whether a face on a photo or a video matches with one of the faces in the pre-created database.
Collection (1:N) CheckBoolean
If True, uses the main camera, otherwise the front one.
Parameter
Type
Description
actions
List<VerificationAction>
Actions from the captured video
use_main_camera
analyses.results_media -> output_images -> original_name = "ResultImage.jpg"This callback is called when the system encounters any error. It contains the error details and telemetry ID that you can use for further investigation.
on_error {
"code": "error_code",
"event_session_id": "id_of_telemetry_session_with_error",
"message": "<error decription>",
"context": {} // additional information if any
}
await OZSDK.initSDK([<% license path and license file name %>]);await OZSDK.setApiConnectionWithCredentials(<login>, <password>, <host>); await OZSDK.setApiConnectionWithToken(token, host);await OZSDK.setEventConnectionWithCredentials(<login>, <password>, <host>);await OZSDK.setEventConnectionWithToken(<token>, <host>);await OZSDK.startLiveness(<actions>, <use_main_camera>);class Screen extends StatefulWidget {
static const route = 'liveness';
const Screen({super.key});
@override
State<Screen> createState() => _ScreenState();
}
class _ScreenState extends State<Screen> {
late StreamSubscription<List<Media>> _subscription;
@override
void initState() {
super.initState();
// subscribe to liveness result
_subscription = OZSDK.livenessResult.listen(
(List<Media> medias) {
// media contains liveness media
},
onError: (Object error) {
// handle error, in most cases PlatformException
},
);
}
@override
Widget build(BuildContext context) {
// omitted to shorten the example
}
void _startLiveness() async {
// use startLiveness to start liveness screen
OZSDK.startLiveness(<list of actions>);
}
@override
void dispose() {
// cancel subscription
_subscription.cancel();
super.dispose();
}
}List<Analysis> analysis = [ Analysis(Type.quality, Mode.serverBased, <media>, {}), ];final analysisResult = await OZSDK.analyze(analysis, [], {});final analysisResult = await OZSDK.analyze(analysis, folderID, [], {});media = Media(FileTypedocumentPhoto, VerificationAction.oneShot, “photo_selfie”, null, <path to image>, null, null, “”)// replace VerificationAction.blank with your Liveness gesture if needed
final cameraMedia = await OZSDK.executeLiveness([VerificationAction.blank], use_main_camera);
final analysis = [
Analysis(Type.quality, Mode.serverBased, cameraMedia, {}),
];
final analysisResult = await OZSDK.analyze(analysis, [], {});// replace VerificationAction.blank with your Liveness gesture if needed
final cameraMedia = await OZSDK.executeLiveness([VerificationAction.blank], use_main_camera);
final biometryMedia = [...cameraMedia];
biometryMedia.add(
Media(
FileType.documentPhoto,
VerificationAction.blank,
MediaType.movement,
null,
<your reference image path>,
null,
null,
MediaTag.photoSelfie,
),
);
final analysis = [
Analysis(Type.quality, Mode.serverBased, cameraMedia, {}),
Analysis(Type.biometry, Mode.serverBased, biometryMedia, {}),
];
final analysisResult = await OZSDK.analyze(analysis, [], {});{
"analyses": [{
"type": "quality",
"source_media": ["1111aaaa-11aa-11aa-11aa-111111aaaaaa"], // // optional; omit to include all media from the folder
"params" : {
"extract_best_shot": true // the mandatory part for the best shot analysis
}
}]
}In this section, we explain how to use Oz Flutter SDK for iOS and Android.
Before you start, it is recommended that you install:
Flutter 3.0.0 or newer;
Android SDK (API Level) 24 or newer;
dart 2.18.6 or newer;
iOS platform 13 or newer;
Xcode.
Please find the Flutter repository .
Master license is the offline license that allows using Mobile SDKs with any bundle_id, unlike the regular licenses. To get a master license, create a pair of keys as shown below. Email us the public key, and we will email you the master license shortly after that.
Your application needs to sign its bundle_id with the private key, and the Mobile SDK checks the signature using the public key from the master license. Master licenses are time-limited.
This section describes the process of creating your private and public keys.
To create a private key, run the commands below one by one.
You will get these files:
Please note: this feature has been implemented in 8.1.0.
To add or update the language pack for Oz Android SDK, please follow these instructions:
Go to the folder for the locale needed, or create a new folder. Proceed to for the details.
Create the file called strings.xml.
How to compare a photo or video with ones from your database.
The collection check algorithm is designed to check the presence of a person using a database of preloaded photos. A video fragment and/or a photo can be used as a source for comparison.
You're .
You have already marked by correct tags into this folder.
To start using Oz iOS SDK, follow the steps below.
Embed Oz iOS SDK into your project as described .
Get a trial license for SDK on our or a production license by . We'll need your bundle id. Add the license to your project as described .
If you want to get back to the previous (up to 6.4.2) versions' design, reset the customization settings of the capture screen and apply the parameters that are listed below.
In this section, we listed the guides for the face matching checks.
This section contains the most common cases of integrating the Oz Forensics Liveness and face Biometry system.
The scenarios can be combined together, for example, integrating liveness into both web and mobile applications or integrating liveness with face matching.
How to Integrate Oz Liveness Using the Non-Persistent Oz API ModeHow to Integrate Oz Liveness into Your Web ApplicationHow to Integrate Oz Liveness into Your Mobile ApplicationHow to Perform a Face Matching AnalysisYou can also download Postman collections for Oz API. Please find them here.
Redefine the strings you need in the appropriate localization records.
A list of keys for Android:
The keys action_*_go refer to the appropriate gestures. Others refer to the hints for any gesture, info messages, or errors.
When new keys appear with new versions, if no translation is provided in your file, the new strings are shown in English.
// customization parameters for the toolbar
let toolbarCustomization = ToolbarCustomization(
closeButtonColor: .white,
backgroundColor: .black)
// customization parameters for the center hint
let centerHintCustomization = CenterHintCustomization(
verticalPosition: 70)
// customization parameters for the center hint animation
let hintAnimationCustomization = HintAnimationCustomization(
hideAnimation: true)
// customization parameters for the frame around the user face
let faceFrameCustomization = FaceFrameCustomization(
strokeWidth: 6,
strokeFaceAlignedColor: .green,
strokeFaceNotAlignedColor: .red)
// customization parameters for the background outside the frame
let backgroundCustomization = BackgroundCustomization(
backgroundColor: .clear)
OZSDK.customization = OZCustomization(toolbarCustomization: toolbarCustomization,
centerHintCustomization: centerHintCustomization,
hintAnimationCustomization: hintAnimationCustomization,
faceFrameCustomization: faceFrameCustomization,
versionCustomization: vesrionCustomization,
backgroundCustomization: backgroundCustomization)privateKey.txt is privateKey.der encoded by base64. This key containing will be used as the host app bundle_id signature.
The OpenSSL command specification: https://www.openssl.org/docs/man1.1.1/man1/openssl-pkcs8.html
To create a public key, run this command.
You will get the public key file: publicKey.pub. To get a license, please email us this file. We will email you the license.
SDK initialization:
Prior to the SDK initializing, create a base64-encoded signature for the host app bundle_id using the private key.
Signature creation example:
Pass the signature as the masterLicenseSignature parameter during the SDK initialization.
If the signature is invalid, the initialization continues as usual: the SDK checks the list of bundle_id included into the license, like it does it by default without a master license.
1. Initiate the analysis: POST/api/folders/{{folder_id}}/analyses/
If you want to use a webhook for response, add it to the payload at this step, as described here.
You'll need analysis_id or folder_id from response.
2. If you use a webhook, just wait for it to return the information needed. Otherwise, initiate polling:
GET /api/analyses/{{analysis_id}} – for the analysis_id you have from the previous step.
GET /api/folders/{{folder_id}} – for all analyses performed on media in the folder with the folder_id you have from the previous step.
Wait for the resolution_status and resolution fields to change the status to anything other than PROCESSING and treat this as a result.
If you want to know which person from your collection matched with the media you have uploaded, find the collection analysis in the response, check results_media, and retrieve person_id. This is the ID of the person who matched with the person in your media. To get the information about this person, use GET /api/collections/{{collection_id}}/persons/{{person_id}} with IDs of your collection and person.
openssl genpkey -algorithm RSA -outform DER -out privateKey.der -pkeyopt rsa_keygen_bits:2048
# for MacOS
base64 -i privateKey.der -o privateKey.txt
# for Linux
base64 -w 0 privateKey.der > privateKey.txtopenssl rsa -pubout -in privateKey.der -out publicKey.pubfun init(
context: Context,
licenseSources: List<LicenseSource>,
masterLicenseSignature: String,
statusListener: StatusListener<LicensePayload>? = null,
)private fun getMasterSignature(): String {
Security.insertProviderAt(org.spongycastle.jce.provider.BouncyCastleProvider(), 1)
val privateKeyBase64String = "the string copied from the privateKey.txt file"
// with key example:
// val privateKeyBase64String = "MIIEpAIBAAKCAQEAxnpv02nNR34uNS0yLRK1o7Za2hs4Rr0s1V1/e1JZpCaK8o5/3uGV+qiaTbKqU6x1tTrlXwE2BRzZJLLQdTfBL/rzqVLQC/n+kAmvsqtHMTUqKquSybSTY/zAxqHF3Fk59Cqisr/KQamPh2tmg3Gu61rr9gU1rOglnuqt7FioNMCMvjW7ciPv+jiawLxaPrzNiApLqHVN+xCFh6LLb4YlGRaNUXlOgnoLGWSQEsLwBZFkDJDSLTJheNVn9oa3PXg4OIlJIPlYVKzIDDcSTNKdzM6opkS5d+86yjI1aTKEH3Zs64+QoEuoDfXUxS3TOUFx8P+wfjOR5tYAT+7TRN4ocwIDAQABAoIBAATWJPV05ZCxbXTURh29D/oOToZ0FVn78CS+44Vgy1hprAcfG9SVkK8L/r6X9PiXAkNJTR+Uivly64Oua8//bNC7f8aHgxRXojFmWwayj8iOMBncFnad1N2h4hy1AnpNHlFp3I8Yh1g0RpAZOOVJFucbTxaup9Ev0wLdWyGgQ3ENmRXAyLU5iUDwUSXg59RCBFKcmsMT2GmmJt1BU4P3lL9KVyLBktqeDWR/l5K5y8pPo6K7m9NaOkynpZo+mHVoOTCtmTj5TC/MH9YRHlF15VxQgBbZXuBPxlYoQCsMDEcZlMBWNw3cNR6VBmGiwHIc/tzSHZVsbY0VRCYEbxhCBZkCgYEA+Uz0VYKnIWViQF2Na6LFuqlfljZlkOvdpU4puYTCdlfpKNT3txYzO0T00HHY9YG9k1AW78YxQwsopOXDCmCqMoRqlbn1SBe6v49pVB85fPYU2+L+lftpPlx6Wa0xcgzwOBZonHb4kvp1tWhUH+B5t27gnvRz/rx5jV2EfmWinycCgYEAy8/aklZcgoXWf93N/0EZcfzQo90LfftkKonpzEyxSzqCw7B9fHY68q/j9HoP4xgJXUKbx1Fa8Wccc0DSoXsSiQFrLhnT8pE2s1ZWvPaUqyT5iOZOW6R+giFSLPWEdwm6+BeFoPQQFHf8XH3Z2QoAepPrEPiDoGN1GSIXcCwoe9UCgYEAgoKj4uQsJJKT1ghj0bZ79xVWQigmEbE47qI1u7Zhq1yoZkTfjcykc2HNHBaNszEBks45w7qo7WU5GOJjsdobH6kst0eLvfsWO9STGoPiL6YQE3EJQHFGjmwRbUL7AK7/Tw2EJG0wApn150s/xxRYBAyasPxegTwgEj6j7xu7/78CgYEAxbkI52zG5I0o0fWBcf9ayx2j30SDcJ3gx+/xlBRW74986pGeu48LkwMWV8fO/9YCx6nl7JC9dHI+xIT/kk8OZUGuFBRUbP95nLPHBB0Hj50YRDqBjCBh5qaizSEGeGFFNIfFSKddri3U8nnZTNiKLGCx7E3bjE7QfCh5qoX8ZF0CgYAtsEPTNKWZKA23qTFI+XAg/cVZpbSjvbHDSE8QB6X8iaKJFXbmIC0LV5tQO/KT4sK8g40m2N9JWUnaryTiXClaUGU3KnSlBdkIA+I77VvMKMGSg+uf4OdfJvvcs4hZTqZRdTm3dez8rsUdiW1cX/iI/dJxF4964YIFR65wL+SoRg=="
val sig = Signature.getInstance("SHA512WithRSA")
val keySpec = PKCS8EncodedKeySpec(Base64.decode(privateKeyBase64String, Base64.DEFAULT))
val keyFactory = KeyFactory.getInstance("RSA")
sig.initSign(keyFactory.generatePrivate(keySpec))
sig.update(packageName.toByteArray(Charsets.UTF_8))
return Base64.encodeToString(sig.sign(), Base64.DEFAULT).replace("\n", "")
}{
"analyses": [{
"type": "collection",
"collection_id": "your_image_database_id",
"source_media": ["1111aaaa-11aa-11aa-11aa-111111aaaaaa"] // // optional; omit to include all media from the folder
}]
}Connect SDK to API as described here. This step is optional, as this connection is required only when you need to process data on a server.
Capture videos by creating the controller as described here. You'll send them for analysis afterwards.
Upload and analyze media you've taken at the previous step. The process of checking liveness and face biometry is described here.
If you want to customize the look-and-feel of Oz iOS SDK, please refer to this section.
Minimal iOS version: 12.
Minimal Xcode version: 16.
Available languages: EN, ES, HY, KK, KY, TR, PT-BR.
A sample app source code using the Oz Liveness SDK is located in the GitLab repository:
Follow the link below to see a list of SDK methods and properties:
Download the demo app latest build here.
To start using Oz Android SDK, follow the steps below.
Embed Oz Android SDK into your project as described here.
Connect SDK to API as described . This step is optional, as this connection is required only when you need to process data on a server.
Capture videos using methods described . You'll send them for analysis afterward.
Analyze media you've taken at the previous step. The process of checking liveness and face biometry is described .
If you want to customize the look-and-feel of Oz Android SDK, please refer to .
Recommended Android version: 7.0+ (API Level 24).
Recommended versions of components:
We do not support emulators.
Available languages: EN, ES, HY, KK, KY, TR, PT-BR.
To obtain the sample apps source code for the Oz Liveness SDK, proceed to the GitLab repository:
Follow the link below to see a list of SDK methods and properties:
Download the demo app latest build .
Instant API, or non-persistent operation mode, has been introduced in API 6.0.1. It is a mode where we do not save any data anywhere. All data is being used only within a request: you send it, receive the response, and that's all, nothing gets recorded. This ensures you do not store any sensitive data, which might be crucial for GDPR compliance. Also, it significantly reduces storage requirements. However, you can set up S3 storage to save the Instant API artifacts.
To enable this mode, when you prepare the config.py file to run the API, set the OZ_APP_COMPONENTS parameter to stateless. Call POST /api/instant/folders/ to send the request without saving any data. Authorization for Instant API should be set on your side.
If you use Instant API with Web SDK, in Web Adapter configuration, set architecture to lite. The version of Web SDK should be 1.7.14 or above.
CPU: 16 cores, 32 threads, base frequency – 2.3 GHz, single-core maximum turbo frequency – 4 GHz.
RAM: 32 GB, DDR 5, Dual Channel.
To evaluate your RPS and RPM and configure your system for optimal performance, please contact us.
Prior to the launch, prepare a configuration file with the parameters listed below.
These parameters are crucial to run Instant API.
You can find the Instant API methods or download the collection below.
To get an access token, call POST /api/authorize/auth/ with credentials (which you've got from us) containing the email and password needed in the request body. The host address should be the API address (the one you've also got from us).
{
"credentials": {
"email": "{{user_email}}", // your login
"password": "{{user_password}}" // your password
}
}The successful response will return a pair of tokens:access_token and expire_token.
access_token is a key that grants you access to system resources. To access a resource, you need to add your access_token to the header.
headers = {‘ X-Forensic-Access-Token’: <access_token>}
access_token is time-limited, the limits depend on the account type.
service accounts – OZ_SESSION_LONGLIVE_TTL (5 years by default),
other accounts – OZ_SESSION_TTL (15 minutes by default).
expire_token is the token you can use to renew your access token if necessary.
If the value ofexpire_date > current date, the value of current sessionexpire_date is set to current date + time period that is defined as shown above (depending on the account type).
To renewaccess_token and expire_token, call POST /api/authorize/refresh/. Add expire_token to the request body and X-Forensic-Access-Token to the header.
In case of success, you'll receive a new pair of access_token and expire_token. The "old" pair will be deleted upon the first authentication with the renewed tokens.
The Web Plugin works inside an iframe. The iframe must be allowed to use the camera, and every page involved must be served over HTTPS and covered by your license.
<iframe src="https://your-domain.example/liveness-page" allow="camera"></iframe>allow="camera" is mandatory, otherwise, the browser blocks camera access, and the plugin cannot start.
allow="camera" on the iframe tag
The plugin reads the address of every parent window to check it against your license. When the parent page is on a different origin, the browser blocks that read and the check cannot complete. This setup is supported, but it needs an additional setting on the Web Adapter side – contact Oz representative.
iframe_allowed is no longer used. iframe support is always on, and the requirements above are all that is needed, so just remove the parameter from the Web Adapter configuration file.
Download and install the Postman client from this page. Then download the JSON file needed:
This collection is identical to 6.0.0, plus a method introduced in 6.6.5.
Oz API 5.1.0 works with the same collection.
Launch the client and import Oz API collection for Postman by clicking the Use resources or import button:
Click files, locate the JSON needed, and hit Open to add it:
The collection will be imported and will appear in the Postman interface:
The Oz API is a comprehensive Rest API that enables facial biometrics, allowing for both face matching and liveness checks. This write-up provides an overview of the essential concepts that one should keep in mind while using the Oz API.
To ensure security, every Oz API call requires an access token in its HTTP headers. To obtain this token, execute the POST /api/authorize/auth method with login and password provided by us. Pass this token in X-Forensic-Access-Token header in subsequent Oz API calls.
provides comprehensive details on the authentication process. Kindly refer to it for further information.
Furthermore, the Oz API offers distinct user roles, ranging from CLIENT, who can perform checks and access reports but lacks administrative rights, e.g., deleting folders, to ADMIN, who enjoys nearly unrestricted access to all system objects. For additional information, please consult
Please note: this feature has been implemented in 8.1.0.
To add or update the language pack for Oz iOS SDK, use the set(languageBundle: Bundle) method. It shows the SDK that you are going to use the non-standard bundle. In OzLocalizationCode, use the custom language (optional).
If you don’t set the custom language and bundle, the SDK uses the pre-installed languages only.
To integrate OZLivenessSDK into an Xcode project via the dependency manager, add the following code to Podfile:
Version is optional as, by default, the newest version is integrated. However, if necessary, you can find the older version number in .
Since 8.1.0, you can also use a simpler code:
The following code also works:
For 8.1.0 and higher:
Please note: installation via SPM is available for versions 8.7.0 and above.
Add the following package dependencies via SPM: (if you need a guide on adding the package dependencies, please refer to the ). OzLivenessSDK is mandatory. Skip the OzLivenessSDKOnDevice file.
You can also add the necessary frameworks to your project manually.



License error. Origin https://… is not in the list premitted by license
The domain of that page is not in your license
Contact your Oz representative to add the domain
Check same-origin policy of parent windows. Plugin should check host of each window.
The parent page is on a different origin than the page with the plugin
Contact your Oz representative – this setup needs an additional server-side setting
every iframe in the chain
HTTPS
the parent page and the page with the plugin
Domain listed in your license
the parent page and the page with the plugin
Same origin as the page with the plugin
the parent page – see Parent page on a different domain
The camera permission dialog never appears; on_error receives error_no_camera (error_no_camera_ios on iOS, error_no_camera_android on Android)
An iframe in the chain has no allow="camera"
Add allow="camera" to every iframe in the chain
Connection error. Please use HTTPS to connect.
The parent page or the page with the plugin is served over HTTP
Serve both over HTTPS
The session with expire_token you have passed doesn't exist.
403
You have not access to refresh this session
A user who makes the request is not thisexpire_token session owner.
Error code
Error message
What caused the error
400
Could not locate field for key_path expire_token from provided dict data
expire_token haven't been found in the request body
401
Session not found
Download the SDK files from here and add them to your project.
OZLivenessSDK.xcframework,
OZLivenessSDKResources.bundle.
Download the TensorFlow framework 2.11 from here.
Make sure that:
both xcframework are in Target-Build Phases -> Link Binary With Libraries and Target-General -> Frameworks, Libraries, and Embedded Context;
the bundle file(s) are in Target-Build Phases -> Copy Bundle Resources.
To customize the Oz Liveness interface, use OZCustomization as shown below. For the description of customization parameters, please refer to iOS SDK Methods and Properties.
# application components list, values for Instant API: auth,stateless
# auth is for Oz authentication component
OZ_APP_COMPONENTS=stateless
# local storage support enable
OZ_LOCAL_STORAGE_SUPPORT_ENABLE=false
# service tfss host
OZ_SERVICE_TFSS_HOST=http://xxx.xxx.xxx.xxx:xxxx
# allowed hosts
APP_ALLOWED_HOSTS=example-host1.com,example-host2.com
# secret key
OZ_API_SECRET_KEY=long_secret_keyCONTAINER_NAME=<container name> \
DEPLOY_INSTANT_PORT_EXT=<external port> \
INSTANT_IMAGE=<provided image name> \
ADDITIONAL_PARAMS="-e LICENSE_KEY=<your license key>" \
docker run -d --name $CONTAINER_NAME
$ADDITIONAL_PARAMS
-p ${DEPLOY_INSTANT_PORT_EXT}:8080
$INSTANT_IMAGEservices:
oz-api-instant:
image: <provided image>
container_name: oz-api-instant
environment:
- LICENSE_KEY=<your license key>
# - TF_ENABLE_ONEDNN_OPTS=1 # In some cases, especially for AMD CPUs, set to 0
# - API_LISTEN_PORT=8080
# - LOG_LEVEL=info # ['critical', 'error', 'warning', 'info', 'debug', 'trace']
restart: always
ports:
- 8080:8080{
"expire_token": "{{expire_token}}"
}pod 'OZLivenessSDK', :git => 'https://gitlab.com/oz-forensics/oz-mobile-ios-sdk', :tag => 'VERSION'// for the latest version
pod ‘OZLivenessSDK’
// OR, for the specific version
// pod ‘OZLivenessSDK’, ‘8.22.0’pod 'OZLivenessSDK/Core', :git => 'https://gitlab.com/oz-forensics/oz-mobile-ios-sdk.git', :tag => 'VERSION'pod ‘OZLivenessSDK/Core’
// OR
// pod ‘OZLivenessSDK/Core’, ‘8.22.0’// customization parameters for the toolbar
let toolbarCustomization = ToolbarCustomization(
closeButtonIcon: UIImage(named: "example"),
closeButtonColor: .black.withAlphaComponent(0.8),
titleText: "",
titleFont: .systemFont(ofSize: 18, weight: .regular),
titleColor: .gray,
backgroundColor: .lightGray)
// customization parameters for the center hint
let centerHintCustomization = CenterHintCustomization(
textColor: .white,
textFont: .systemFont(ofSize: 22, weight: .regular),
verticalPosition: 42,
backgroundColor: UIColor.init(hexRGBA: "1C1C1E8F")!,
hideTextBackground: false,
backgroundCornerRadius: 14)
// customization parameters for the center hint animation
let hintAnimationCustomization = HintAnimationCustomization(
hideAnimation: false,
animationIconSize: 80,
toFrameGradientColor: UIColor.red)
// customization parameters for the frame around the user face
let faceFrameCustomization = FaceFrameCustomization(
strokeWidth: 4,
strokeFaceAlignedColor: .green,
strokeFaceNotAlignedColor: .red,
geometryType: .rect(cornerRadius: 10),
strokePadding: 3)
// customization parameters for the SDK version text
let versionCustomization = VersionLabelCustomization(
textFont: .systemFont(ofSize: 12, weight: .regular),
textColor: .gray
)
// customization parameters for the background outside the frame
let backgroundCustomization = BackgroundCustomization(
backgroundColor: .lightGray
)
// customization parameters for the antiscam protection text
let antiscamCustomization: AntiscamCustomization = AntiscamCustomization(
customizationEnableAntiscam: false,
customizationAntiscamTextMessage: "Face recognition",
customizationAntiscamTextFont: UIFont.systemFont(ofSize: 15, weight: .semibold),
customizationAntiscamTextColor: UIColor.black,
customizationAntiscamBackgroundColor: UIColor.init(hexRGBA: "F2F2F7FF")!,
customizationAntiscamCornerRadius: 18,
customizationAntiscamFlashColor: UIColor.init(hexRGBA: "FF453AFF")!)
// customization parameters for your logo
// should be allowed by license
let logoCustomization = LogoCustomization(
image: UIImage(),
size: CGSize(width: 100, height: 100),
verticalPosition: 100,
horizontalPosition: 50)
OZSDK.customization = Customization(toolbarCustomization: toolbarCustomization,
antiscamCustomization: antiscamCustomization,
centerHintCustomization: centerHintCustomization,
hintAnimationCustomization: hintAnimationCustomization,
faceFrameCustomization: faceFrameCustomization,
versionCustomization: vesrionCustomization,
backgroundCustomization: backgroundCustomization,
logoCustomization: logoCustomization)Java Target Level
1.8
JDK
17
Gradle
7.5.1
Kotlin
1.7.21
AGP
7.3.1
The unit of work in Oz API is a folder: you can upload interrelated media to a folder, run analyses on them, and check for the aggregated result. A folder can contain the unlimited number of media, and each of the media can be a target of several analyses. Also, analyses can be performed on a bunch of media.
Media OZ API works with photos and videos. Video can be either a regular video container, e.g., MP4 or MOV, or a ZIP archive with a sequence of images. Oz API uses the file mime type to define whether media is an image, a video, or a shot set.
It is also important to determine the semantics of a content, e.g., if an image is a photo of a document or a selfie of a person. This is achieved by using tags. The selection of tags impacts whether specific types of analyses will recognize or ignore particular media files. The most important tags are:
photo_id_front – for the front side of a photo ID
photo_selfie – for a non-document reference photo
video_selfie_blank – for a liveness video recorded beyond Oz Liveness SDK
if a media file is captured using the Oz Liveness SDK, the tags are assigned automatically.
The full list of Oz media tags with their explanation and examples can be found here.
Since video analysis may take a few seconds, the analyses are performed asynchronously. This implies that you initiate an analysis (/api/folders/{{folder_id}}/analyses/) and then monitor the outcomes by polling until processing is complete (/api/analyses/{{analysis_id}} for a single analysis or /api/folders/{{folder_id}}/analyses/ for all folder’s analyses). Alternatively, there is a webhook option available. To see an example of how to use both the polling and webhook options, please check this guide.
These were the key concepts of Oz API. To gain a deeper understanding of its capabilities, please refer to the Oz API section of our developer guide.
If both custom bundle and language are set, SDK retrieves all the translations from the custom bundle localization file.
A list of keys for iOS:
The keys Action.*.Task refer to the appropriate gestures. Others refer to the hints for any gesture, info messages, or errors.
When new keys appear with new versions, if no translation is provided by your custom bundle localization file, you’ll see the default (English) text.
By default, iOS string file is called Localizable.strings. If you want to use another table, set it via the set(localizableTableName: "Name") method.
Send the encrypted container to your own backend as raw bytes (application/octet-stream). Your backend forwards it to Oz API and returns the analysis response.
func handleContainer(_ container: DataContainer) {
YourBackend.uploadOzContainer(
container,
contentType: "application/octet-stream"
) { result in
DispatchQueue.main.async {
self.handleAnalysisResult(result)
}
}
}Your backend submits the container to Oz API in a single synchronous POST request as shown here.
To check liveness and face biometry, you need to upload media to our system and then analyze them.
Below, you'll see the example of performing a check and its description.
let analysisRequest = AnalysisRequestBuilder()
// create one or more analyses
let analysis = Analysis.init(
media: mediaToAnalyze, // mediaToAnalyze is an array of OzMedia that were captured or otherwise created
type: .quality, // check the analysis types in iOS methods
mode: .serverBased)
analysisRequest.uploadMedia(mediaToAnalyze)
analysisRequest.addAnalysis(analysis)
// initiate the analyses
analysisRequest.run(
statusHandler: { state in }, // scenario steps progress handler
errorHandler: { _ in }
) { result in
// receive and handle analyses results here
}To delete media files after the checks are finished, use the cleanTempDirectory method.
To add metadata to a folder, use AnalysisRequest.addFolderMeta.
In the params field of the Analysis structure, you can pass any additional parameters (key + value), for instance, to extract the best shot on the server side.
To use a media file that is captured with another SDK (not Oz iOS SDK), specify the path to it in the OzMedia structure (the bestShotURL property):
If you want to add your media to the existing folder, use the addFolderId method:
To work properly, the resolution algorithms need each uploaded media to be marked with special tags. For video and images, the tags are different. They help algorithms to identify what should be in the photo or video and analyze the content.
The following tag types should be specified in the system for video files.
To identify the data type of the video:
video_selfie
To identify the orientation of the video:
orientation_portrait – portrait orientation;
orientation_landscape – landscape orientation.
To identify the action on the video:
video_selfie_left – head turn to the left;
video_selfie_right – head turn to the right;
On January 1, 2027, the One Shot gesture will become unavailable. Please plan your .
The tags listed allow the algorithms recognizing the files as suitable for the (Liveness) and analyses.
Important: in API 4.0.8 and below, to launch the Quality analysis for a photo, pack the image into a .zip archive, apply the SHOTS_SET type, and mark it with video_*. Otherwise, it will be ignored by algorithms.
Example of the correct tag set for a video file with the “blink” action:
The following tag types should be specified in the system for photo files:
A tag for selfies:
photo_selfie – to identify the image type as “selfie”.
Tags for photos/scans of ID cards:
Important: in API 4.0.8 and below, to launch the Quality analysis for a photo, pack the image into a .zip archive, apply the SHOTS_SET type, and mark it with video_*. Otherwise, it will be ignored by algorithms.
Example of the correct tag set for a “selfie” photo file:
Example of the correct tag set for a photo file with the face side of an ID card:
Example of the correct set of tags for a photo file of the back of an ID card:
In version 6.0.1, we introduced a new feature which allows you to send all required data and receive the analysis result within a single request.
Before 6.0.1, interacting with the API required multiple requests: you had to create a folder and upload media to it, initiate analyses (see Liveness, Biometry, and Blacklist), and then either poll for results or use webhooks for notifications when the result was ready. This flow is still supported, so if you need to send separate requests, you can continue using the existing methods that are listed above.
However, the new API operation mode significantly simplifies the process by allowing you to send a single request and receive the response synchronously. The key benefits are:
Single request for everything – all data is sent in one package, eliminating the risk of data loss.
Synchronous response – no need for polling or webhooks to retrieve results.
High performance – supports up to 36 analyses per minute per instance.
To use this method, call POST /api/folders/. In the X-Forensic-Access-Token header, pass your . Add media files to the request body and define the tags and metadata if needed in the payload part.
In response, you receive analysis results.
For commercial use of Oz Forensics products, a license is required. The license is time-limited and defines the software access parameters based on the terms of your agreement. Some product features are also controlled by the license:
features.watermark
Displays logo (Oz by default)
Once you initialize mobile SDK, run Web Plugin, or use Oz Bio, the system checks if your license is valid. The check runs in the background and has minimal impact on the user experience.
As you can see on the scheme above, the license is required for:
Mobile SDKs for iOS and Android,
Web SDK, which consists of Web Adapter and Web Plugin,
Oz BIO, which is needed for server analyses and is installed for .
For each of the components, you require a separate license which is bound to this component. Thus, if you use all three components, three licenses are required.
To issue a license for mobile SDK, we require your bundle (application) ID. There are two types of licenses for iOS and Android SDKs: online and offline.
As its name suggests, an online license requires a stable connection. Once you initialize our SDK with this license, it connects to our license server and retrieves information about license parameters, including counters of transactions or devices, where:
Transaction: increments each time you start a video capture.
Device: increments when our SDK is installed on a new device.
The online license can be transaction-limited, device-limited, or both, according to your agreement.
Please note that even though on-device analyses don’t need the Internet themselves, you still require a connection for license verification.
Offline license is a type of license that can work without Internet. All license parameters are set in the license file, and you just need to add the file to your project. This license type doesn’t have any restrictions on transactions or devices.
The main benefit of the offline license is its autonomy, allowing it to function without a network connection. However, when your license expires, and you add a new one, you’ll require to release a new version of your application in Google Play and App Store. Otherwise, the SDK won’t function.
How to add a license to mobile SDK:
Web SDK license is almost similar to the mobile SDK offline license. It can function without network connection, and the license file contains all the necessary parameters, such as expiration date. Web SDK license also has no restrictions on transactions or devices.
The license is bound to URLs of your domains and/or subdomains. To add the license to your SDK instance, you need to place it to the Web SDK container as described . In rare cases, it is also possible to .
The difference between Mobile SDK offline license and Web SDK license is that you don’t need to release a new application version when Web SDK license is renewed.
For on-premise installations, we offer a dedicated license with a limitation on activations, with each activation representing a separate Oz BIO seat. This license can be online or offline, depending on whether your Oz BIO servers have internet access. The online license is verified through our license server, while for offline licenses, we assist you in within your infrastructure and activating the license.
For test integration purposes, we provide a free trial license that is sufficient for initial use, such as testing with your datasets to check analysis accuracy. For Mobile SDKs, you can generate a one-month license yourself on our website: . If you would like to integrate with your web application, please to obtain a license, and we will also assist you in configuring your dedicated instance of our Web SDK. With the license, you will receive credentials to access our services.
Once you're ready to move to commercial use, a new production license will be issued. We’ll provide you with new production credentials and assist you with integration and configuration. Our engineers are always available to help.
Our software offers flexible licensing options to meet your specific needs. Whether you prioritize seamless updates or prefer autonomous operation, we have a solution tailored for you. If you have any questions, please contact us.
Create a controller that will capture videos as follows:
getSessionToken() { sessionToken in
DispatchQueue.main.async {
do {
let action:OZVerificationMovement = .selfie
let mediaRequest = MediaRequest.action(action)
let profile = AnalysisProfile(mediaList: [mediaRequest],
type: .quality,
params: [:] )
let request = CaptureRequest(analysisProfileList: [profile], cameraPosition: .front)
let ozLivenessVC = try OZSDK.createMediaCaptureScreen(self, request, sessionToken: sessionToken)
self.present(ozLivenessVC, animated: true)
} catch let error {
print(error.localizedDescription)
}
}
}The delegate object must implement the OZLivenessDelegate protocol:
extension ViewController: LivenessDelegate {
func onResult(container: DataContainer) {
}
func onError(status: OZVerificationStatus?) {
}
}Create a controller that will capture videos as follows:
let actions: [OZVerificationMovement] = [.selfie]
let ozLivenessVC: UIViewController = OZSDK.createVerificationVCWithDelegate(self, actions: actions)
self.present(ozLivenessVC, animated: true)action – a list of user’s actions while capturing the video.
Once video is captured, the system calls the onOZLivenessResult method:
extension viewController: OZLivenessDelegate {
func onError(status: OZVerificationStatus?) {
// show error
}
}
func onOZLivenessResult(results: [OZMedia]) {
// proceed to the checks step
}
}The method returns the results of video capturing: the [OZMedia] objects. The system uses these objects to perform checks.
If a user closes the capturing screen manually, the failedBecauseUserCancelled error appears.
The Biometry algorithm is intended to compare two or more photos and detect the level of similarity of the spotted faces. As a source media, the algorithm takes photos, videos, and documents (with photos).
You're authorized.
You have already created a folder and added your media marked by correct tags into this folder.
1. Initiate the analysis for the folder: POST /api/folders/{{folder_id}}/analyses/
If you want to use a webhook for response, add it to the payload at this step, as described .
You'll needanalysis_id or folder_id from response.
2. If you use a webhook, just wait for it to return the information needed. Otherwise, initiate polling:
GET /api/analyses/{{analysis_id}} – for the analysis_id you have from the previous step.
GET /api/folders/{{folder_id}} – for all analyses performed on media in the folder with the folder_id you have from the previous step.
Repeat until the resolution_status and resolution fields change status to any other except PROCESSING, and treat this as a result.
The add_lang(lang_id, lang_obj) method allows adding a new or customized language pack.
Parameters:
lang_id: a string value that can be subsequently used as lang parameter for the open() method;
lang_obj: an object that includes identifiers of translation strings as keys and translation strings themselves as values.
A list of language identifiers:
An example of usage:
OzLiveness.add_lang('en', enTranslation), where enTranslation is a JSON object.
To set the SDK language, when you launch the plugin, specify the language identifier in lang:
You can check which locales are installed in Web SDK: use the ozLiveness.get_langs() method. If you have added a locale manually, it will also be shown.
A list of all language identifiers:
The keys oz_action_*_go refer to the appropriate gestures. oz_tutorial_camera_* – to the hints on how to enable camera in different browsers. Others refer to the hints for any gesture, info messages, or errors.
Since 1.5.0, if your language pack doesn't include a key, the message for this key will be shown in English.
Oz Forensics specializes in liveness and face matching: we develop products that help you identify your clients remotely and protect against spoofing and deepfake attacks. Oz software helps you to add facial recognition to your software systems and products. You can integrate Oz modules in many ways depending on your needs. We are constantly improving our components, increasing their quality.
Oz Liveness is responsible for recognizing a living person on a video it receives. Oz Liveness can distinguish a real human from their photo, video, mask, or other kinds of spoofing and deepfake attacks. The accuracy of our algorithms is confirmed by BixeLab, the independent biometric testing laboratory.
Here are the confirmation letters from the laboratory.
PAD levels 1 and 2:
PAD level 3:
IAD:
ISO ISO/IEC 19795-2: 2007:
Oz Liveness is also certified by iBeta, a NIST-accredited biometric testing laboratory, with 100% accuracy.
Our liveness technology protects against both injection and presentation attacks.
The injection attack detection is layered. Our SDK examines user environment to detect potential manipulations: browser, camera, etc. Further on, the deep neural network comes into play to defend against even the most sophisticated injection attacks.
The presentation attack detection is based on deep neural networks of various architectures, combined with a proprietary ensembling algorithm to achieve optimal performance. The networks consider multiple factors, including reflection, focus, background scene, motion patterns, etc. We offer both passive (no gestures) and active (various gestures) , ensuring that your customers enjoy the user experience while delivering accurate results for you. The iBeta test was conducted using passive Liveness, and since then, we have significantly enhanced our networks to better meet the needs of our clients.
Oz Face Matching (Biometry) verifies that the person performing the check is the same person shown on the document. Oz Biometry looks through the video, finds the best shot where the person is clearly seen, and compares it with the photo from ID or another document. The algorithm's accuracy is 99.99% confirmed by NIST FRVT.
Our biometry technology has both 1:1 Face Verification and 1:N Face Identification, which are also based on ML algorithms. To train our neural networks, we use our own framework based on state-of-the-art technologies. Our private dataset of over 4.5 million unique faces covers a wide range of ethnic groups and attributes (predicted race, age, etc.), helping our models produce robust matching scores.
Our face detector can work with photos and videos. Also, the face detector excels in detecting faces in images of IDs and passports (which can be rotated or of low quality).
The Oz software combines accuracy in analysis with ease of integration and use. To further simplify the integration process, we have provided a detailed description of all the key concepts of our system in this section. If you're ready to get started, please refer to our , which provide the step-by-step instructions on how to achieve your facial recognition goals quickly and easily.
Oz Forensics adheres to SOC 2® and ISO/IEC 27001:2022 standards.
This guide describes how to match a liveness video with a reference photo of a person that is already stored in your database.
However, if you prefer to include a photo ID capture step to your liveness process instead of using a stored photo, then you can refer to in this section.
By this time you should have already implemented liveness video recording and liveness check. If not, please refer to these guides:
In this scenario, you upload your reference image to the same folder where you have a liveness video, initiate the BIOMETRY analysis, and poll for the results.
Given that you already have the liveness video recorded and uploaded, you will be working with the same Oz API folder where your liveness video is. Obtain the folder ID as described below, and pass it to your back end.
Send the encrypted container to your own backend as raw bytes (application/octet-stream). Your backend forwards it to Oz API and returns the analysis response.
Your backend submits the container to Oz API in a single synchronous POST request as shown .
To check liveness and face biometry, you need to upload media to our system and then analyze them.
Here’s an example of performing a check:
To delete media files after the checks are finished, use the clearActionVideos
Master license is the offline license that allows using Mobile SDKs with any bundle_id, unlike the regular licenses. To get a master license, create a pair of keys as shown below. Email us the public key, and we will email you the master license shortly after that.
Your application needs to sign its bundle_id with the private key, and the Mobile SDK checks the signature using the public key from the master license. Master licenses are time-limited.
This section describes the process of creating your private and public keys.
To create a private key, run the commands below one by one.
You will get these files:
Response codes 2XX indicate a successfully processed request (e.g., code 200 for retrieving data, code 201 for adding a new entity, code 204 for deletion, etc.).
Response codes 4XX indicate that a request could not be processed correctly because of some client-side data issues (e.g., 404 when addressing a non-existing resource).
Response codes 5XX indicate that an internal server-side error occurred during the request processing (e.g., when database is temporarily unavailable).
This article contains the full description of folders' and analyses' statuses in API.
In this section, you will find the description of both API and SDK components of Oz Forensics Liveness and face biometric system. API is the backend component of the system, it is needed for all the system modules to interact with each other. SDK is the frontend component that is used to:
1) take videos or images which are then processed via API,
2) display results.
We provide two versions of API.
With full version, we provide you with all functionality of Oz API.
The Lite version is a simple and lightweight version with only the necessary functions included.
The SDK component consists of web SDK and mobile SDK.
Web SDK is a plugin that you can embed into your website page and the adapter for this plugin.
Yes, for hiding logo
features.version-on-screen
Displays SDK version
No
configs.custom_logo
Displays a custom logo
Yes













-
-
starting state
starting state
FAILED
system error
system error
system error
system error
FINISHED
finished successfully
-
finished successfully
-
DECLINED
-
check failed
-
check failed
OPERATOR_REQUIRED
-
additional check is needed
-
additional check is needed
SUCCESS
-
check succeeded
-
check succeeded
The details on each status are below.
This is the state when the analysis is being processed. The values of this state can be:
FAILED – the analysis failed due to some error and couldn't get finished;
FINISHED – job's done, the analysis is finished, and you can check the result.
Once the analysis is finished, you'll see one of the following results:
SUCCESS – everything went fine, the check succeeded (e.g., faces match or liveness confirmed);
OPERATOR_REQUIRED (except the Liveness analysis) – the result should be additionally checked by a human operator;
DECLINED – the check failed (e.g., faces don't match or some spoofing attack detected).
If the analysis hasn't been finished yet, the result inherits a value from analyses.state.
A folder is an entity that contains media to analyze. If the analyses have not been finished, the stage of processing media is shown in resolution_status:
INITIAL – no analyses applied;
FAILED – any of the analyses failed due to some error and couldn't get finished;
FINISHED – media in this folder are processed, the analyses are finished.
Folder result is the consolidated result of all analyses applied to media from this folder. Please note: the folder result is the result of the last-finished group of analyses. If all analyses are finished, the result will be:
SUCCESS – everything went fine, all analyses completed successfully;
OPERATOR_REQUIRED (except the Liveness analysis) – there are no analyses with the DECLINED status, but one or more analyses have been completed with the OPERATOR_REQUIRED status;
DECLINED – one or more analyses have been completed with the DECLINED status.
INITIAL
func onResult(container: DataContainer) {
let analysisRequest = AnalysisRequestBuilder()
analysisRequest.addContainer(container)
analysisRequest.run(
statusHandler: { status in
},
errorHandler: { error in
}
) { result in
}
}video_selfie_down – head tilt downwards;
video_selfie_high – head raise up;
video_selfie_smile – smile;
video_selfie_eyes – blink;
video_selfie_scan – scanning;
video_selfie_blank – no action;
video_selfie_oneshot – a one-frame analysis.
photo_id – to identify the image type as “ID”;
photo_id_front – for the photo of the ID front side;
Portuguese (Brazilian)
kz, kk
Kazakh
en
English
es
Spanish
pt-br
To force the closing of the plugin window, use the close() method. All requests to server and callback functions (except on_close) within the current session will be aborted.
Example:
var session_id = 123;
OzLiveness.open({
// We transfer the arbitrary meta data, by which we can later identify the session in Oz API
meta: {
session_id: session_id
},
// After sending the data, forcibly close the plugin window and independently request the result
on_submit: function() {
OzLiveness.close();
my_result_function(session_id);
}
});To hide the plugin window without cancelling the requests for analysis results and user callback functions, call the hide() method. Use this method, for instance, if you want to display your own upload indicator after submitting data.
An example of usage:
For a video recorded by Web SDK, get the folder_id as described here.
For a video recorded by Android or iOS SDK, retrieve the folder_id from the analysis’ results as shown below:
Android:
iOS:
Call POST /api/folders/{{folder_id}}/media/ method, replacing the folder_id with the ID you’ve got in the previous step. This will upload your new media to the folder where your ready-made liveness video is located.
Set the appropriate tags in the payload field of the request, depending on the nature of a reference photo that you have.
To launch the analysis, call POST /api/folders/{{folder_id}}/analyses/ with the folder_id from the previous step. In the request body, specify the biometry check to be launched.
Repeat calling GET /api/analyses/{{analysis_id}} with the analysis_id from the previous step once a second until the state changes from PROCESSING to something else. For a finished analysis, get the result from resolution (SUCCESS or DECLINED).
Here is the Postman collection for this guide.
With these steps completed, you are done with adding face matching via Oz API. You will be able to access your media and analysis results in Web UI via browser or programmatically via API.
Oz API methods can be combined with great flexibility. Explore Oz API using the API Developer Guide.

privateKey.txt is privateKey.der encoded by base64. This key containing will be used as the host app bundle_id signature.
The OpenSSL command specification: https://www.openssl.org/docs/man1.1.1/man1/openssl-pkcs8.html
To create a public key, run this command.
You will get the public key file: publicKey.pub. To get a license, please email us this file. We will email you the license.
SDK initialization:
License setting:
Prior to the SDK initializing, create a base64-encoded signature for the host app bundle_id using the private key.
Signature creation example:
Pass the signature as the masterLicenseSignature parameter either during the SDK initialization or license setting.
If the signature is invalid, the initialization continues as usual: the SDK checks the list of bundle_id included into the license like it does it by default without a master license.
let analysis = Analysis.init(media: mediaToAnalyze, type: .quality, mode: .serverBased)
var folderMeta: [String: Any] = ["key1": "value1"]
analysisRequest.addFolderMeta(folderMeta)
...let analysis = Analysis.init(media: mediaToAnalyze, type: .quality, mode: .serverBased, params: [“extract_best_shot” : true])let referenceMedia = OZMedia.init(movement: .selfie,
mediaType: .movement,
metaData: ["meta":"data"],
videoURL: nil,
bestShotURL: imageUrl,
preferredMediaURL: nil,
timestamp: Date())let analysis = Analysis.init(media: mediaToAnalyze, type: .quality, mode: .serverBased)
analysisRequest.addFolderId(IdRequired)"video1": [
"video_selfie",
"video_selfie_eyes",
"orientation_portrait"
]"photo1": [
"photo_selfie"
]"photo1": [
"photo_id",
"photo_id_front"
]"photo1": [
"photo_id",
"photo_id_back"
]{
// (optional block) folder metadata if needed
"folder:meta_data": {
"partner_side_folder_id": "00000000-0000-0000-0000-000000000000",
"person_info": {
"first_name": "John",
"middle_name": "Jameson",
"last_name": "Doe"
}
},
// (optional block) folder metadata if needed
"media:meta_data": {
"video1": {
"foo": "bar"
}
},
"media:tags": {
"video1": [
"video_selfie",
"video_selfie_eyes",
"orientation_portrait"
]
},
"analyses": [
{
"type": "quality",
// (optional block) folder metadata if needed
"meta_data": {
"example1": "some_example1"
},
// additional parameters
"params": {
"extract_best_shot": false
}
}
]
}{
"company_id": "00000000-0000-0000-0000-000000000000",
"time_created": 1744017549.366616,
"folder_id": "00000000-0000-0000-0000-000000000000",
"user_id": "00000000-0000-0000-0000-000000000000",
"resolution_endpoint": null,
"resolution_status": "FINISHED",
"resolution_comment": "[]",
"system_resolution": "SUCCESS",
...
// folder metadata if you've added it
"meta_data": {
"partner_side_folder_id": "00000000-0000-0000-0000-000000000000",
"person_info": {
"first_name": "John",
"middle_name": "Jameson",
"last_name": "Doe"
}
},
"media": [
{
"company_id": "00000000-0000-0000-0000-000000000000",
"folder_id": "00000000-0000-0000-0000-000000000000",
"folder_time_created": 1744017549.366616,
"original_name": "00000000-0000-0000-0000-000000000000.mp4",
"original_url": null,
"media_id": "00000000-0000-0000-0000-000000000000",
"media_type": "VIDEO_FOLDER",
"tags": "video1": [
"video_selfie",
"video_selfie_eyes",
"orientation_portrait"
]
"info": {},
"time_created": 1744017549.368665,
"time_updated": 1744017549.36867,
// media metadata if you've added it
"meta_data": {
"foo": "bar"
},
"thumb_url": null,
"image_id": "00000000-0000-0000-0000-000000000000"
}
],
"time_updated": 1744017549.366629,
"analyses": [
{
"company_id": "00000000-0000-0000-0000-000000000000",
"group_id": "00000000-0000-0000-0000-000000000000",
"folder_id": "00000000-0000-0000-0000-000000000000",
"folder_time_created": 1744017549.366616,
"analysis_id": "00000000-0000-0000-0000-000000000000",
"state": "FINISHED",
"resolution_operator": null,
"results_media": [
{
...
}
],
"results_data": null,
// analysis metadata if you've added it
"meta_data": {
"example1": "some_example1"
},
"time_created": 1744017549.369485,
"time_updated": 1744017550.659305,
"error_code": null,
"error_message": null,
"source_media": [
{
...
}
],
"type": "QUALITY",
"analyse_id": "00000000-0000-0000-0000-000000000000",
"resolution_status": "SUCCESS",
"resolution": "SUCCESS"
}
]
}{
"analyses": [{
"type": "biometry",
// optional; omit to include all media from the folder
"source_media": [
"1111aaaa-11aa-11aa-11aa-111111aaaaaa",
"2222bbbb-22bb-22bb-22bb-222222bbbbbb"
]
}]
}// Editing the button text
OzLiveness.add_lang('en', {
action_photo_button: 'Take a photo'
});OzLiveness.open({
lang: 'es', // the identifier of the needed language
...
});let mediaRequest1 = MediaRequest.action(.scanning)
let mediaRequest2 = MediaRequest.action(.eyes)
let mediaRequest3 = MediaRequest.action(.smile)
let profile = AnalysisProfile(
mediaList: [mediaRequest1, mediaRequest2, mediaRequest3],
type: .quality,
params: [:]
)
let request = CaptureRequest(
analysisProfileList: [profile],
cameraPosition: .front
)
let livenessVC = try OZSDK.createMediaCaptureScreen(
delegate,
request,
sessionToken: sessionToken // from Step 3
)
livenessVC.modalPresentationStyle = .fullScreen
parent.present(livenessVC, animated: true)OzLiveness.open({
// When receiving an intermediate result, hide the plugin window and show your own loading indicators
on_result: function(result) {
OzLiveness.hide();
if (result.state === 'processing') {
show_my_loader();
}
},
on_complete: function() {
hide_my_loader();
}
});AnalysisRequest.Builder()
...
.run(object : AnalysisRequest.AnalysisListener {
override fun onSuccess(result: List<OzAnalysisResult>) {
// save folder_id that is needed for the next step
val folderId = result.firstOrNull()?.folderId
}
...
})private void analyzeMedia(List<OzAbstractMedia> mediaList) {
new AnalysisRequest.Builder()
...
.run(new AnalysisRequest.AnalysisListener() {
@Override public void onStatusChange(@NonNull AnalysisRequest.AnalysisStatus analysisStatus) {}
@Override
public void onSuccess(@NonNull List<OzAnalysisResult> list) {
String folderId = list.get(0).getFolderId();
}
}
...
});
}analysisRequest.run(
scenarioStateHandler: { state in },
uploadProgressHandler: { (progress) in }
) { (analysisResults : [OzAnalysisResult], error) in
// save folder_id that is needed for the next step
let folderID = analysisResults.first?.folderID
}
}{
"media:tags": {
"photo1": [
"photo_id", "photo_id_front" // for the front side of an ID
// OR
"photo_selfie" // for a non-ID photo
]
}
}{
"analyses": [
{
"type": "biometry"
}
]
}openssl genpkey -algorithm RSA -outform DER -out privateKey.der -pkeyopt rsa_keygen_bits:2048
# for MacOS
base64 -i privateKey.der -o privateKey.txt
# for Linux
base64 -w 0 privateKey.der > privateKey.txtopenssl rsa -pubout -in privateKey.der -out publicKey.pubOZSDK(licenseSources: [LicenseSource], masterLicenseSignature: String? = nil, completion: @escaping ((LicenseData?, LicenseError?) -> Void))setLicense(licenseSource: LicenseSource, masterLicenseSignature: String? = nil)private func getSignature() -> String? {
let privateKeyBase64String = "the string copied from the privateKey.txt file"
// with key example:
// let privateKeyBase64String = "MIIEogIBAAKCAQEAvxpyONpif2AjXiiG8fs9pQkn5C9yfiP0lD95Z0UF84t0Ox1S5U1UuVE5kkTYYGvS2Wm7ykUEGuHhqt/PyOAxrrNkAGz3OcVTsvcqPmwcf4UNdYZmug6EnQ5ok9wxYARS0aYqJUdzUb4dKOYal6WpHZE4yLx08R0zQ5jPkg5asT2u2PLB7JHZNnXwBcvdUonAgocNzdakUbWTNHKMxjwdAvwdIICdIneLZ9nCqe1d0cx7JBIhLzSPu/DVRANF+DOsE9JM8DT/Snnjok2xXzqpxBs1GwqiMJh98KYP78AVRWFuq3qbq0hWpjbq+mWl8xa7UMv8WxVd4PvQkWVYq/ojJwIDAQABAoIBAEvkydXwTMu/N2yOdcEmAP5I25HQkgysZNZ3OtSbYdit2lQbui8cffg23MFNHA125L65Mf4LWK0AZenBhriE6NYzohRVMf28cxgQ9rLhppOyGH1DCgr79wiUj02hVe6G6Qkfj39Ml+yvrs7uS0NMZBQ89yspRNv4t8IxrsWXc8cNQr33fdArlZ021Z12u2wdamaagiFwTa6ZYcQ5OYl3d/xL+oAwf9ywHwRrVM2JksGCxrcLJ7JCOL6lLyjp8rRrIG4iZ1V8YDfUNHmwD4w1fl30H6ejA+Cy5qge7CBZK+hqKr+hOcfBfakfOtgcEbFq2L8DqHoSaTeY6n9wjPJiFrkCgYEA8fc/Cg+d0BN98aON80TNT+XLEZxXMH+8qdmJYe/LB2EckBj1N0en87OEhqMFm9BjYswGf/uO+q2kryEat1n3nejbENN9XaO36ahlXTpQ6gdHO3TuO+hnnUkXeUNgiGYs+1L8Ot6PuNykwL0BZ09U0iBVoawEjTAg9tLNfVW2upsCgYEAyi/75YFT3ApxfSf/9XR74a0aKrfGGlBppcGvxuhVUC2aW2fPEZGXo4qlEhP2tyVTfj78F2p0Fnf3NSyvLZAzSwKo4w8EyZfXn1RI4sM95kzIMhH3Gz8VxCZWKEgr7cKNU5Zhs8un/VFd9Mc0KyZfmVy4VrZ5JumgahBRzSn9zGUCgYA7TTt3/cfRvVU6qbkajBw9nrYcRNLhogzdG+GdzSVXU6eqcVN4DunMwoySatXvEC2rgxF8wGyUZ4ZbHaPsl/ImE3HNN+gb0Qo8C/d719UI5mvA2LGioRzz4XwNTkQUaeZQWlBTJUTYK8t9KVV0um6xaRdTnlMnP0p088lFFILKTQKBgDsR98selKyF1JBXPl2s8YCGfU2bsWIAukz2IG/BcyNgn2czFfkxCxd5qy5z7LGnUxRgPHBu5oml9PBxJKDwLzwsA8GKosBu/00KZ9zwY8ZECn0uaH5qWOacuLE+HK9zFq0kE1lfF65XtlaMWH5+0JFS2HxlBVJMEVTLfcquCPtNAoGAG6ytPm24AS1satPwlKnZODQEg0kc7d5S42jbt4X7lwICY/7gORSdbNS8OmrqYhP/8tDOAUtzPQ20fEt43/VA87bq88BVzoSp4GVQcSL44MzRBQHQwTVkoVnbCXSD9K9gZ71wii+m+8rZZ0EMdiTR3hsRXRuSmw4t8y3CuzlZ9k4="
guard let data = Data(base64Encoded: privateKeyBase64String, options: [.ignoreUnknownCharacters]) else {
return nil
}
let sizeInBits = data.count * 8
let keyDict: [CFString: Any] = [
kSecAttrKeyType: kSecAttrKeyTypeRSA,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: NSNumber(value: sizeInBits)
]
var error: Unmanaged<CFError>?
guard let secKey = SecKeyCreateWithData(data as CFData, keyDict as CFDictionary, &error) else {
return nil
}
guard let bundleID = Bundle.main.bundleIdentifier else {
return nil
}
guard let signature = SecKeyCreateSignature(secKey,
.rsaSignatureMessagePKCS1v15SHA512,
Data(bundleID.utf8) as CFData,
&error) else {
return nil
}
return (signature as Data).base64EncodedString()
}To add metadata to a folder, use the addFolderMeta method.
.addFolderMeta(
mapOf(
"key1" to "value1",
"key2" to "value2"
)
).addFolderMeta(Collections.singletonMap("key", "value")) In the params field of the Analysis structure, you can pass any additional parameters (key + value), for instance, to extract the best shot on the server side.
To use a media file that is captured with another SDK (not Oz Android SDK), specify the path to it in OzAbstractMedia:
If you want to add your media to the existing folder, use the setFolderId method:
private fun handleContainer(container: DataContainer?) {
if (container == null) return
YourBackend.uploadOzContainer(
container = container.getBytes(),
contentType = "application/octet-stream"
)
}analysisCancelable = AnalysisRequest.Builder()
// mediaToAnalyze is an array of OzAbstractMedia that were captured or otherwise created
.addAnalysis(Analysis(Analysis.Type.QUALITY, Analysis.Mode.SERVER_BASED, mediaToAnalyze))
.build()
//initiating the analyses and setting up a listener
.run(object : AnalysisRequest.AnalysisListener {
override fun onStatusChange(status: AnalysisRequest.AnalysisStatus) { handleStatus(status) // or your status handler
}
override fun onSuccess(result: RequestResult) {
handleResults(result) // or your result handler
}
override fun onError(error: OzException) { handleError(error) // or your error handler
}
})analysisCancelable = new AnalysisRequest.Builder()
// mediaToAnalyze is an array of OzAbstractMedia that were captured or otherwise created
.addAnalysis(new Analysis(Analysis.Type.QUALITY, Analysis.Mode.SERVER_BASED, mediaToAnalyze)) // or ON_DEVICE if you want the on-device analysis
.build()
//initiating the analyses and setting up a listener
.run(new AnalysisRequest.AnalysisListener() {
@Override
public void onSuccess(@NonNull RequestResult list) { handleResults(list); } // or your result handler
@Override
public void onError(@NonNull OzException e) { handleError(e); } // or your error handler
@Override
public void onStatusChange(@NonNull AnalysisRequest.AnalysisStatus analysisStatus) { handleStatus(analysisStatus); } // or your status handler
})mapOf("extract_best_shot" to true) val file = File(context.filesDir, "media.mp4") // use context.getExternalFilesDir(null) instead of context.filesDir for external app storage
val media = OzAbsractMedia.OzVideo(OzMediaTag.VideoSelfieSmile, file.absolutePath) .setFolderId(folderId)Each response error includes HTTP code and JSON data with error description. It has the following structure:
error_code – integer error code;
error_message– text error description;
details – additional error details (format is specified to each case). Can be empty.
Sample error response:
Error codes:
0
UNKNOWN
Unknown server error
1
NOT ALLOWED
Error code
Error message
Description
3
Invalid request data
Missing payload.json
4
{
"error_code": 0,
"error_message": "Unknown server side error occurred",
"details": null
}Even though the analysis result is available to the host application via Web Plugin callbacks, it is recommended that the application back end receives it directly from Oz API. All decisions of the further process flow should be made on the back end as well. This eliminates any possibility of malicious manipulation with analysis results within the browser context.
To find your folder from the back end, you can follow these steps:
On the front end, add your unique identifier to the folder metadata.
OzLiveness.open({
...
meta: {
// the user or lead ID from an external lead generator
// that you can pass to keep track of multiple attempts made by the same user
'end_user_id': '<user_or_lead_id>',
// the unique attempt ID
'transaction_id': '<unique_transaction_id>'
}
});You can add your own key-value pairs to attach user document numbers, phone numbers, or any other textual information. However, ensure that tracking personally identifiable information (PII) complies with relevant regulatory requirements.
/api/folders/?meta_data=transaction_id==unique_id1&with_analyses=trueUse the on_complete callback of the plugin to be notified when the analysis is done. Once used, call your back end and pass the transaction_id value.
On the back end side, find the folder by the identifier you've specified using the Oz API Folder LIST method:
To speed up the processing of your request, we recommend adding the time filter as well:
In the response, find the analysis results and folder_id for future reference.
Web Adapter may send analysis results to the Web Plugin with various levels of verbosity. It is recommended that, in production, the level of verbosity is set to minimum.
In the Web Adapter file, set the result_mode parameter to "safe".
Web Plugin is a plugin called by your web application. It works in a browser context. The Web Plugin communicates with Web Adapter, which, in turn, communicates with Oz API.
Please find a sample for Oz Liveness Web SDK here. To make it work, replace <web-adapter-url> with the Web Adapter URL you've received from us.
For the samples below, replace https://<link>.ozforensics.com in index.html.
Angular sample
sample
sample
sample
This callback is called periodically during the analysis’ processing. It retrieves an intermediate result (unavailable for the capture mode). The result content depends on the Web Adapter result_mode configuration parameter.
When result_mode is safe, the on_result callback contains the state of the analysis only:
{
"state": "finished"
}For the status value, the callback contains the state of the analysis, and for each of the analysis types, the name of the type, state, and resolution.
{
"state": "finished",
"analyses": {
"quality": {
"state": "finished",
"resolution": "SUCCESS"
}
}
}The folder value is almost similar to the status value, with the only difference: the folder_id is added.
In this case, you receive the detailed response possibly containing sensitive data. This mode is deprecated; for security reasons, we recommend using the safe mode.
API Lite (FaceVer) changes
Security updates.
Fixed the bug with the time_created and folder_id parameters of the Detect method that sometimes might have been generated incorrectly.
Security updates.
Updated models.
The file size for the detect Liveness method is now capped at 15 MB, with a maximum of 10 files per request.
Updated the gesture list for best_shot analysis: it now supports head turns (left and right), tilts (up and down), smiling, and blinking.
Introduced the new that can process videos and archives as well.
Added the .
API Lite now accepts base64.
Improved the biometric model.
Added the 1:N mode.
Added the CORS policy.
Published the documentation.
Improved error messages – made them more detailed.
Simplified the Liveness/Detect methods.
Reworked and improved the core.
Added anti-spoofing algorithms.
Added the extract_and_compare method.
The webhook feature simplifies getting analyses' results. Instead of polling after the analyses are launched, add a webhook that will call your website once the results are ready.
When you create a folder, add the webhook endpoint (resolution_endpoint) into the payload section of your request body:
{
"resolution_endpoint": "address.com", // use address of your website here
... // other request details - folder etc.
}You'll receive a notification each time the analyses are completed for this folder. The webhook request will contain information about the folder and its corresponding analyses.
This article covers the default rules of applying analyses.
Analyses in Oz system can be applied in two ways:
manually, for instance, when you choose the Liveness scenario in our demo application;
automatically, when you don’t choose anything and just assign all possible analyses (via API or SDK).
The automatic assignment means that Oz system decides itself what analyses to apply to media files based on its and type. If you upload files via the web console, you select the tags needed; if you take photo or video via Web SDK, the SDK picks the tags automatically. As for the media type, it can be IMAGE
We offer different usage models for the Oz software to meet your specific needs. You can either utilize the software as a service from one of our cloud instances or integrate it into your existing infrastructure. Regardless of the usage model you choose, all Oz modules will function equally. It’s only up to you what to pick, depending on your needs.
With the SaaS model, you can access one of our clouds without having to install our software in your own infrastructure.
Choose SaaS when you want:
Faster start as you don’t need to procure or allocate hardware within your company and set up a new instance.
To connect SDK to Oz API, specify the API URL, , and as shown below.
Alternatively, you can use the login and password provided by your Oz Forensics account manager:
By default, logs are saved along with the analyses' data. If you need to keep the logs distinct from the analysis data, for as shown below:
This article describes how to get the analysis scores.
When you perform an analysis, the result you get is a number. For biometry, it reflects a chance that the two or more people represented in your media are the same person. For liveness, it shows a chance of deepfake or a spoofing attack: that the person in uploaded media is not a real one. You can get these numbers via API from a JSON response.
.
Make a request to the folder or folder list to get a JSON response. Set the with_analyses parameter to true.
An unallowed method is called. Usually is followed by the 405 HTTP status of response. For example, trying to request the PATCH method, while only GET/POST ones are supported
2
NOT REALIZED
The method is documented but is not realized by any temporary or permanent reason
3
INVALID STRUCTURE
Incorrect structure of request. Some required fields missing or a format validation error occurred
4
INVALID VALUE
Incorrect value of the parameter inside request body or query
5
INVALID TYPE
The invalid data type of the request parameter
6
AUTH NOT PROVIDED
Access token not specified
7
AUTH INVALID
The access token does not exist in the database
8
AUTH EXPIRED
Access token is expired
9
AUTH FORBIDDEN
Access denied for the current user
10
NOT EXIST
The requested resource is not found (alternative of HTTP status_code = 404)
11
EXTERNAL SERVICE
Error in the external information system
12
DATABASE
Critical database error on the server host
Invalid request data
No media have been added into container
5
Invalid request data
Container is damaged
13
Invalid request data
API didn’t receive the container
14
Invalid request data
The container appears to be affected by errors and can’t be unpackaged,
or Oz API (Full) detected a repeat analysis on OzCapsula media after a failed analysis
In API 6.0, we've implemented new analysis modes:
Single RequestInstant API: Non-Persistent Mode
OZSDK.setApiConnection(Connection.fromServiceToken(host: "https://<link>.ozforensics.com", token: token, sslPins: pins)) { (token, error) in
}OZSDK.setApiConnection(Connection.fromCredentials(host: “https://<link>.ozforensics.com”, login: login, password: password, sslPins: pins)) { (token, error) in
// Your code to handle error or token
}For the Biometry analysis, check the response for the min_confidence value:
This value is a quantitative result of matching the people on the media uploaded.
4. For the Liveness Analysis, seek the confidence_spoofing value related to the video you need:
This value is a chance that a person is not a real one.
To process a bunch of analysis results, you can parse the appropriate JSON response.
"items":
[
{
"analyses":
[
{
"analysis_id": "biometry_analysis_id"
"folder_id": "some_folder_id",
"type": "BIOMETRY",
"state": "FINISHED",
"results_data":
{
"max_confidence": 0.997926354,
"min_confidence": 0.997926354
}/api/folders/?meta_data=transaction_id==unique_id1&with_analyses=true/api/folders/?meta_data=transaction_id==unique_id1&with_analyses=true&time_created.min=([CURRENT_TIME]-1hour)"result_mode": "safe"{
"state": "finished",
"folder_id": "your_folder_id",
"analyses": {
"quality": {
"state": "finished",
"resolution": "SUCCESS"
}
}
}let eventsConnection = Connection.fromCredentials(host: https://echo.cdn.ozforensics.com/,
login: <your_telemetry_user_eg_tm@company.com>,
password: your_telemetry_password)
OZSDK.setEventsConnection(eventsConnection) { (token, error) in
}"items":
[
{
"analyses":
[
{
"source_media":
[
{
"media_id": "your_media_id",
"media_type": "VIDEO_FOLDER",
}
]
"results_media":
[
"analysis_id": "liveness_analysis_id",
"results_data":
{
"confidence_spoofing": 0.55790174
}VIDEOSHOTS_SETSHOTS_SETBelow, you will find the tags and type requirements for all analyses. If a media doesn’t match the requirements for the certain analysis, this media is ignored by algorithms.
The rules listed below act by default. To change the mapping configuration, please contact us.
This analysis is applied to all media, regardless of the gesture recorded (gesture tags begin from video_selfie).
Important: to process a photo in API 4.0.8 and below, pack it into a .zip archive, apply the SHOTS_SET type, and mark it with video_*. Otherwise, it will be ignored.
This analysis is applied to all media.
If the folder contains less than two matching media files, the system will return an error. If there are more than two files, then all pairs will be compared, and the system will return a result for the pair with the least similar faces.
This analysis works only when you have a pre-made image database, which is called collection. The analysis is applied to all media in the folder (or the ones marked as source media).
Best Shot is an addition to the Quality (Liveness) analysis. It requires the appropriate option enabled. The analysis is applied to all media files that can be processed by the Quality analysis.
The Documents analysis is applied to images as listed below. This is the priority list: if the higher priority option is present, others are ignored.
Images with IDs listed in source_media:
Images with tags photo_id_front and photo_id_back (documents), and photo_selfie (selfie).
If there is no media listed in source_media or with one of these tags, untagged media is picked.
The result will be positive if the system finds the selfie photo and matches it with a photo on one of the valid documents from the following list:
personal ID card
driver license
foreign passport
Code
Message
Description
202
Could not locate face on source media [media_id]
No face is found in the media that is being processed, or the source media has wrong (photo_id_back) or/and missing tag used for the media.
"source_media": ["media1_id", "media2_id", "$media3_id"]Lower maintenance cost as Oz maintains and upgrades server components.
No cross-border data transfer for the regions where Oz has cloud instances.
The on-premise model implies that all the Oz components required are installed within your infrastructure. Choose on-premise for:
Your data not leaving your infrastructure.
Full and detailed control over the configuration.
The choice is yours to make, but we're always available to provide assistance.
This article covers the use case when you need to perform face matching with an external photo while using OzCapsula for data transmission. Here is what you need to do.
Depending on the API configuration:
Instant API: run a Liveness analysis using OzCapsula with the best shot extraction enabled. This best shot is then used for comparison.
Full API: launch a regular Liveness analysis.
Run a face matching request without OzCapsula. Matching happens on the backend, so secure data transmission isn't needed.
These parameters are mandatory for OzCapsula to work. Define them in your API configuration file.
The instructions below show how to adjust the flow for each API configuration.
The best shot is a frame from the Liveness video where the face is most clearly seen. When best shot extraction is enabled, the server selects this frame during the Quality (Liveness) analysis and stores it in the same folder as the source video, so it can be reused as input for the face matching (Biometry) analysis without recapturing media.
This section describes where to switch on the best shot extraction in each Oz SDK.
Add extract_best_shot to the params map of the AnalysisProfile whose type is QUALITY, inside CaptureRequest.analysisProfileList
After this, run createMediaCaptureScreen(captureRequest, session_token) to get the data container and send it to analysis with addContainer(container) — exactly as in the standard OzCapsula flow.
After this, run createMediaCaptureScreen(request: captureRequest, session_token: token) to get the data container and send it to analysis with addContainer(container).
This guide describes the steps needed to add face matching to your liveness check.
By this time you should have already implemented liveness video recording and liveness check. If not, please refer to these guides:
How to Integrate Oz Liveness into Your Web Application
How to Integrate Oz Liveness into Your Mobile Application
Simply add photo_id_front to the list of actions for the plugin, e.g.,
OzLiveness.open({
session_token,
lang: 'en',
action: [
'photo_id_front',
'video_selfie_blank'
],
...
});For the purpose of this guide, it is assumed that your reference photo (e.g., front side of an ID) is stored on the device as reference.jpg.
Modify the code that runs the analysis as follows:
Check also the Android source code.
For the purpose of this guide, it is assumed that your reference photo (e.g., front side of an ID) is stored on the device as reference.jpg.
Modify the code that runs the analysis as follows:
Check also the iOS source code.
You will be able to access your media and analysis results in Web UI via browser or programmatically via API.
Oz API methods as well as Mobile and Web SDK methods can be combined with great flexibility. Explore the options available in the section.
The plugin window is launched with open(options) method:
OzLiveness.open({
// omit session_token if your SDK version is older than 1.9.2
session_token,
lang: 'en',
action: [
'photo_id_front', // request photo ID picture
// you can add several gestures here for the multi-gesture scenario
// 'video_selfie_smile',
// 'video_selfie_eyes',
'video_selfie_blank' // request passive liveness video
],
meta: {
// an ID of user undergoing the check
// add for easier conversion calculation
'end_user_id': '<user_or_lead_id>',
// Your unique identifier that you can use later to find this folder in Oz API
// Optional, yet recommended
'transaction_id': '<your_transaction_id>',
// You can add iin if you plan to group transactions by the person identifier
'iin': '<your_client_iin>',
// Other meta data
'meta_key': 'meta_value',
},
on_error: function (result) {
// error details
console.error('on_error', result);
},
on_complete: function (result) {
// This callback is invoked when the analysis is complete
// It is recommended to commence the transaction on your backend,
// using transaction_id to find the folder in Oz API and get the results
console.log('on_complete', result);
},
on_capture_complete: function (result) {
// Handle captured data here if necessary
console.log('on_capture_complete', result);
}
});Call GET /api/folders/?meta_data=transaction_id==<your_transaction_id> to find a folder in Oz API from your backend by your unique identifier.
Read more about Oz API.
The full list of OzLiveness.open() parameters:
options – an object with the following settings:
session_token – a specific token required to use OzCapsula data container.
token – (optional) the auth token;
license – an object containing the license data;
Here’s a step-by-step guide on how to issue a service token in Oz API 5 and 6.
Authorize using your ADMIN account: {{host}}/api/authorize/auth.
curl -L 'https://{{host}}/api/authorize/auth' \
-H 'Content-Type: application/json' \
--data-raw '{
"credentials": {
"email": "admin_email@email.com",
"password": "your_admin_password"
}
}'{
…
"user": {
"user_type": "ADMIN",
…
},
"access_token": "<token>",
…
}As a user must belong to a company, create a company: call {{host}}/api/companies/ with your company name.
curl -L 'https://{{host}}/api/companies/'
-H 'X-Forensic-Access-Token: token_id'
-H 'Content-Type: application/json'
-d '{ "name": "your_company_name" }'{
"company_id": "company_id",
"name": "your_company_name",
"in_deletion": false,
"technical_meta_data": {}
}Create a service user. Call {{host}}/api/users/ and write down user_id that you will get in response.
As in API 6.0, the logic of issuing a service token has slightly changed, here are examples for both API 6 and API 5 (and below) cases.
In the request body, define user_type as CLIENT_SERVICE.
Set the is_service flag value to true.
If you need to obtain the service token to use it, for instance, with Web SDK, authorize as ADMIN (same as in Step 1) and call:
API 6: {{host}}/api/authorize/service_token/{user_id} with user_id from the previous step.
API 5 and below: {{host}}/api/authorize/service_token.
To set your own look-and-feel options, use the style section in the Ozliveness.open method. Here is what you can change:
faceFrame – the color of the frame around a face:
faceReady – the frame color when the face is correctly placed within the frame;
faceNotReady – the frame color when the face is placed improperly and can't be analyzed.
centerHint – the text of the hint that is displayed in the center.
textSize – the size of the text;
color – the color of the text;
closeButton – the button that closes the plugin:
image – the button image, can be an image in PNG or dataURL in base64.
backgroundOutsideFrame – the color of the overlay filling (outside the frame):
color – the fill color.
Example:
To improve the overall security level or Oz products, we’ve introduced a new proprietary data exchange format that provides improved data confidentiality and integrity: OzCapsula.
A proprietary data exchange format is a container that safely stores and transmits transaction-related media data.
When you capture video using Oz SDK, your media is placed into the OzCapsula container along with all required information. The package can be processed only in Oz API due to internal mechanisms, so it is significantly more difficult to access the package containing.
Integrity and Authenticity Guaranteed. Each container’s content is verified by the API, ensuring data arriving from the user device is genuine, untampered, and fully intact.
Full Confidentiality of Internal Data. Multi-layered cryptographic protection keeps all data, metadata, and technical details hidden from unauthorized viewing, extraction, or interpretation.
Unified Data Package. All content is stored in a single, secure file, simplifying transmission and enabling consistent, predictable processing.
Built-In Investigation Tools. Every action within the container is logged, giving complete visibility for incident analysis and rapid troubleshooting.
Strict, Built-In Access Control. Only authorized systems can open or use the container, preventing misuse, tampering attempts, or unauthorized integration.
Ready for High-Volume Workflows. The container is designed to scale effortlessly, supporting any number of transmissions without performance or integration issues.
Minimal component versions:
API: 6.6.1.
Web SDK: 1.9.10.
Native SDKs: 10.0.0.
You will also require a new token: session_token.
Configure SDK and API:
Native SDK doesn't require additional configuration, you'll just need to use new methods.
Add the following URL to the build.gradle of the project:
allprojects {
repositories {
maven { url "https://ozforensics.jfrog.io/artifactory/main" }
}
}Add this to the build.gradle of the module (VERSION is the version you need to implement. Please refer to Changelog):
dependencies {
implementation 'com.ozforensics.liveness:sdk:VERSION'
}Also add:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}From 8.18.0, you can move the SDK into a Google Dynamic Feature module and load it on demand. Since most of the SDK's size comes from its native .so files, moving all SDK interaction into a separate module can noticeably reduce your base app size.
To support this, the SDK exposes an onContextAttachListener callback that fires from attachBaseContext inside the SDK's Activity, so you can call SplitCompat.installActivity() when needed:
Please note: for the plugin to work, your browser version should support JavaScript ES6 and be the one as follows or newer.
Google Chrome (and other browsers based on the Chromium engine)
56
*Web SDK doesn't work in Internet Explorer compatibility mode due to lack of important functions.
WebAssembly support is also required.
Download and install the Postman client from this page. Then download the JSON file needed:
Launch the client and import Oz API Lite collection for Postman by clicking the Import button:
Click files, locate the JSON needed, and hit Open to add it:
The collection will be imported and will appear in the Postman interface:
This article describes Oz components that can be integrated into your infrastructure in various combinations depending on your needs.
The typical integration scenarios are described in the Integration Quick Start Guides section.
Oz API is the central component of the system. It provides RESTful application programming interface to the core functionality of Liveness and Face matching analyses, along with many important supplemental features:
Persistence: your media and analyses are stored for future reference unless you explicitly delete them,
Authentication, roles and access management,
Asynchronous analyses,
Ability to work with videos as well as images.
For more information, please refer to and . To test Oz API, please check the Postman collection .
Under the logical hood, Oz API has the following components:
File storage and database where media, analyses, and other data are stored,
The Oz BIO module that runs neural network models to perform facial biometry magic,
Licensing logic.
The front-end components (Oz Liveness Mobile or Web SDK) connect to Oz API to perform server-side analyses either directly or via customer's back end.
iOS and Android SDK are collectively referred to as Mobile SDKs or Native SDKs. They are written on Swift and Kotlin/Java, respectively, and designed to be integrated into your native mobile application.
Mobile SDKs implement the out-of-the-box customizable user interface for capturing Liveness video and ensure that the two main objectives are met:
The capture process is smooth for users,
The quality of a video is optimal for the subsequent Liveness analysis.
After Liveness video is recorded and available to your mobile application, you can run the server-side analysis. You can use corresponding SDK methods, call the API directly from your mobile application, or pass the media to your backend and interact with Oz API from there.
The basic integration option is described in the .
Web Adapter and Web Plugin together constitute Web SDK.
Web SDK is designed to be integrated into your web applications and have the same main goals as Mobile SDKs:
The capture process is smooth for users,
The quality of a video is optimal for the subsequent Liveness analysis.
Web Adapter needs to be set up on a server side. Web Plugin is called by your web application and works in a browser context. It communicates with Web Adapter, which, in turn, communicates with Oz API.
Web SDK adds the two-layer protection against injection attacks:
Collects information about browser context and camera properties to detect usage of virtual cameras or other injection methods.
Records liveness video in a format that allows server-side neural networks to search for traces of injection attack in the video itself.
Check the for the basic integration scenario, and explore the for more details.
Web UI is a convenient user interface that allows to explore the stored API data in the easy way. It relies on API authentication and database and does not store any data on its own.
Web console has an intuitive interface, yet the user guide is available .
This callback is called after the check is completed. It retrieves the analysis result (unavailable for the capture mode). The result content depends on the Web Adapter result_mode configuration parameter.
When result_mode is safe, the on_complete callback contains the state of the analysis only:
{
"state": "finished"
}For the status value, the callback contains the state of the analysis, and for each of the analysis types, the name of the type, state, and resolution.
{
"state": "finished",
"analyses": {
"quality": {
"state": "finished",
"resolution": "SUCCESS"
}
}
}The folder value is almost similar to the status value, with the only difference: the folder_id is added.
In this case, you receive the detailed response possibly containing sensitive data. This mode is deprecated; for security reasons, we recommend using the safe mode.
The description of the objects you can find in Oz Forensics system.
System objects on Oz Forensics products are hierarchically structured as shown in the picture below.
On the top level, there is a Company. You can use one copy of Oz API to work with several companies.
The next level is a User. A company can contain any amount of users. There are several roles of users with different permissions. For more information, refer to .
When a user requests an analysis (or analyses), a new folder is created. This folder contains media. One user can create any number of folders. Each folder can contain any amount of media. A user applies analyses to one or more media within a folder. The rules of assigning analyses are described . The media quality requirements are listed on .
In 8.8.0, we’ve implemented SSL pinning to protect our clients from MITM attacks. We strongly recommend adding a built-in certificate whitelist to your application to prevent fraud with third-party certificates set as trusted.
You can add a list of certificates your application should trust at the moment of connection to Oz API via the optional sslPins field of OzConnection class. As an input, this field takes a list of public certificate key hashes with their expiration dates as shown below:
Go to the website.
Enter your domain address. Once the address is processed, you’ll see a list of your servers.
Metadata is any optional data you might need to add to a . In the meta_data section, you can include any information you want, simply by providing any number of fields with their values:
Metadata is available for most Oz system objects. Here is the list of these objects with the API methods required to add metadata. Please note: you can also add metadata to these objects during their creation.
Describing how passive and active liveness works.
The objective of the Liveness check is to verify the authenticity and physical presence of an individual in front of the camera. In the passive Liveness check, it is sufficient to capture a user's face while they look into the camera. Conversely, the active Liveness check requires the user to perform an action such as smiling, blinking, or turning their head. While passive Liveness is more user-friendly, active Liveness may be necessary in some situations to confirm that the user is aware of undergoing the Liveness check.
In our Mobile or Web SDKs, you can define what action the user is required to do. You can also combine several actions into a sequence. Actions vary in the following dimensions:
User experience,
Mozilla Firefox
55
Safari
11
Microsoft Edge*
17
Opera
47
202
Biometry. Analysis requires at least 2 media objects to process
The algorithms did not find the two appropriate media for analysis. This might happen when only a single media has been sent for the analysis, or a media is missing a tag.
202
Processing error - did not found any document candidates on image
The Documents analysis can't be finished because the photo uploaded seems not to be a document, or it has wrong (not photo_id_*) or/and missing tags.
400
Can't start analysis without media
The Documents analysis can't find a document photo due to wrong tags
5
Invalid/missed tag values to process quality check
The tags applied can't be processed by the Quality algorithm (most likely, the tags begin from photo_*; for Quality, they should be marked as video_*)
5
Invalid/missed tag values to process collection check
The tags applied can't be processed by the Collection algorithm. This might happen when a media is missing a tag.
RAM: 32 GB
Disk: 80 GB
Oz API / Web UI / Web SDK Server
OS: OS: please check versions here
CPU: 8 cores
RAM: 16 GB
Disk: 300 GB
Please check the OS version with our team.
On your backend, obtain a session token as described here to use it on the frontend.
Using Oz SDK methods, take a video and package it along with all required data into container:
Send the container to Oz API using Oz SDK or through your backend (optional) and get the results.





yPosition – the vertical position measured from top;
letterSpacing – the spacing between letters;
fontStyle – the style of font (bold, italic, etc.).
OzLivenessSDK.config.onContextAttachListener = object : OnContextAttachListener {
override fun onContextAttached(context: Context) {
SplitActivity.installActivity(this)
}
}PATCH /api/users/{{user_id}}
Folder
PATCH /api/folders/{{folder_id}}/meta_data/
Media
PATCH /api/media/{{media_id}}/meta_data
Analysis
PATCH /api/analyses/{{analyse_id}}/meta_data
Collection
PATCH /api/collections/{{collection_id}}/meta_data/
and, for a person in a collection,
PATCH /api/collections/{{collection_id}}/persons/{{person_id}}/meta_data
You can also change or delete metadata. Please refer to our API documentation.
You may want to use metadata to group folders by a person or lead. For example, if you want to calculate conversion when a single lead makes several Liveness attempts, just add the person/lead identifier to the folder metadata.
Here is how to add the client ID iin to a folder object.
In the request body, add:
Another case is security: when you need to process the analyses’ result from your back end, but don’t want to perform this using the folder ID. Add an ID (transaction_id) to this folder and use this ID to search for the required information. This case is thoroughly explained here.
If you store PII in metadata, make sure it complies with the relevant regulatory requirements.
You can also add metadata via SDK to process the information later using API methods. Please refer to the corresponding SDK sections:
Object
API Method
User
private fun analyzeMedia(mediaList: List<OzAbstractMedia>) {
val refFile = File(context.filesDir, "reference.jpg")
val refMedia = OzAbstractMedia.OzDocumentPhoto(
OzMediaTag.PhotoIdFront , // OzMediaTag.PhotoSelfie for a non-ID photo
refFile.absolutePath
)
AnalysisRequest.Builder()
.addAnalysis(Analysis(Analysis.Type.QUALITY, Analysis.Mode.SERVER_BASED, mediaList))
.addAnalysis(Analysis(Analysis.Type.BIOMETRY, Analysis.Mode.SERVER_BASED, mediaList + refMedia))
.build()
.run(object : AnalysisRequest.AnalysisListener {
override fun onSuccess(result: List<OzAnalysisResult>) {
result.forEach {
println(it.resolution.name)
println(it.folderId)
}
}
override fun onError(error: OzException) {
error.printStackTrace()
}
})
} private void analyzeMedia(List<OzAbstractMedia> mediaList) {
File refFile = new File(context.getFilesDir(), "reference.jpg");
OzAbstractMedia refMedia = new OzAbstractMedia.OzDocumentPhoto(
OzMediaTag.PhotoIdFront , // OzMediaTag.PhotoSelfie for a non-ID photo
refFile.getAbsolutePath()
);
ArrayList<OzAbstractMedia> mediaWithReferencePhoto = new ArrayList<>(mediaList);
mediaWithReferencePhoto.add(refMedia);
new AnalysisRequest.Builder()
.addAnalysis(new Analysis(Analysis.Type.QUALITY, Analysis.Mode.SERVER_BASED, mediaList, Collections.emptyMap()))
.addAnalysis(new Analysis(Analysis.Type.BIOMETRY, Analysis.Mode.SERVER_BASED, mediaWithReferencePhoto, Collections.emptyMap()))
.build()
.run(new AnalysisRequest.AnalysisListener() {
@Override public void onStatusChange(@NonNull AnalysisRequest.AnalysisStatus analysisStatus) {}
@Override
public void onSuccess(@NonNull List<OzAnalysisResult> list) {
String folderId = list.get(0).getFolderId();
}
@Override
public void onError(@NonNull OzException e) { e.printStackTrace(); }
});
}let imageURL = URL(fileURLWithPath: NSTemporaryDirectory())
.appendingPathComponent("reference.jpg")
let refMedia = OZMedia.init(movement: .selfie,
mediaType: .movement,
metaData: nil,
videoURL: nil,
bestShotURL: imageUrl,
preferredMediaURL: nil,
timestamp: Date())
var mediaBiometry = [OZMedia]()
mediaBiometry.append(refMedia)
mediaBiometry.append(contentsOf: mediaToAnalyze)
let analysisRequest = AnalysisRequestBuilder()
let analysisBiometry = Analysis.init(media: mediaBiometry, type: .biometry, mode: .serverBased)
let analysisQuality = Analysis.init(media: mediaToAnalyze, type: .quality, mode: .serverBased)
analysisRequest.addAnalysis(analysisBiometry)
analysisRequest.addAnalysis(analysisQuality)
analysisRequest.uploadMedia(mediaBiometry)
analysisRequest.run(
scenarioStateHandler: { state in }, // scenario steps progress handler
uploadProgressHandler: { (progress) in } // file upload progress handler
) { (analysisResults : [OzAnalysisResult], error) in
// receive and handle analyses results here
for result in analysisResults {
print(result.resolution)
print(result.folderID)
}
}OzLiveness.open({
// ...
style: {
// the backward compatibility block
doc_color: "",
face_color_success: "",
face_color_fail: "",
// the current customization block
faceFrame: {
faceReady: "",
faceNotReady: "",
},
centerHint: {
textSize: "",
color: "",
yPosition: "",
letterSpacing: "",
fontStyle: "",
},
closeButton: {
image: "",
},
backgroundOutsideFrame: {
color: "",
},
},
// ...
});{
"state": "finished",
"folder_id": "your_folder_id",
"analyses": {
"quality": {
"state": "finished",
"resolution": "SUCCESS"
}
}
}…
meta_data:
{
"field1": "value1",
"field2": "value2"
}
…{
"iin": "123123123"
}After this, run createMediaCaptureScreen(captureRequest, session_token) to get the data container and send it to analysis with addContainer(container) — exactly as in the standard OzCapsula flow.
Add extract_best_shot to the params of the AnalysisProfile whose type is .quality, inside CaptureRequest.analysisProfileList.
let livenessProfile = AnalysisProfile(
mediaList:
After this, run createMediaCaptureScreen(request: captureRequest, session_token: token) to get the data container and send it to analysis with addContainer(container).
Add extract_best_shot to the params of the object passed to OzLiveness.open(). Unlike the mobile SDKs, this parameter sits at the top level of the launch options, not nested per analysis, and works the same way regardless of whether you use the OzCapsula data container or the legacy flow.
OzLiveness.open({
session_token, // required for OzCapsula (Web SDK 1.9.2+)
action: ['video_selfie_blank'],
params: {
extract_best_shot: true
},
// ... other options
});Instant API returns the best shot in the base64 format. In the response, you will find it in folder.analyses.results_media → output_images → image_b64. Decode the base64 best shot from the Liveness response and save it as a file (e.g., best_shot.jpeg).
Face matching is launched directly via Oz API, without the SDK capture step.
Call POST /api/instant/folders/ with your reference photo and the best shot you've obtained from the Liveness analysis as shown in 1.2.
{
"media:tags": {
"UUID_of_reference_photo.jpeg": ["photo_selfie"],
"best_shot.jpeg": ["photo_selfie"]
},
"analyses": [
{ "type": "biometry" }
]
}The response will contain the result of the biometry analysis.
folder_id and the original name of your media file (video that has been taken) which is in folder.media → original_name.Call Oz API POST /api/folders/{{folder_id}}/analyses/ with folder_id from the response of your Liveness request (Step 1). Set biometry as the analysis type and define what media files to compare in the source_media section. Use the original name and extension of your media file from Step 1, e.g., original_name.zip or original_name.mp4.
The response will contain the result of the biometry analysis.
OZ_SESSION_TOKEN_LIFETIME=<your_ttl_for_session_token>
OZ_JWT_PRIVATE_KEY_PATH=<jwt_private_key_path>
OZ_JWT_PUBLIC_KEY_PATH=<jwt_public_key_path>
OZ_MALEWICZ_ANALYSIS_ENABLED=trueOzLiveness.open({
session_token, // required for OzCapsula (Web SDK 1.9.2+)
action: ['video_selfie_blank'],
// ... other options
});val livenessProfile = AnalysisProfile(
mediaList = listOf(
MediaRequest(
id = UUID.randomUUID().toString(),
actionMedia = OzAction.Smile
)
),
type = "QUALITY"
)
val captureRequest = CaptureRequest(
analysisProfileList = listOf(livenessProfile)
)let livenessProfile = AnalysisProfile(
mediaList: [
MediaRequest(
id: UUID().uuidString,
actionMedia: .smile
)
],
type: .quality
)
let captureRequest = CaptureRequest(
analysisProfileList: [livenessProfile]
)val livenessProfile = AnalysisProfile(
mediaList =
licenseUrl – a string containing the path to the license;
Warning: The license and licenseUrl parameters override the server-side license, including its expiration date. If you use a server-side license, omit these parameters from OzLiveness.open(), otherwise, you might be getting a license error.
lang – a string containing the identifier of one of the installed language packs;
meta – an object with names of meta fields in keys and their string values in values. Metadata is transferred to Oz API and can be used to obtain analysis results or for searching;
params – an object with identifiers and additional parameters:
extract_best_shot – true or false: run the best frame choice in the Quality analysis;
action – an array of strings with identifiers of actions to be performed.
Available actions:
photo_id_front – photo of the ID front side;
photo_id_back – photo of the ID back side;
video_selfie_left – turn head to the left;
video_selfie_right – turn head to the right;
video_selfie_down – tilt head downwards;
video_selfie_high – raise head up;
video_selfie_smile – smile;
video_selfie_eyes – blink;
video_selfie_scan – scanning;
video_selfie_blank – no action, simple selfie;
video_selfie_best – special action to select the best shot from a video and perform analysis on it instead of the full video.
On January 1, 2027, the One Shot gesture will become unavailable. Please plan your .
overlay_options – the document's template displaying options:
show_document_pattern: true/false – true by default, displays a template image, if set to false, the image is replaced by a rectangular frame;
on_submit – a callback function (no arguments) that is called after submitting customer data to the server (unavailable for the capture mode).
on_capture_complete – a callback function (with one argument) that is called after the video is captured and retrieves the information on this video. The example of the response is described here.
on_result – a callback function (with one argument) that is called periodically during the analysis and retrieves an intermediate result (unavailable for the capture mode). The result content depends on the Web Adapter result_mode configuration parameter and is described here.
on_complete – a callback function (with one argument) that is called after the check is completed and retrieves the analysis result (unavailable for the capture mode). The result content depends on the Web Adapter result_mode configuration parameter and is described here.
on_error – a callback function (with one argument) that is called in case of any error happened during video capturing and retrieves the error information: an object with the error code, error message, and telemetry ID for logging.
on_close – a callback function (no arguments) that is called after the plugin window is closed (whether manually by the user or automatically after the check is completed).
style – the customization section.
device_id – (optional) identifier of camera that is being used. A passed device_id is now always respected: if that camera is unavailable, the Web SDK returns an error. Without device_id, it tries all available cameras. use_for_liveness in the Web Adapter configuration parameters takes priority over device_id.
enable_3d_mask – enables the 3D mask as the default face capture behavior. This parameter works only if load_3d_mask in the Web Adapter configuration parameters is set to true; the default value is false.
On January 1, 2027, 3D Mask will become unavailable. Please plan your migration.
cameraFacingMode (since 1.4.0) – the parameter that defines which camera to use; possible values: user (front camera), environment (rear camera). This parameter only works if the use_for_liveness option in the Web Adapter configuration file is undefined. If use_for_liveness is set (with any value), cameraFacingMode gets overridden and ignored.
disable_adaptive_aspect_ratio (since 1.5.0) – if True, disables the video adaptive aspect ratio, so your video doesn’t automatically adjust to the window aspect ratio. The default value is False, and by default, the video adjusts to the closest ratio of 4:3, 3:4, 16:9, or 9:16. Please note: smartphones still require the portrait orientation to work.
In response, you will get a service token that you can use in any service processes.
curl -L 'https://{{host}}/api/users/'
-H 'X-Forensic-Access-Token: token_id'
-H 'Content-Type: application/json'
--data-raw '{
"credentials": {
"email": "<your_new_service_user@email.com>",
"password": "<your_service_user_password>"
},
"profile": {
"company_id": " company_id",
<!-- the next line is for API 6 -->
"user_type": "CLIENT_SERVICE",
"first_name": "first_name",
"last_name": "last_name",
"middle_name": "",
"is_admin": false,
<!-- the next line is for API 5 and below -->
"is_service": true,
"can_start_analyse_biometry": true,
"can_start_analyse_collection": true,
"can_start_analyse_documents": true,
"can_start_analyse_quality": true
}
}{
"user_id": "user_id",
"user_type": "CLIENT_SERVICE",
…
"is_active": true,
…
"is_service": true
}{
"credentials": {
"email": " <your_new_service_user@email.com> ",
"password": "your_client_service_user_password"
},
"profile": {
"company_id": "{{company_id}}",
"user_type": "CLIENT_SERVICE",
"first_name": "john",
"last_name": "doe",
"middle_name": "",
"can_start_analysis_biometry": true,
"can_start_analysis_collection": true,
"can_start_analysis_documents": true,
"can_start_analysis_quality": true
}
}
{
"credentials": {
"email": "john.doe_client_service@ozforensics.com",
"password": "your_client_service_user_password"
},
"profile": {
"company_id": "{{company_id}}",
"user_type": "CLIENT",
"first_name": "john",
"last_name": "doe",
"middle_name": "",
"is_admin": false,
"is_service": true,
"can_start_analyse_biometry": true,
"can_start_analyse_collection": true,
"can_start_analyse_documents": true,
"can_start_analyse_quality": true
}
}curl -L 'https://{{host}}/api/authorize/service_token/{{user_id}}' \
-H 'X-Forensic-Access-Token: token_id' \
-H 'Content-Type: application/json'{
"token_id": "token_id",
"user_id": "user_id",
"access_token": "service_token",
"expire_date": 1904659888.282587,
"session_id": 0
}time_created
Timestamp
Object (except user and company) creation time
time_updated
Timestamp
Object (except user and company) update time
Besides these parameters, each object type has specific ones.
company_id
UUID
Company ID within the system
name
String
user_id
UUID
User ID within the system
folder_id
UUID
Folder ID within the system
resolution_status
String
A media can be an image, a video, or shots_set (an archive with frames).
media_id
UUID
Media ID
original_name
analyse_id
UUID
ID of the analysis
folder_id

Certificate number one is your host certificate. Your root certificate is in the very bottom of the list. Others are intermediate. For SSL pinning, any of them fits.
The higher the certificate is on the list, the better the level of protection against theft. Thus, if you use the host certificate to pin in your application, you get the highest security level. However, the lifetime of these certificates is significantly shorter than that of intermediate or root certificates. To keep your application secure, you will need to change your pins as soon as they expire; otherwise, functionality might become unavailable.
As a reasonable balance between safety and the resources needed to maintain it, we recommend using intermediate or even root certificate keys for pinning. While the security level is slightly lower, you won’t need to change these pins as often because these certificates have a much longer lifetime.
Certificate owner
Trust level
Resources requirements (depend on the certificate’s lifetime)
Host
Highest
High, but requires the most resources to maintain: keys’ list should be updated at the same time as certificate
Intermediate certificate authority
Above average; the application considers all certificates that have been issued by this authority as trusted
To obtain the hash, run the following command with your server domain and port:
In the response, you’ll receive hash for your SslPin.
To get the certificate’s expiration date, run the next command – again with your server domain and port:
The date you require will be in the notAfter parameter.
We’ll provide you with the hash and date of our API server certificate.
Connection.fromServiceToken(
"your API server host",
"your token",
listOf(
SslPin(
"your hash", // SHA256 key hash in base64
<date> // key expiration date as a UNIX timestamp, UTC time
)
),
)let pins = [SSLPin.pin(
publicKeyHash: "your hash", // SHA256 key hash in base64
expirationDate: date)] // key expiration date as a UNIX timestamp, UTC time
OZSDK.setApiConnection(.fromServiceToken(
host: "your API server host",
token: "your token",
sslPins: pins)) { (token, error) in
//
}echo | openssl s_client -connect {SERVER_DOMAIN_NAME}:{PORT} 2> /dev/null | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary| openssl enc -base64openssl s_client -servername {SERVER_DOMAIN_NAME} -connect {SERVER_DOMAIN_NAME}:{PORT} | openssl x509 -noout -dates
echo -n Q | openssl s_client -servername {SERVER_DOMAIN_NAME} -connect {SERVER_DOMAIN_NAME}:{PORT} | openssl x509 -noout -datesLiveness check accuracy,
Suitability for review by a human operator or in court.
In most cases, the Selfie action is optimal, but you can choose other actions based on your specific needs. Here is a summary of available actions:
Selfie
A short video, around 0.7 sec. Users are not required to do anything. Recommended for most cases. It offers the best combination of user experience and liveness check accuracy.
One shot
Similar to “Simple selfie” but only one image is chosen instead of the whole video. Recommended when media size is the most important factor. Difficult for a human (e.g., an operator or a court) to evaluate as spoofing. We recommend avoiding the one shot gesture whenever possible, as it tends to produce less accurate results. On January 1, 2027, the One Shot gesture will become unavailable. Please plan your .
Scan
A 5-second video where a user is asked to follow the text looking at it. Recommended when the longer video is required, e.g., for subsequent review by a human operator or in a court.
Smile
Blink
Tilt head up
A user is required to complete a particular gesture within 5 seconds.
Use active liveness when you need a confirmation that the user is aware of undergoing a Liveness check.
Video length and file size may vary depending on how soon a user completes a gesture.
Our algorithms use tags to identify which gesture the user performed. For more information, please read the Media Tags article. The detailed information on how the actions, or, in other words, gestures are called in different Oz Liveness components is here.
The Scan gesture is now easier to pass: resolved the issue with conflicting hints.
Files passed via UserMedia in MediaRequest (OzCapsula) are now named using a UUID v4 identifier with the original file extension. The original file name can still be transmitted via the mediaMeta field.
Telemetry observer callbacks (EventObserver.update() and EventObserver.onDetected()) are now dispatched on a background thread.
Enhanced security.
Android:
Added edge-to-edge display support required for Android 16. The UI now correctly adapts to system insets — the close button no longer overlaps the status bar.
The Action rules unavailable error no longer appears on the first liveness attempt.
Sessions that failed with the
iOS:
Removed the OZ_ prefix from cases of the ContainerType.
The One Shot gesture media is now sent as ZIP instead of JPEG.
Resolved the SQLCipher integration conflict.
The analyze method now correctly handles errors from native SDK’s AnalysisRequest.
Android:
Fixed the bug with SDK crashes caused by the “Invalid to call at Released state” and “Pending dequeue output buffer request cancelled” errors.
Fixed the bug with "java.util.concurrent.TimeoutException" causing crashes.
Android SDK now passes orientation and media type tags along with the action one.
Changed the way you add our SDK to pubspec.yaml. Please check the .
Android:
Fixed the bug with green videos on some smartphone models.
Fixed occasional SDK crashes in specific cases and / or on specific devices.
Android:
Resolved an issue with warning that could appear when running Fragment.
SDK no longer crashes when calling copyPlane.
When you choose to send compressed videos for a hybrid analysis, SDK no longer saves original media as well as compressed.
initSDK in the iOS debugging mode now works properly.
You can now .
Fixed an error in the example code.
The Scan gesture hint is now properly voiced.
If you try to delete the reference photo, SDK now asks you to confirm deletion.
Changed the wording for the head_down gesture: the new wording is “tilt down”.
Updated the authorization logic.
Improved voiceover.
Bug fixes.
Security and telemetry updates.
The SDK hints and UI controls can be voiced in accordance to WCAG requirements.
Improved user experience with head movement gestures.
Android:
The executeLiveness method is now deprecated, please use startLiveness instead.
Updated the code needed to obtain the Liveness results.
Security and telemetry updates.
Added descriptions for the errors that occur when providing an empty string as an ID in the addFolderID (iOS) and setFolderID (Android) methods.
Android:
Fixed a bug causing an endless spinner to appear if the user switches to another application during the Liveness check.
Android:
Upgraded the on-device Liveness model.
Security updates.
iOS:
The length of the Selfie gesture is now (affects the video file size).
Removed the pause after the Scan gesture.
Security and logging updates.
Bug fixes.
Android: updated the on-device Liveness model.
iOS: changed the default behavior in case a localization key is missing: now the English string value is displayed instead of a key.
Fixed some bugs.
Implemented the possibility of using a master license that works with any bundle_id.
Fixed the bug with background color flashing.
Video compression failure on some phone models is now fixed.
Initial release.
You can generate the trial license here or contact us by email to get a productive license. To create the license, your bundle id is required. After you get a license file, there are two ways to add the license to your project.
Rename this file to forensics.license and put it into the project. In this case, you don't need to set the path to the license.
During the runtime: when initializing SDK, use the following method.
OZSDK(licenseSources: [.licenseFileName(“forensics.license”)]) { licenseData, error in
if let error = error {
print(error)
}
}or
or
LicenseSource a source of license, and LicenseData is the information about your license (file name, path to file or license data as byte array). Please note: this method checks whether you have an active license or not and if yes, this license won't be replaced with a new one. To force the license replacement, use the setLicense method.
In case of any license errors, the system will use your error handling code as shown above. Otherwise, the system will return information about license. To check the license data manually, use OZSDK.licenseData.
If you want to get back to the previous (up to 6.4.2) versions' design, reset the customization settings of the capture screen and apply the parameters that are listed below.
OzLivenessSDK.config.customization = UICustomization(
// customization parameters for the toolbar
OzLivenessSDK.config().setCustomization(new UICustomization(
// customization parameters for the toolbar
new ToolbarCustomization(
R.drawable.ib_close,
new Color.ColorHex("#FFFFFF"),
new Color.ColorHex("#000000"),
100, // toolbar text opacity (in %)
),
// customization parameters for the center hint
new CenterHintCustomization(
70, // vertical position (in %)
),
// customization parameters for the hint animation
new HintAnimation(
true, // hide animation
),
// customization parameters for the frame around the user face
new FaceFrameCustomization(
new Color.ColorHex("#EC574B"),
new Color.ColorHex("#00FF00"),
6, // frame stroke width (in dp)
),
// customization parameters for the background outside the frame
new BackgroundCustomization(
100 // background opacity (in %)
),
)
);This article describes the main types of analyses Oz software performs.
Liveness checks whether a person in a media is a real human.
Face Matching examines two or more media to identify similarities between the faces depicted in them.
Collection looks for resemblances between an individual featured in a media and individuals in a pre-existing photo database.
These analyses are accessible in the Oz API for both SaaS and On-Premise models. Please visit to learn more about the usage models.
Liveness protects against two types of attacks:
A presentation attack, also known as a spoofing attack, refers to the attempt of an individual to deceive a facial recognition system by presenting into a camera video, photo, or any other type of media that mimics the appearance of a genuine user. These attacks can include the use of realistic masks or make up.
An injection attack is an attempt to deceive a facial recognition system by replacing physical camera input with a prerecorded image or video, manipulating physical camera output before it becomes input to a facial recognition, or injecting some malicious code. Virtual camera software is the most common tool for injection attacks.
Oz Liveness is able to detect both types of attacks. Any component can detect presentation attacks, and for injection attack detection, use Oz Liveness SDK. To learn about how to use Oz components to prevent attacks, check our integration quick start guides:
Once the Liveness check is finished, you can check the results.
Asking users to perform a gesture, such as smiling or turning their head, is a popular requirement when recording a Liveness video. With Oz Liveness Mobile and Web SDK, you can also request gestures from users. However, our Liveness check relies on other factors, analyzed by neural networks, and does not depend on gestures. For more details, please check .
Liveness check also can return the best shot from a video: a best-quality frame where the face is seen the most properly.
The Biometry algorithm allows comparing several media and checking whether the people on them are the same person. As sources, you can use images, videos, and scans of documents (with photo). To perform the analysis, the algorithm requires at least two media.
To learn how to integrate Face Matching, please refer to the .
In Oz API, you can configure one or more face collections. These collections are databases of people depicted in photos. When the Collection analysis is being conducted, Oz software compares the face in a photo or video taken with faces of this pre-made database and shows whether a face exists in a collection.
For additional information, please refer to .
Here, you'll get acquainted with types of analyses that Oz API provides and will learn how to interpret the output.
Using Oz API, you can perform one of the following analyses:
documents (deprecated),
.
The Biometry algorithm allows comparing several media and check if the people on them are the same person or not. As sources, you can use images, videos, and scans of documents (with photo). To perform the analysis, the algorithm requires at least two media (for details, please refer to ).
The Liveness detection (Quality) algorithm aims to check whether a person in a media is a real human acting in good faith, not a fake of any kind.
The Best Shot algorithm checks for the best shot from a video (a best-quality frame where the face is seen the most properly). It is an addition to liveness.
The Documents analysis aims to recognize the document and check if its fields are correct according to its type.
As an output, you'll get a list of document fields with recognition results for each field and a result of checking that can be:
The documents passed the check successfully,
The documents failed to pass the check.
Additionally, the result of Biometry check is displayed.
The Collection checking algorithm is used to determine whether the person on a photo or video is present in the database of pre-uploaded images. The person's face is being compared with the faces of known swindlers or a list of VIPs depending on your needs.
Oz Liveness Web SDK implements the ready-to-use face capture user interface that is essential for seamless customer experience and accurate liveness results. The SDK detects both presentation and injection attacks.
This guide walks you through your first liveness check using Web SDK and Oz API. Here, we cover the .
The described flow combines:
Capture mode – the Web SDK (or Mobile SDK) captures the Liveness video in the browser/app and the Client backend forwards it to Oz API. Capture results are not sent from the SDK straight to Oz API; the Client backend acts as an intermediary.
OzCapsula – a proprietary encrypted binary container. The SDK packages the captured media into it; only Oz API can decrypt and process it. On the device it is an opaque blob – you cannot decode or inspect it, only forward it as-is.
We recommend applying these settings when starting the app.
To customize the Oz Liveness interface, use UIcustomization as shown below. For the description of customization parameters, please refer to Android SDK Methods and Properties.
By default, SDK uses the locale of the device. To switch the locale, use the code below:
To generate the license, we need the domain name of the website where you are going to use Oz Forensics Web SDK, for instance, your-website.com. You can also define subdomains.
Set the license as shown below:
With license data:
With license path:
Check whether the license is updated properly.
To launch one or more analyses for your media files, you need to create a folder via Oz API (or use an existing folder) and put the files into this folder. Each file should be marked by : they describe what's pictured in a media and determine the applicable analyses.
To create a folder and upload media to it, call POST /api/folders/
To add files to the existing folder, call POST /api/folders/{{folder_id}}/media/
Add the files to the request body; tags should be specified in the payload.
Here's the example of the payload for a passive Liveness video and ID front side photo.
An example of usage (Postman):
meta_data
JSON
Any user parameters
technical_meta_data
JSON
Module-required parameters; reserved for internal needs
Company name within the system
user_type
String
first_name
String
Name
last_name
String
Surname
middle_name
String
Middle name
String
User email = login
password
String
User password (only required for new users or to change)
can_start_analyze_*
String
Depends on user roles
company_id
UUID
Current user company’s ID within the system
is_admin
Boolean
Whether this user is an admin or not
is_service
Boolean
Whether this user account is service or not
The latter analysis status
String
Original filename (how the file was called on the client machine)
original_url
String
HTTP link to this file on the API server
tags
Array(String)
List of tags for this file
UUID
ID of the folder
type
String
Analysis type: BIOMETRY for face matching or QUALITY for Liveness
results_data
JSON
Results of the analysis
CameraDevice was already closedVIDEO_RECORD_ERRORVideos captured in the Hybrid analysis flow are now compressed correctly.
A rare codec-related crash during liveness recording no longer appears.
Rebuilt TensorFlow Lite with 16 KB page alignment to comply with Google's updated requirements; the RELRO alignment warning at build/publish no longer occurs.
Removed the OzForensics namespace reference from the Android manifest.
The unbalanced dispatch_group_leave() crash on session timeout no longer occurs.
Fixed the bug with green videos appearing on some devices.
Resolved the issue with occasional SDK crashes caused by restrictions of device camera.
Fixed minor bugs.
Enhanced security.
iOS:
Now you can set a custom localization. Use the setLocalizationValue method.
Long antiscam messages are now displayed properly.
SDK no longer crashes when Liveness screen is called several times in a row with short intervals.
Resolved the issue with container errors not being returned.
Resolved the issue with mediaId appearing null.
Improved SDK performance for some devices.
Updated SDK to support the upcoming security features.
Enhanced security.
iOS:
Fixed the bug with crashes that might happen during the Biometry analysis after taking a reference photo using camera.
Resolved the issue with SDK not returning the license-related callbacks.
Resolved the issue with SDK sometimes not responding to user actions on some devices.
Updated SDK to support the upcoming security features.
Enhanced security.
iOS:
The Scan gesture animation now works properly.
Fixed the bug where SDK didn’t call completion during initialization in debug mode.
Enhanced security.
Background is no longer dark when you launch SDK.
SDK no longer flips one of the images during the Biometry analysis.
Fixed some bugs related to the on-device and hybrid analysis types.
Android:
Added support for Google Dynamic Feature Delivery.
Resolved the issue with possible SDK crashes when closing the Liveness screen.
iOS:
Resolved the issue with integration via Swift UI.
Enhanced security and updated telemetry.
Security updates.
Android: you can now disable video validation that has been implemented to avoid recording extremely short videos (3 frames and less).
iOS:
SDK now compresses videos if their size exceeds 10 MB.
Head movement gestures are now handled properly.
Xcode updated to version 16 to comply with Apple requirements.
Moved the large video compression step to the Liveness screen closure.
Fixed the bug when the best shot frame could contain an image with closed eyes.
Resolved codec issues on some smartphone models.
Fixed the bug when the recorded videos might appear green.
iOS:
Added Xcode 16 support.
The screen brightness no longer changes when the rear camera is used.
Fixed the video recording issues on some smartphone models.
Fixed some smartphone model specific-bugs.
Security and logging updates.
The messages displayed by the SDK after uploading media have been synchronized with Android.
The bug causing analysis delays that might have occurred for the One Shot gesture has been fixed.
Android: if the recorded video is larger than 10 MB, it gets compressed.
Turn head left
Turn head right
Average
Root certificate authority
Average; the application considers all certificates that have been issued by this authority as trusted, including the intermediate authority-issued certificates
Low


The license data is missing. Please check it.
License error. Cannot parse license from (your_URI), invalid format
The license file is somehow damaged. Please email us the file.
License error. Bundle company.application.id is not in the list allowed by license (bundle.id1, bundle.id2)
The bundle (application) identifier you specified is missing in the allowed list. Please check the spelling, if it is correct, you need to get another license for your application.
License error. Current date yyyy-mm-dd hh:mm:ss is later than license expiration date yyyy-mm-dd hh:mm:ss
Your license has expired. Please contact us.
License is not initialized.
You haven't initialized the license. Please add the license to your project as described above.
License error. License not found
The license file is missing. Please check its name.
License error. License at (your_URI) not found
The license file is missing. Please check path to the file.
The license data is invalid. Please contact us.
// connecting to the API server
OzLivenessSDK.setApiConnection(OzConnection.fromServiceToken(HOST, TOKEN))
// settings for the number of attempts to detect an action
OzLivenessSDK.config.attemptSettings = attemptSettings
// the possibility to display additional debug information (you can do it by clicking the SDK version number)
OzLivenessSDK.config.allowDebugVisualization = allowDebugVisualization
// logging settings
OzLivenessSDK.config.logging = ozLogging OzLivenessSDK.config.customization = UICustomization().apply {
// customization parameters for the toolbar
toolbarCustomization.apply {
closeButtonIcon = R.drawable.ic_close
closeButtonColor = Color.ColorRes(R.color.white)
titleText = "Liveness"
titleFont = R.font.roboto
titleSize = 18
titleColor = Color.ColorRes(R.color.white)
titleAlpha = 100
isTitleCentered = true
backgroundColor = Color.ColorRes(R.color.black)
backgroundAlpha = 60
}
// customization parameters for the center hint
centerHintCustomization.apply {
textFont = R.font.roboto
textColor = Color.ColorRes(R.color.white)
textSize = 20
textStyle = R.style.Sdk_Text_Primary
backgroundColor = Color.ColorRes(R.color.black)
backgroundOpacity = 56
backgroundCornerRadius = 14
textAlpha = 100
}
// customization parameters for the hint animation
hintAnimation.apply {
hintGradientColor = Color.ColorRes(R.color.error_red)
hintGradientOpacity = 80
animationIconSize = 120
hideAnimation = false
}
// customization parameters for the frame around the user face
faceFrameCustomization.apply {
geometryType = GeometryType.Rectangle(10) // 10 is the corner radius
strokeWidth = 5
strokeFaceNotAlignedColor = Color.ColorRes(R.color.error_red)
strokeFaceAlignedColor = Color.ColorRes(R.color.success_green)
strokeAlpha = 100
verticalPosition = 50
strokePadding = 3
}
// customization parameters for the SDK version label
versionLabelCustomization.apply {
textFont = R.font.roboto
textSize = 12
textColor = Color.ColorRes(R.color.white)
textAlpha = 100
}
// customization parameters for the background outside the frame
backgroundCustomization.apply {
backgroundColor = Color.ColorRes(R.color.black)
backgroundAlpha = 60
}
// hides the status bar and the navigation buttons
hideStatusBar = true
// customization parameters for the antiscam protection text
antiScamCustomization = AntiScamCustomization().apply {
textMessage = "Recording..."
textFont = R.font.roboto
textSize = 14
textColor = Color.ColorRes(R.color.white)
textAlpha = 100
backgroundColor = Color.ColorRes(R.color.black)
backgroundOpacity = 100
cornerRadius = 20
flashColor = Color.ColorRes(R.color.success_green)
}
// custom logo parameters, all four are required
// must be allowed by the license
logoCustomization = LogoCustomization(
Image.Drawable(R.drawable.ic_logo), // image
Size(176, 64), // size (dp)
100, // verticalPosition
50, // horizontalPosition
)
}OzConfig config = OzLivenessSDK.config();
// connecting to the API server
OzLivenessSDK.setApiConnection(OzConnection.fromServiceToken(HOST, TOKEN));
// settings for the number of attempts to detect an action
config.setAttemptSettings(attemptSettings);
// the possibility to display additional debug information (you can do it by clicking the SDK version number)
config.setAllowDebugVisualization(allowDebugVisualization);
// logging settings
config.setLogging(ozLogging); Proceed to your website origin and launch Liveness -> Simple selfie.
Once the license is added, the system will check its validity on launch.
OzLiveness.open({
license: {
'payload_b64': 'some_payload',
'signature': 'some_data',
'enc_public_key': 'some_key'
},
...,
})
{
"analyses": [
{
"type": "biometry",
"source_media": [
<original_name_with_extension>,
<UUID_of_reference_photo.jpeg>
]
}
]
}OZSDK(licenseSources: [.licenseFilePath(“path_to_file”)]) { licenseData, error in
if let error = error {
print(error)
}
}OZSDK(licenseSources: [.licenseData(license_data_byte_array)]) { licenseData, error in
if let error = error {
print(error)
}
}OzLivenessSDK.config.setCustomization(new UICustomization(
// customization parameters for the toolbar
new ToolbarCustomization(
R.drawable.ic_close, // closeButtonIcon
new Color.ColorRes(R.color.white), // closeButtonColor
"Liveness", // titleText
R.font.roboto, // titleFont
18, // titleSize (sp)
null, // titleFontStyle
new Color.ColorRes(R.color.white), // titleColor
100, // titleAlpha (%)
true, // isTitleCentered
null, // titleStyle
new Color.ColorRes(R.color.black), // backgroundColor
60 // backgroundAlpha (%)
),
// customization parameters for the center hint
new CenterHintCustomization(
R.font.roboto, // textFont
null, // textFontStyle
new Color.ColorRes(R.color.white), // textColor
20, // textSize (sp)
null, // verticalPosition
R.style.Sdk_Text_Primary, // textStyle
new Color.ColorRes(R.color.black), // backgroundColor
56, // backgroundOpacity (%)
14, // backgroundCornerRadius (dp)
100 // textAlpha (%)
),
// customization parameters for the hint animation
new HintAnimation(
new Color.ColorRes(R.color.error_red), // hintGradientColor
80, // hintGradientOpacity (%)
120, // animationIconSize
false // hideAnimation
),
// customization parameters for the frame around the user face
new FaceFrameCustomization(
new GeometryType.Rectangle(10), // geometryType, 10 = corner radius
5, // strokeWidth (dp)
new Color.ColorRes(R.color.error_red), // strokeFaceNotAlignedColor
new Color.ColorRes(R.color.success_green), // strokeFaceAlignedColor
100, // strokeAlpha (%)
50, // verticalPosition (%)
3 // strokePadding (dp)
),
// customization parameters for the SDK version label
new VersionLabelCustomization(
R.font.roboto, // textFont
12, // textSize (sp)
null, // textFontStyle
new Color.ColorRes(R.color.white), // textColor
100, // textAlpha (%)
R.style.Sdk_Text_Primary // textStyle
),
// customization parameters for the background outside the frame
new BackgroundCustomization(
new Color.ColorRes(R.color.black), // backgroundColor
60 // backgroundAlpha (%)
),
// hides the status bar and the navigation buttons
true, // hideStatusBar
null, // dialogStyle
// customization parameters for the antiscam protection text
new AntiScamCustomization(
"Recording...", // textMessage
R.font.roboto, // textFont
14, // textSize
new Color.ColorRes(R.color.white), // textColor
100, // textAlpha (%)
R.style.Sdk_Text_Primary, // textStyle
new Color.ColorRes(R.color.black), // backgroundColor
100, // backgroundOpacity (%)
20, // cornerRadius
new Color.ColorRes(R.color.success_green) // flashColor
),
// custom logo parameters (must be allowed by the license)
new LogoCustomization(
new Image.Drawable(R.drawable.ic_logo), // image
new Size(176, 64), // size (dp)
100, // verticalPosition
50 // horizontalPosition
)
));OzLivenessSDK.config.localizationCode = OzLocalizationCode.ENOzLivenessSDK.config.setLocalizationCode(OzLocalizationCode.EN)OzLiveness.open({
licenseUrl: 'https://some_url',
...,
}){
"media:tags": { // this section sets the tags for the media files that you upload
// media files are referenced by the keys in a multipart form
"video1": [ // your file key
// a typical set of tags for a passive Liveness video
"video_selfie", // video of a person
"video_selfie_blank", // no gesture used
"orientation_portrait" // video orientation
],
"photo1": [
// a typical set of tags for an ID front side
"photo_id",
"photo_id_front"
]
}
}Each step is marked:
[Oz SDK] – call our SDK API.
[Your code] – call your own backend or your own code.
{{host}} in the examples below is the base URL of your Oz API deployment, provided to you during deployment setup.
Oz API
6.6.1
Web SDK
1.9.10
You require a dedicated Web Adapter. Expand the section below if it has not yet been configured for your company.
These parameters are mandatory for OzCapsula to work. Define them in your API configuration file.
session_token from your backendOzCapsula uses a session token. The token is mandatory for OzCapsula.
Your backend requests a session token from Oz API. Request it before each capture session, as close to the moment the user starts capture as possible.
Endpoint:
GET {{host}}/api/authorize/session_tokenRequest:
curl --location -g '{{host}}/api/authorize/session_token' \
--header 'X-Forensic-Access-Token: {{access_token}}' ## optional, depends on installation settingsThe authorization mechanism for calls to Oz API (access_token) depends on your installation settings: when using Instant API, you can integrate it under your own authorization scheme. If access token is required in your case, please check . Never expose the access token in the browser. Also, please note that .
Response:
This token is short-lived (default lifetime: 900 seconds for API Full, 120 seconds for Instant API). Request one per capture session and pass it to the SDK immediately – do not cache or reuse tokens across sessions.
When capture completes, the SDK fires the on_capture_complete callback. The container is delivered as the second argument – a Blob with MIME type application/octet-stream.
The container is an opaque encrypted blob. You cannot decode it, inspect it, or extract individual images / frames / metadata from it on the device. It must be forwarded as-is to your backend. If you need access to captured images (e.g., ), retrieve them from the Oz API analysis response on the server side.
Upload it to your backend as application/octet-stream.
Your backend submits the container in a single synchronous POST request.
Endpoint (Instant API):
Endpoint (Full API):
Headers:
Content-Type: application/octet-stream (mandatory).
Your backend now has the response – a JSON folder object describing the result.
Make the accept/reject decision using only these two top-level fields:
Interpret system_resolution:
SUCCESS – all checks passed; accept the user.
With these steps, you are done with basic integration of Web SDK into your web application. You will be able to access recorded media and analysis results in Web Console via browser or programmatically via API (please find the instructions here: retrieving an MP4 video, getting analysis results).
In the Web Plugin Developer Guide, you can find instructions for common next steps:
Customizing plugin look-and-feel
Adding custom language pack
Tuning plugin behavior
Plugin parameters and callbacks
Security recommendations
Please find a sample for Oz Liveness Web SDK here. To make it work, replace <web-adapter-url> with the Web Adapter URL you've received from us.
For Angular and React, replace https://<link>.ozforensics.com in index.html.
OZ_SESSION_TOKEN_LIFETIME=<your_ttl_for_session_token>
OZ_JWT_PRIVATE_KEY_PATH=<jwt_private_key_path>
OZ_JWT_PUBLIC_KEY_PATH=<jwt_public_key_path>
OZ_MALEWICZ_ANALYSIS_ENABLED=trueIn this article, you’ll learn how to capture videos and send them through your backend to Oz API.
Here is the data flow for your scenario:
1. Oz Web SDK takes a video and makes it available for the host application as a frame sequence.
2. The host application calls your backend using an archive of these frames.
3. After the necessary preprocessing steps, your backend calls Oz API, which performs all necessary analyses and returns the analyses’ results.
4. Your backend responds back to the host application if needed.
On the server side, Web SDK must be configured to operate in the Capture mode:
The architecture parameter must be to capture in the app_config.json file.
In your Web app, add a callback to process captured media when opening the Web SDK :
The result object structure depends on whether any virtual camera is detected or not.
Here’s the list of variables with descriptions.
The video from Oz Web SDK is a frame sequence, so, to send it to Oz API, you’ll need to archive the frames and transmit them as a ZIP file via the POST /api/folders request (check our).
You can retrieve the MP4 video from a folder using the /api/folders/{{folder_id}} request with this folder's ID. In the JSON that you receive, look for the preview_url in source_media. The preview_url
Oz API accepts data without the base64 encoding.
To connect SDK to Oz API, specify the API URL, access token, and SSL pins as shown below.
OzLivenessSDK.setApiConnection(OzConnection.fromServiceToken(host, token, sslPins))OzLivenessSDK.INSTANCE.setApiConnection(
Alternatively, you can use the login and password provided by your Oz Forensics account manager:
OzLivenessSDK.setApiConnection(
OzConnection.fromCredentials(host, username, password, sslPins),
OzLivenessSDK.INSTANCE.setApiConnection(
Although, the preferred option is authentication via access token – for security reasons.
By default, logs are saved along with the analyses' data. If you need to keep the logs distinct from the analysis data, set up the separate connection for telemetry as shown below:
OzLivenessSDK.setEventsConnection(
OzConnection.fromCredentials(
Clearing authorization:
Check for the presence of the saved Oz API access token:
LogOut:
This article describes how to create a collection via API, how to add persons and photos to this collection and how to delete them and the collection itself if you no longer need it. You can do the same in Web console, but this article covers API methods only.
Collection in Oz API is a database of facial photos that are used to compare with the face from the captured photo or video via the Collection analysis
Person represents a human in the collection. You can upload several photos for a single person.
The collection should be created within a company, so you require your company's company_id as a prerequisite.
If you don't know your ID, call GET /api/companies/?search_text=test, replacing "test" with your company name or its part. Save the company_id you've received.
Now, create a collection via POST /api/collections/. In the request body, specify the alias for your collection and company_id of your company:
In a response, you'll get your new collection identifier: collection_id.
To add a new person to your collection, call POST /api/collections/{{collection_id}}/persons/, using collection_id of the collection needed. In the request body, add a photo or several photos. Mark them with appropriate in the payload:
The response will contain the person_id which stands for the person identifier within your collection.
If you want to add a name of the person, in the request payload, add it as metadata:
To add more photos of the same person, call POST {{host}}/api/collections/{{collection_id}}/persons/{{person_id}}/images/ using the appropriate person_id. The request body should be filled as you did it before with POST /api/collections/{{collection_id}}/persons/.
To obtain information on all the persons within the single collection, call GET /api/collections/{{collection_id}}/persons/.
To obtain a list of photos for a single person, call GET /api/collections/{{collection_id}}/persons/{{person_id}}/images/. For each photo, the response will containperson_image_id. You'll need this ID, for instance, if you want to delete the photo.
To delete a person with all their photos, call DELETE /api/collections/{{collection_id}}/persons/{{person_id}} with the appropriate collection and person identifiers. All the photos will be deleted automatically. However, you can't delete a person entity if it has any related analyses, which means the Collection analysis used this photo for comparison and found a match. To delete such a person, you'll need to delete these analyses using DELETE /api/analyses/{{analysis_id}} with analysis_id of the Collection (1:N) analysis.
To delete all the collection-related analyses, get a list of folders where the Collection analysis has been used: call GET /api/folders/?analyse.type=COLLECTION. For each folder from this list (GET /api/folders/{{folder_id}}/), find the analysis_id of the required analysis, and delete the analysis – DELETE /api/analyses/{{analysis_id}}.
To delete a single photo of a person, call DELETE collections/<collection_id>/persons/<person_id>/images/<media_id>/ with collection, person, and image identifiers specified.
Delete the information on all the persons from this collection as described above, then call DELETE /api/collections/{{collection_id}}/ to delete the remaining collection data.
A dedicated Web Adapter in our cloud or the adapter deployed on-premise. The adapter's URL is required for adding the plugin.
To embed the plugin in your page, add a reference to the primary script of the plugin (plugin_liveness.php) that you received from Oz Forensics to the HTML code of the page. web-sdk-root-url is the Web Adapter link you've received from us.
<script src="https://web-sdk-root-url/plugin_liveness.php"></script>The main change in interaction with API is that you require to send data with another content type, as data container is a binary file: Content-Type = application/octet-stream. We've added support for this content type along with container functionality.
Also, Instant API now requires client’s private and public keys to function. The paths to these keys should be specified in OZ_JWT_PRIVATE_KEY_PATH and OZ_JWT_PUBLIC_KEY_PATH in the configuration file.
To generate them, use commands as listed below.
These parameters are mandatory for OzCapsula to work. Add them to your configuration file.
POST api/folders:
Oz Liveness Web SDK is a module for processing data on clients' devices. With Oz Liveness Web SDK, you can take photos and videos of people via their web browsers and then analyze these media. Web SDK captures video at 720p HD (1280×720 px).
Most browsers and devices are supported. Available languages: EN, ES, PT-BR, KK.
Please find a sample for Oz Liveness Web SDK . To make it work, replace <web-adapter-url> with the Web Adapter URL you've received from us.
For Angular and React, replace https://<link>.ozforensics.com in index.html.
This article covers common cyberattacks and the steps you can take to stay safe.
The most common cyberattacks can be divided to three groups: injection, integration, and presentation attacks. Below, you’ll find some examples for mobile and web SDKs.
An injection attack on a liveness detection system is an attempt to bypass liveness verification mechanisms by injecting falsified data or modifying the execution logic of the frontend SDK. This type of attack is typically carried out by code injection, tampering with the runtime environment, or replacing camera input components (e.g., intercepting and substituting the video stream in real time, using virtual cameras, or manipulating JavaScript logic in the Web SDK). The goal of such attacks is to trick the liveness system into accepting fake or pre-recorded content as a genuine live interaction with the user.
Examples for mobile SDKs:
Virtual cameras.
<link rel="stylesheet" href="https://web-sdk-root-url/plugin/ozliveness.css" />
<script src="https://web-sdk-root-url/plugin_liveness.php"></script>best_frame_png
String
The best frame, PNG in the data URL format
best_frame_bounding_box
Array[Named_parameter: Int]
The coordinates of the bounding box where the face is located in the best frame
best_frame_landmarks
Array[Named_parameter: Array[Int, Int]]
The coordinates of the face landmarks (left eye, right eye, nose, mouth, left ear, right ear) in the best frame
frame_list
Array[String]
All frames in the data URL format
frame_bounding_box_list
Array[Array[Named_parameter: Int]]
The coordinates of the bounding boxes where the face is located in the corresponding frames
frame_landmarks
Array[Named_parameter: Array[Int, Int]]
The coordinates of the face landmarks (left eye, right eye, nose, mouth, left ear, right ear) in the corresponding frames
action
String
An action code
additional_info
String
Information about client environment
Also, in the POST {{host}}/api/folders request, you need to add the additional_info field. It is required for the capture architecture mode to gather the necessary information about client environment. Here’s the example of filling in the request’s body:
Variable
Type
Description
best_frame
String
The best frame, JPEG in the data URL format
The order of SDK initialization and API connection does not matter, but both methods must be finished successfully before invoking the createStartIntent method.
OzLivenessSDK.setEventsConnection(
OzConnection.fromCredentials(
"https://tm.ozforensics.com/",
"<your_telemetry_user_eg_tm@company.com>",
"your_telemetry_password"
)
);X-Forensic-Access-Token: {{access_token}}. (optional, depends on installation settings).
Request body: the raw container bytes – no JSON envelope, no multipart, no base64 wrapping.
Request (Instant API):
Request (Full API):
On success: HTTP 201 with a JSON folder object describing the result. Check Step 6.
On container-level error: HTTP 400 – see Exceptions.
This guide covers the Liveness analysis. To perform a Face Matching analysis within the OzCapsula flow, see How to Perform a Face Matching Analysis within OzCapsula Flow.
DECLINED – one or more checks failed; reject the user.FAILED – a system error prevented at least one analysis from completing; do not treat as accept or reject.
For per-analysis verdicts (for example, to know whether liveness passed but biometry failed), read $.analyses[*].resolution_status with the values described above.
Login: j.doe@yourcompany.com
Password: …
API: https://<link>.ozforensics.com/
Web Console: https://<link>.ozforensics.com
Web Adapter: https://<link>.ozforensics.com/your_company_name/
Domain names from which Web SDK will be called:
www.yourbrand.com
www.yourbrand2.com
Email for admin access:
j.doe@yourcompany.com
OzLiveness.open({
... // other parameters
on_capture_complete: function(result) {
// Your code to process media/send it to your API, this is STEP #2
}
}){
"action": <action>,
"best_frame": <bestframe>,
"best_frame_png": <bestframe_png>,
"best_frame_bounding_box": {
"left": <bestframe_bb_left>,
"top": <bestframe_bb_top>,
"right": <bestframe_bb_right>,
"bottom": <bestframe_bb_bottom>
},
"best_frame_landmarks": {
"left_eye": [bestframe_x_left_eye, bestframe_y_left_eye],
"right_eye": [bestframe_x_right_eye, bestframe_y_right_eye],
"nose_base": [bestframe_x_nose_base, bestframe_y_nose_base],
"mouth_bottom": [bestframe_x_mouth_bottom, bestframe_y_mouth_bottom],
"left_ear": [bestframe_x_left_ear, bestframe_y_left_ear],
"right_ear": [bestframe_x_right_ear, bestframe_y_right_ear]
},
"frame_list": [<frame1>, <frame2>],
"frame_bounding_box_list": [
{
"left": <frame1_bb_left>,
"top": <frame1_bb_top>,
"right": <frame1_bb_right>,
"bottom": <frame1_bb_bottom>
},
{
"left": <frame2_bb_left>,
"top": <frame2_bb_top>,
"right": <frame2_bb_right>,
"bottom": <frame2_bb_bottom>
},
],
"frame_landmarks": [
{
"left_eye": [frame1_x_left_eye, frame1_y_left_eye],
"right_eye": [frame1_x_right_eye, frame1_y_right_eye],
"nose_base": [frame1_x_nose_base, frame1_y_nose_base],
"mouth_bottom": [frame1_x_mouth_bottom, frame1_y_mouth_bottom],
"left_ear": [frame1_x_left_ear, frame1_y_left_ear],
"right_ear": [frame1_x_right_ear, frame1_y_right_ear]
},
{
"left_eye": [frame2_x_left_eye, frame2_y_left_eye],
"right_eye": [frame2_x_right_eye, frame2_y_right_eye],
"nose_base": [frame2_x_nose_base, frame2_y_nose_base],
"mouth_bottom": [frame2_x_mouth_bottom, frame2_y_mouth_bottom],
"left_ear": [frame2_x_left_ear, frame2_y_left_ear],
"right_ear": [frame2_x_right_ear, frame2_y_right_ear]
}
],
"from_virtual_camera": null,
"additional_info": <additional_info>
}{
"action": <action>,
"best_frame": null,
"best_frame_png": null,
"best_frame_bounding_box": null,
"best_frame_landmarks": null
"frame_list": null,
"frame_bounding_box_list": null,
"frame_landmarks": null,
"from_virtual_camera": {
"additional_info": <additional_info>,
"best_frame": <bestframe>,
"best_frame_png": <bestframe_png>,
"best_frame_bounding_box": {
"left": <bestframe_bb_left>,
"top": <bestframe_bb_top>,
"right": <bestframe_bb_right>,
"bottom": <bestframe_bb_bottom>
},
"best_frame_landmarks": {
"left_eye": [bestframe_x_left_eye, bestframe_y_left_eye],
"right_eye": [bestframe_x_right_eye, bestframe_y_right_eye],
"nose_base": [bestframe_x_nose_base, bestframe_y_nose_base],
"mouth_bottom": [bestframe_x_mouth_bottom, bestframe_y_mouth_bottom],
"left_ear": [bestframe_x_left_ear, bestframe_y_left_ear],
"right_ear": [bestframe_x_right_ear, bestframe_y_right_ear]
},
"frame_list": [<frame1>, <frame2>],
"frame_bounding_box_list": [
{
"left": <frame1_bb_left>,
"top": <frame1_bb_top>,
"right": <frame1_bb_right>,
"bottom": <frame1_bb_bottom>
},
{
"left": <frame2_bb_left>,
"top": <frame2_bb_top>,
"right": <frame2_bb_right>,
"bottom": <frame2_bb_bottom>
},
],
"frame_landmarks": [
{
"left_eye": [frame1_x_left_eye, frame1_y_left_eye],
"right_eye": [frame1_x_right_eye, frame1_y_right_eye],
"nose_base": [frame1_x_nose_base, frame1_y_nose_base],
"mouth_bottom": [frame1_x_mouth_bottom, frame1_y_mouth_bottom],
"left_ear": [frame1_x_left_ear, frame1_y_left_ear],
"right_ear": [frame1_x_right_ear, frame1_y_right_ear]
},
{
"left_eye": [frame2_x_left_eye, frame2_y_left_eye],
"right_eye": [frame2_x_right_eye, frame2_y_right_eye],
"nose_base": [frame2_x_nose_base, frame2_y_nose_base],
"mouth_bottom": [frame2_x_mouth_bottom, frame2_y_mouth_bottom],
"left_ear": [frame2_x_left_ear, frame2_y_left_ear],
"right_ear": [frame2_x_right_ear, frame2_y_right_ear]
}
]
}
}"VIDEO_FILE_KEY": VIDEO_FILE_ZIP_BINARY
"payload": "{
"media:meta_data": {
"VIDEO_FILE_KEY": {
"additional_info": <additional_info>
}
}
}"OzLivenessSDK.setApiConnection(null)OzLivenessSDK.INSTANCE.setApiConnection(null, null);val isLoggedIn = OzLivenessSDK.isLoggedInboolean isLoggedIn = OzLivenessSDK.INSTANCE.isLoggedIn();OzLivenessSDK.logout()OzLivenessSDK.INSTANCE.logout();{
"alias": "your_collection",
"company_id": "your_company_id"
}{
"media:tags": {
"image1": [
"photo_selfie",
"orientation_portrait"
]
}
} "person:meta_data": {
"person_info": {
"first_name": "John",
"middle_name": "Jameson",
"last_name": "Doe"
}
},{
"session_token": "<session_token>"
}OzLiveness.open({
lang: 'en',
action: ['video_selfie_blank'], // passive liveness
session_token: session_token, // session_token from Step 2
on_capture_complete: function (action, ozCapsula) {
// ozCapsula = the OzCapsula container (Blob) — Step 4
sendToYourBackend(ozCapsula);
},
on_error: function (err) { /* handle */ }
});POST {{host}}/api/instant/folders/POST {{host}}/api/folders/$.resolution_status // "FINISHED" – analyses completed; "FAILED" – error during analysis processing
$.system_resolution // "SUCCESS", "DECLINED", or "FAILED"curl -X POST '{{host}}/api/instant/folders/' \
--header 'X-Forensic-Access-Token: {{access_token}}' ## optional, depends on installation settings
-H 'Content-Type: application/octet-stream' \
--data-binary '@/path/to/container.dat'curl -X POST '{{host}}/api/folders/' \
--header 'X-Forensic-Access-Token: {{access_token}}' ## optional, depends on installation settings
-H 'Content-Type: application/octet-stream' \
--data-binary '@/path/to/container.dat'POST api/instant/folders:Error code
Error message
Description
3
Invalid request data
Missing payload.json
4
Before you start with SDK, obtain a session token:
(Optional, only if you use stateful API) Authorize as any non-OPERATOR role.
Call GET {{host}}/api/authorize/session_token.
Example request
Example response
# Generate private key:
openssl ecparam -name secp384r1 -genkey -noout | openssl pkcs8 -topk8 -nocrypt -out ./jwt.key
# Generate public key:
openssl ec -in ./jwt.key -pubout -out ./jwt.pubOZ_SESSION_TOKEN_LIFETIME=<your_ttl_for_session_token>
OZ_JWT_PRIVATE_KEY_PATH=<jwt_private_key_path>
OZ_JWT_PUBLIC_KEY_PATH=<jwt_public_key_path>
OZ_MALEWICZ_ANALYSIS_ENABLED=truecurl -X POST \
'{{host}}/api/folders' \
-H 'Content-Type: application/octet-stream' \
-H 'X-Forensic-Access-Token: <YOUR_TOKEN>' \
--data-binary '@/path/to/container.dat'curl -X POST \
'{{host}}api/instant/folders' \
-H 'Content-Type: application/octet-stream' \
-H 'X-Forensic-Access-Token: <YOUR_TOKEN>' \
--data-binary '@/path/to/container.dat'curl -L 'https://{{host}}/api/authorize/session_token' \
-H 'X-Forensic-Access-Token: <token>' \
-H 'Content-Type: application/json'{
"session_token": "<session_token>"
}Vue sample
Svelte sample
Web SDK requires HTTPS (with SSL encryption) to work; however, at localhost and 127.0.01, you can check the resources' availability via HTTP.
Oz Liveness Web SDK consists of two components:
Client side – a JavaScript file that is being loaded within the frontend part of your application. It is called Oz Liveness Web Plugin.
Server side – a separate server module with OZ API, the backend part. The module is called Oz Liveness Web Adapter.
The integration guides can be found here:
Oz Web SDK can be provided via SaaS, when the server part works on our servers and is maintained by our engineers, and you just use it, or on-premise, when Oz Web Adapter is installed on your servers. Contact us for more details and choose the model that is convenient for you.
Oz Web SDK requires a license to work. To issue a license, we need the domain name of the website where you are going to use our SDK.
This is a guide on how to start with Oz Web SDK:
Integrate the plugin into your page.
If you want to customize the look-and-feel of Oz Web SDK, please refer to this section.
Web SDK can be integrated into mobile applications using a WebView. However, for security-sensitive scenarios, we recommend using Mobile SDKs.
Function hooking & application modification.
Emulators and cloud devices.
For web:
Virtual cameras.
Code injection attacks.
A presentation attack is an attempt to deceive the system by presenting pre-recorded or artificial content that mimics a real user. The goal of such attacks is to pass the liveness check without involving a real, live person. These attacks do not target the SDK directly but rather the biometric models on the backend. They may include:
Photos,
Videos,
3D masks,
Screens of other devices, or
Other media used to create the illusion of live presence.
These attacks include cyber fraudsters manipulating how the liveness detection module is integrated into the application or backend, bypassing or faking the check. Typically, these attacks involve patching the app, injecting hooks, or exploiting weak verification of liveness results. For instance, Man-in-the-Middle (MitM) / SSL Interception attack that is based on substitution or manipulation of captured data during network transmission, typically involving SSL/TLS violations or certificate pinning bypass.
With cyberattacks on the rise, cybersecurity has become crucial and is now our highest priority. We provide protection even from multi-vector complex attacks, ensuring your data is safe at all stages of processing, including media capture, data transmission, and analysis. This protection involves many mechanisms on multiple layers that work together, supporting and reinforcing each other. To name a few:
We do not accept virtual cameras and emulators.
In native SDKs, you can configure SSL pinning and add protection for media files using request payload.
For Web SDK, you can move the decision logic to backend to avoid manipulating data within the browser context.
As our software aims to be embedded, it includes mechanisms to verify its runtime integrity, but it does not validate the integrity of the host application itself. Ensuring protection of the host application through anti-tampering techniques, code obfuscation, and runtime integrity verification is the responsibility of the host application owner. Without such safeguards, even a secure SDK may become susceptible to manipulation at the application or platform level.
Here are some measures we recommend to protect your application.
Consider revising your policies. This might involve:
Creating and using corporate SSL certificates,
Limiting access to unverified sources,
Using SSL proxy,
Controlling connections via SNI / TLS Handshake,
Creating a security policy and adhere to it,
etc.
For mobile applications, use Play Integrity (Android) and App Attest (iOS).
As for our SDKs, we recommend:
Ensuring you always have the latest version of Oz software installed, as almost each of our releases includes security enhancements.
Setting up for Native SDKs.
For Web SDK, to avoid possible manipulations within the browser context, and using the mode when setting up responses.
For more detailed recommendations, please contact us. For us, clients' safety comes first, and we’ll be happy to help.
Web SDK can be integrated into mobile applications using a WebView. However, for security-sensitive scenarios, we recommend using Mobile SDKs.
Invalid request data
No media have been added into container
5
Invalid request data
Container is damaged
13
Invalid request data
API didn’t receive the container
14
Invalid request data
The container appears to be affected by errors and can’t be unpackaged,
or Oz API (Full) detected a repeat analysis on OzCapsula media after a failed analysis

On-Premise
Install our Web SDK. Our engineers will help you to install the components needed using the or manually. The license will be installed as well; to update it, please refer to .
Configure the .
SaaS
This part is fully covered by the Oz Forensics engineers. You get a link for Oz Web Plugin (see step 2).
To start recording, use startActivityForResult:
val sessionToken: String = getSessionToken()
val captureRequest = CaptureRequest(
listOf(
AnalysisProfile(
Analysis.Type.QUALITY,
listOf(MediaRequest.ActionMedia(OzAction.Blank)),
)
)
)
val intent = OzLivenessSDK.createMediaCaptureScreen(captureRequest, sessionToken)
startActivityForResult(intent, REQUEST_LIVENESS_CONTAINER)To obtain the container, use onActivityResult:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_LIVENESS_CONTAINER) {
when (resultCode) {
OzLivenessResultCode.SUCCESS -> runAnalysis(OzLivenessSDK.getContainerFromIntent(data))
OzLivenessResultCode.USER_CLOSED_LIVENESS -> { /* user closed the screen */ }
else -> {
val errorMessage = OzLivenessSDK.getErrorFromIntent(data)
/* show error */
}
}
}
}If you use fragment, please refer to the example below. LivenessFragment is the Fragment representation of the Liveness screen UI.
childFragmentManager.beginTransaction()
.replace(android.R.id.content, LivenessFragment.create(createCaptureRequest(), sessionToken))
.commit()
childFragmentManager.setFragmentResultListener(OzLivenessSDK.Extra.REQUEST_CODE, this) { _, result ->
when (val resultCode = result.getInt(OzLivenessSDK.Extra.EXTRA_RESULT_CODE)) {
OzLivenessResultCode.SUCCESS -> {
val container = result.getParcelable(OzLivenessSDK.Extra.EXTRA_DATA_CONTAINER) as? DataContainer
/* Run analysis */
}
OzLivenessResultCode.USER_CLOSED_LIVENESS -> { /* User closed the screen */ }
else -> { /* Show error */ }
}
}To start recording, use thestartActivityForResult method:
val intent = OzLivenessSDK.createStartIntent(listOf(OzAction.Smile, OzAction.Blank))
startActivityForResult(intent, REQUEST_CODE)List<OzAction> actions = Arrays.asList(OzAction.Smile, OzAction.Scan);
Intent intent = OzLivenessSDK.createStartIntent(actions);
startActivityForResult(intent, REQUEST_CODE);actions – a list of while recording video.
For Fragment, use the code below. LivenessFragment is the representation of the Liveness screen UI.
To obtain the captured video, use theonActivityResult method:
sdkMediaResult – an object with video capturing results for interactions with Oz API (a list of the objects),
sdkErrorString – description of , if any.
If a user closes the capturing screen manually, resultCode receives the Activity.RESULT_CANCELED value.
Code example:
This guide walks you through the full integration: getting a session token, capturing media with the SDK, sending the resulting OzCapsula container to Oz Instant API, reading the response, making the accept/reject decision, reducing the response size, and running minimal diagnostics.
This flow combines three things:
Capture mode – the Web SDK (or Mobile SDK) captures the Liveness video in the browser/app and your backend forwards it to Oz API. Capture results are not sent from the SDK straight to Oz API; your backend acts as an intermediary.
OzCapsula – a . The SDK packages captured media and metadata into it; Oz API decrypts and processes it. It protects the captured data from tampering between the user's device and Oz API. The container is an
childFragmentManager.beginTransaction()
.replace(R.id.content, LivenessFragment.create(actions))
.commit()
// subscribing to the Fragment result
childFragmentManager.setFragmentResultListener(OzLivenessSDK.Extra.REQUEST_CODE, this) { _, result ->
when (result.getInt(OzLivenessSDK.Extra.EXTRA_RESULT_CODE)) {
OzLivenessResultCode.SUCCESS -> { /* start analysis */ }
else -> { /* show error */ }
}
}getSupportFragmentManager().beginTransaction()
.replace(R.id.content, LivenessFragment.Companion.create(actions, null, null, false))
.addToBackStack(null)
.commit();
// subscribing to the Fragment result
getSupportFragmentManager().setFragmentResultListener(OzLivenessSDK.Extra.REQUEST_CODE, this, (requestKey, result) -> {
switch (result.getInt(OzLivenessSDK.Extra.EXTRA_RESULT_CODE)) {
case OzLivenessResultCode.SUCCESS: {/* start analysis */}
default: {/* show error */}
}
});override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE) {
sdkMediaResult = OzLivenessSDK.getResultFromIntent(data)
sdkErrorString = OzLivenessSDK.getErrorFromIntent(data)
}
}@Override
protected void onActivityResult(int requestCode, int resultCode, @androidx.annotation.Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
List<OzAbstractMedia> sdkMediaResult = OzLivenessSDK.INSTANCE.getResultFromIntent(data);
String sdkErrorString = OzLivenessSDK.INSTANCE.getErrorFromIntent(data);
}when (resultCode) {
Activity.RESULT_CANCELED -> *USER CLOSED THE SCREEN*
OzLivenessResultCode.SUCCESS -> {
val sdkMediaResult = OzLivenessSDK.getResultFromIntent(data)
*SUCCESS*
}
else -> {
val errorMessage = OzLivenessSDK.getErrorFromIntent(data)
*FAILURE*
}
}val sessionToken: String = getSessionToken()
val captureRequest = CaptureRequest(
listOf(
AnalysisProfile(
Analysis.Type.QUALITY,
listOf(
MediaRequest.ActionMedia(OzAction.Blank),
MediaRequest.ActionMedia(OzAction.Smile)
),
)
)
)
val intent = OzLivenessSDK.createMediaCaptureScreen(captureRequest, sessionToken)
startActivityForResult(intent, REQUEST_LIVENESS_CONTAINER)Instant API – the non-persistent mode of Oz API. Results are returned immediately in the response and nothing is stored, unless you want to save data for audit in S3.
Together: the SDK captures and packages media into OzCapsula → your backend forwards the container to Oz Instant API → Oz API returns the result synchronously, storing nothing.
Not covered: the Full API, non-OzCapsula, Collection, direct Web SDK ↔ Oz API workflows.
A few terms used throughout this guide:
{{host}} – the base URL of your Oz API deployment. Provided to you during deployment setup.
Session token – a short-lived token that ties an OzCapsula to a specific capture session, preventing replay of the same container later. Mandatory for OzCapsula.
Folder – the response object Oz API creates for a single submission. It groups the submitted media and the analyses that were applied to them.
Analysis type – what Oz API runs on the media. The API returns QUALITY for Liveness analyses and BIOMETRY for Face Matching analyses.
Oz API
6.6.1
Mobile SDKs (iOS, Android)
10.0.0
Web SDK
These parameters are mandatory for OzCapsula to work. Define them in your API configuration file.
OzCapsula requires a session token for each capture session.
To enable the session token functionality, generate a pair of JWT keys. Please find the instructions on how to create them in the Instant API helm chart: proceed to readme.md and, in the Preparation section, locate sub-section Create a JWT secret. Once you have keys, create a folder within your installation, place keys there, and put this path into API_KEYS_DIR (e.g., API_KEYS_DIR=/opt/oz/api/keys). This should be done once for the installation.
Obtain a session token from Oz Instant API. Request one before each capture session, as close to the moment the user starts capture as possible, and pass it to the SDK immediately – do not cache or reuse tokens across sessions.
Endpoint:
GET {{host}}/api/authorize/session_tokenHeaders:
Content-Type: application/json
Request:
curl -L 'https://{{host}}/api/authorize/session_token' \
-H 'Content-Type: application/json'Response:
{
"session_token": "<session_token>"
}The token is short-lived (default lifetime: 120 seconds for Instant API).
Authorization mechanism for the call to Oz API depends on installation, by default, no access token is required in the headers. If it is required in your case, please check .
The SDK captures media from the user and packages it into an OzCapsula container.
Launch analysis with the session token. The container is returned through the result callback.
The container is returned as a bytearray (Android) or Data (iOS). Forward it to your backend without any transformation.
Call OzLiveness.open() with the session token. When capture completes, the SDK fires the on_capture_complete callback. The container is delivered as the second argument.
Your backend submits the container in a single synchronous POST request.
Endpoint:
Headers:
Content-Type: application/octet-stream (mandatory)
Request body: the raw container bytes – no JSON envelope, no multipart, no base64 wrapping.
If you don't need face matching, skip this step and go straight to .
Call POST /api/instant/folders/ with your reference photo and the best shot you've obtained from the Liveness analysis at .
Request body:
The response will contain the result of the biometry analysis.
When the container fails validation, Oz API responds with HTTP 400 and error_message: "Invalid request data". The specific error_code indicates the cause:
For more details, please refer to:
OZ_SESSION_TOKEN_LIFETIME=<your_ttl_for_session_token>
OZ_JWT_PRIVATE_KEY_PATH=<jwt_private_key_path>
OZ_JWT_PUBLIC_KEY_PATH=<jwt_public_key_path>
OZ_MALEWICZ_ANALYSIS_ENABLED=trueBlob with MIME type application/octet-stream. Forward it to your backend without any transformation.201On container-level error: HTTP 400 (see Non-success outcomes).
The QUALITY (Liveness) analysis provides the best shot. Locate the QUALITY entry in the analyses[] array and read:
The value is a base64-encoded JPEG. Decode it to JPEG.
system_resolution
Overall result: SUCCESS, DECLINED, or FAILED
resolution_comment
Note about the analysis resolution. Useful on FAILED (lists which analyses failed)
meta_data
Metadata block. The block contains event_session_id, the session identifier which is required for tracing the request back to the user session in your frontend
media
Media files submitted in the container
analyses
Array of per-analysis results
type
QUALITY for liveness, BIOMETRY for face matching
state
Processing state of this analysis: FINISHED or FAILED
resolution_status
Use only these two top-level fields:
Interpret system_resolution:
SUCCESS – all checks passed; accept the user.
DECLINED – one or more checks failed; reject the user.
FAILED – a system error prevented at least one analysis from completing; do not treat as accept or reject (see Non-success outcomes).
For per-analysis verdicts (for example, to know whether liveness passed but biometry failed), read $.analyses[*].resolution_status with the same three values.
The response also contains internal identifiers (group_id, media_association_id), file hashes, operator-related fields (operator_comment, operator_status, is_cleared), and other system fields. They are not needed for the integration flow described in this guide.
3
Missing payload
4
No media in the container
5
Container is damaged
13
No container in the request
14
Invalid container – any reason (decryption, signature, hash, or session_token validation failure)
Codes 13 and 14 fire before the container is unpackaged; codes 3, 4, 5 fire after unpackaging when the payload itself fails business-level validation.
For code 14, send the container instance and the error_code to Oz Forensics support – the specific cause is only available in server-side logs.
The container was valid and the analyses ran, but at least one check did not pass.
resolution_status: FINISHED.
system_resolution: DECLINED.
resolution_comment: "[]" (not informative – the decline reason is implicit in the per-analysis result).
Per-analysis resolution_status: DECLINED.
A system error prevented at least one analysis from completing.
resolution_status: FAILED.
system_resolution: FAILED.
resolution_comment – string listing which analyses failed and with what code.
Per-analysis state: FAILED, resolution_status: FAILED, error_code and error_message populated.
1.9.10
// Launch the capture screen
val captureRequest = CaptureRequest(
listOf(
AnalysisProfile(
Analysis.Type.QUALITY,
listOf(MediaRequest.ActionMedia(OzAction.Blank))
)
)
)
val intent = OzLivenessSDK.createMediaCaptureScreen(captureRequest, sessionToken)
startActivityForResult(intent, REQUEST_LIVENESS_CONTAINER)
// Obtain the result
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_LIVENESS_CONTAINER) {
when (resultCode) {
OzLivenessResultCode.SUCCESS -> {
val container = OzLivenessSDK.getContainerFromIntent(data)
handleContainer(container)
}
OzLivenessResultCode.USER_CLOSED_LIVENESS -> { /* user closed the screen */ }
else -> {
val errorMessage = OzLivenessSDK.getErrorFromIntent(data)
/* show error */
}
}
}
}// Launch the capture screen
let mediaRequest = MediaRequest.action(.selfie)
let profile = AnalysisProfile(
mediaList: [mediaRequest],
type: .quality,
params: [:]
)
let request = CaptureRequest(
analysisProfileList: [profile],
cameraPosition: .front
)
let livenessVC = try OZSDK.createMediaCaptureScreen(
delegate,
request,
sessionToken: sessionToken
)
livenessVC.modalPresentationStyle = .fullScreen
parent.present(livenessVC, animated: true)
// Obtain the result
extension YourViewController: LivenessDelegate {
func onResult(container: DataContainer) {
// Pass container to Step 3
handleContainer(container)
}
func onError(status: OZVerificationStatus?) {
// user cancelled, capture failed, etc.
}
}OzLiveness.open({
lang: 'en',
session_token: session_token,
action: ['video_selfie_blank'], // request passive liveness video
on_capture_complete: function(action, ozCapsula) {
// ozCapsula is a Blob (application/octet-stream)
// forward it to your backend
},
on_error: function (err) { /* handle error */ }
});POST {{host}}/api/instant/folders/curl -X POST '{{host}}/api/instant/folders/' \
-H 'Content-Type: application/octet-stream' \
--data-binary '@/path/to/container.dat'{
"media:tags": {
"UUID_of_reference_photo.jpeg": ["photo_selfie"],
"best_shot.jpeg": ["photo_selfie"]
},
"analyses": [
{ "type": "biometry" }
]
}folder_id
Unique identifier of the request
resolution_status
error_code
Condition
$.analyses[*].results_media[*].output_images[*].image_b64Whether processing completed: FINISHED or FAILED
$.resolution_status // "FINISHED" – analyses completed; "FAILED" – error during analysis processing
$.system_resolution // "SUCCESS", "DECLINED", or "FAILED"Outcome of this analysis: SUCCESS, DECLINED, or FAILED
error_code, error_message
Shown only when the analysis failed technically
results_data
Aggregated result values
results_media
Generated media items. For the QUALITY analysis, contains the best shot in output_images[] – see Step 3
source_media
Input media
OzCapsula is our proprietary data format, designed to provide end-to-end protection and maintain data integrity during transmission. We've introduced this format in 8.22 and implemented new methods to use it:
createMediaCaptureScreen(request) for video capture: this method takes a video and packages it into a data container.
AnalysisRequest.addContainer for processing data: this method adds container to the analysis request.
Please follow the links below to access the examples. You can also refer to the illustrative examples shown below the links.
Please check the methods and properties below. You can also find them in the corresponding sections of , , Flutter documentation sections.
This method replaces addAnalysis in the AnalysisRequest structure when you use the data container flow.
Input
Captures media file with all information you need and packages it into a data container.
Input
Output
Detects a request for video capture.
Contains information on media files and analyses that should be applied to them.
Stores information about a media file.
If, during the video capture, SDK encounters an error that prevents user scenario from completion, the data container is deleted.
Should you have any questions, please contact us.
What is Oz API Lite, when and how to use it.
Oz API Lite is the lightweight yet powerful version of Oz API. The Lite version is less resource-demanding, more productive, and easier to work with. The analyses are made within the API Lite image. As Oz API Lite doesn't include any additional services like statistics or data storage, this version is the one to use when you need a high performance.
To check the Liveness processor, GET /v1/face/liveness/health.
To check the Biometry processor, GET /v1/face/pattern/health.
To perform the liveness check for an image, POST /v1/face/liveness/detect (it takes an image as an input and displays the evaluation of spoofing attack chance in this image)
To compare two faces in two images,
POST /v1/face/pattern/extract_and_compareTo compare an image with a bunch of images, call POST /v1/face/pattern/extract_and_compare_n.
For the full list of Oz API Lite methods, please refer to API Methods.
Additional folder metadata
additionalMediaList (optional)
List<>
Media files that you need to upload to server, but it’s not necessary for analyses
cameraPosition (optional)
String
front (default) – front camera
back – rear camera
params (optional)
Map<String, Any>
Additional analysis parameters
userMedia
OzAbstractMedia (Android) or OZMedia (iOS)
An external media file, e.g., a reference or a document photo
The device doesn’t have enough memory to proceed
data_container_internal_failure_2
data_container_internal_failure_3
data_container_internal_failure_4
Internal failure occurred while processing the data container
SDK couldn’t generate the container. Try again
data_container_internal_failure_1000
Internal failure occurred while processing the data container
Any other error not from the list above
// capture and pack media
val referentPhoto = MediaRequest.UserMedia(OzAbstractMedia.OzDocumentPhoto(OzMediaTag.Blank, referentPhotoPath))
val blinkVideo = MediaRequest.ActionMedia(OzAction.EyeBlink)
val scanVideo = MediaRequest.ActionMedia(OzAction.Scan)
val intent = OzLivenessSDK.createMediaCaptureScreen(
CaptureRequest(
listOf(
AnalysisProfile(
Analysis.Type.BIOMETRY,
listOf(referentPhoto, scanVideo)
),
AnalysisProfile(
Analysis.Type.QUALITY,
listOf(referentPhoto, scanVideo, blinkVideo)
),
),
),
sessionToken
)
startActivityForResult(intent, REQUEST_CODE_SDK)
// subscription to result
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_SDK) {
when (resultCode) {
OzLivenessResultCode.USER_CLOSED_LIVENESS -> { /* user closed the screen */ }
OzLivenessResultCode.SUCCESS -> {
// result
val container = OzLivenessSDK.getContainerFromIntent(data)
...
}
else -> {
// error
val errorMessage = OzLivenessSDK.getErrorFromIntent(data)
...
}
}
}
}
// launching analyses
AnalysisRequest.Builder()
.addContainer(container)
.build()
.run(
object: AnalysisRequest.AnalysisListener {
override fun onSuccess(result: RequestResult) {
...
}
override fun onError(exception: OzException) {
...
}
}
)// capture and pack media
let mediaRequest = MediaRequest.actionMedia(.selfie)
let profile = AnalysisProfile(mediaList: [mediaRequest],
type: .quality,
params: ["extract_best_shot" : true])
let request = CaptureRequest(analysisProfileList: [profile], cameraPosition: cameraPosition)
self.ozLivenessVC = try OZSDK.createMediaCaptureScreen(self, request, sessionToken: sessionToken)
self.present(ozLivenessVC, animated: true)
// subscription to result
extension ViewController: LivenessDelegate {
func onError(status: OZVerificationStatus?) {
// error handling
}
func onResult(container: DataContainer) {
let analysisRequest = AnalysisRequestBuilder()
analysisRequest.addContainer(container)
analysisRequest.run(statusHandler: { [weak self] state in
},
errorHandler: { [weak self] error in
// error
}) { result in
// result
}
}
// capture and pack media
final sessionToken = await _getSessionToken();
OZSDK.createMediaCaptureScreen(
CaptureRequest(
analysisProfileList: [
AnalysisProfile(
Type.quality,
mediaList: [ActionMedia(VerificationAction.blank)]
),
],
),
sessionToken,
);
// subscription to result
@override
void initState() {
super.initState();
_subscription = OZSDK.livenessResult.listen((result) {
if (result is DataContainer) {
// OzCapsula media
}
}, onError: (Object error) {
// handle error, in most cases PlatformException
});
}
// launching Liveness
final sessionToken = await _getSessionToken();
OZSDK.createMediaCaptureScreen(
CaptureRequest(
analysisProfileList: [
AnalysisProfile(
Type.quality,
mediaList: [ActionMedia(VerificationAction.blank)]
),
],
),
sessionToken,
);
Parameter
Type
Description
OzDataContainer
bytearray[]
An encrypted file containing media and collateral info, the output of the createMediaCaptureScreen method
Parameter
Type
Description
request
Detects a request for video capture
session_token
String
Parameter
Type
Description
OzDataContainer
bytearray[]
An encrypted file containing media and collateral info
Parameter
Type
Description
analysisProfileList
List<AnalysisProfile>
A list of objects that contain information on media and analyses that should be applied to them
folderMeta (optional)
Parameter
Type
Description
mediaList
List<MediaRequest>
A list of media to be analyzed
type
String (Type (Android) or AnalysisType (iOS))
id
String (UUID v4)
Media ID
actionMedia
OzAction (Android) or OzVerificationMovement (iOS)
Error
Text
Description
session_token_is_empty
Session token must not be empty
Session token is mandatory but hasn’t been provided
data_container_internal_failure_1
Token for current session
Map<String, Any>
Analysis type
An action that user should perform in a video
Internal failure occurred while processing the data container
iOS SDK changes
The on-device and hybrid analysis modes are now deprecated and will be removed on January 1, 2027; please plan your migration to the server-based analysis.
The capture screen now stays open until the result is ready, so onResult or onError arrives right after it closes. If the app’s background time runs out before the result is ready, onError gets .failedBecauseOfBackgroundMode.
Recording now continues for 0.5 seconds after a successful gesture (except selfie and one-shot), so the video includes the face returning to a neutral position.
Fixed a bug where, if the user’s face left the frame before the post-gesture recording finished, the SDK saved the incomplete recording as successful, and the server could reject the video as too short. The SDK now discards such a recording and restarts the gesture.
OzCapsula capture no longer returns an empty container via onResult(container:) when the user has not completed the capture. Related changes:
Creating a second capture screen during a capture throws an error.
An empty media list throws an error instead of opening a screen that hangs.
Resolved an issue where apps using OzCapsula capture could fail to build for the iOS Simulator.
Liveness no longer crashes or hangs on unrecognized gesture rule values, for example, after a downgrade from a newer SDK version.
Fixed a crash that might have appeared when OZSDK was accessed again during its initialization.
Corrected the head-turn prompt direction for the rear camera.
Improved telemetry.
Refined internal processes.
Enhanced security.
The license can now be passed to the SDK as raw bytes through a new LicenseSource case, so a license fetched over the network needs no file on disk or in the app bundle. licenseFilePath and licenseFileName keep working unchanged.
Minimum supported deployment target is now iOS 12.
Resolved a crash that terminated the host app when a security check fired during SDK initialization.
The One Shot gesture is now marked as deprecated. On January 1, 2027, it will become unavailable. Please plan your .
The liveness screen hint no longer overlaps with the toolbar or other UI elements – it now renders above all liveness screen elements.
Internal improvements.
You can now rename the localization table via the method.
Reference photos larger than 5 MB are now compressed.
Fixed voiceover for the Close button and antiscam hint.
SDK no longer returns the DECLINED result if source media is compressed.
Updated internal dependencies.
Enhanced security.
The files passed via UserMedia in MediaRequest (OzCapsula) are now named using a UUID v4 identifier with the original file extension. The original file name can still be transmitted via the mediaMeta field.
Telemetry observer callbacks (EventObserver.update() and EventObserver.onDetected()) are now dispatched on a background thread.
Added the new addAnalysisProfile method. It allows appending an additional AnalysisProfile (e.g., a reference photo) to an existing OzCapsula container generated during capture, forming a multi-container package for biometric or comprehensive analyses. The session token and the existing OzCapsula instance are read from device memory automatically; no additional parameters are needed. Warning: requires API 6.6.1 and above.
The Scan gesture has been made easier to pass: resolved the issue with conflicting hints.
Updated sample to cover the case of biometric verification using OzCapsula.
Added support for optimized data transmission when using container.
You can now (if allowed by license).
The Scan gesture is now voiced properly.
Updated code sample in align with OzCapsula functionality.
Long antiscam messages are now displayed properly.
SDK no longer crashes when Liveness screen is called several times in a row with short intervals.
Resolved the issue with container errors not being returned.
Resolved the issue with SDK not returning the license-related callbacks.
Enhanced security.
Resolved the issue with SDK sometimes not responding to user actions on some devices.
Updated SDK to support the upcoming security features.
Fixed the bug with crashes that might happen during the Biometry analysis after taking a reference photo using camera.
Enhanced security.
The Scan gesture animation now works properly.
Fixed the bug where SDK didn’t call completion during initialization in debug mode.
Enhanced security.
Addressed an SDK crash that occasionally happened when invoking the license.
Resolved the issue with integration via Swift UI.
SDK no longer crashes on smartphones that are running low on storage.
Security and telemetry updates.
Security updates.
Xcode updated to version 16 to comply with Apple requirements.
Security updates.
Updated the authorization logic.
Improved voiceover.
SDK now compresses videos if their size exceeds 10 MB.
Head movement gestures are now handled properly.
Changed the wording for the head_down gesture: the new wording is “tilt down”.
Added proper focus order for VoiceOver when the antiscam hint is enabled.
Added the public setting extract_action_shot in the Demo Application.
Bug fixes.
Accessibility updates according to WCAG requirements: the SDK hints and UI controls can be voiced.
Improved user experience with head movement gestures.
Minor bug fixes and telemetry updates.
The screen brightness no longer changes when the rear camera is used.
Fixed the video recording issues on some smartphone models.
Security and telemetry updates.
Internal SDK improvements.
Added Xcode 16 support.
Security and telemetry updates.
Security updates.
Bug fixes.
SDK now requires Xcode 15 and newer.
Security updates.
Bug fixes.
Internal SDK improvements.
Internal SDK improvements.
Bug fixes.
Logging updates.
Security updates.
You can now install iOS SDK via Swift Package Manager.
The sample is now available on SwiftUI. Please find it .
Added a description for the error that occurs when providing an empty string as an ID in the addFolderID method.
Bug fixes.
The messages displayed by the SDK after uploading media have been synchronized with Android.
The bug causing analysis delays that might have occurred for the One Shot gesture has been fixed.
The length of the Selfie gesture is now (affects the video file size).
You can instead of Oz logo if your license allows it.
Removed the pause after the Scan gesture.
The code in is now up-to-date.
Security updates.
Changed the default behavior in case a localization key is missing: now the English string value is displayed instead of a key.
Fixed some bugs.
Internal licensing improvements.
Implemented the possibility of using a master license that works with any bundle_id.
Fixed the bug with background color flashing.
Bug fixes.
The Analysis structure now contains the sizeReductionStrategy field. This field defines what type of media is being sent to the server in case of the hybrid analysis once the on-device analysis is finished successfully.
The messages for the errors that are retrieved from API are now detailed.
The toFrameGradientColor
If multiple analyses are applied to the folder simultaneously, the system sends them as a group. It means that the “worst” of the results will be taken as resolution, not the latest. Please refer to this article for details.
For the Liveness analysis, the system now treats the highest score as a quantitative result. The Liveness analysis output is described .
Updated the Liveness on-device model.
Added the Portuguese (Brazilian) locale.
You can now add a custom or update an existing language pack. The instructions can be found .
If a media hasn't been uploaded correctly, the system now repeats the upload.
Fixed some bugs and improved the SDK algorithms.
Added the new analysis mode – hybrid (Liveness only). If the score received from an on-device analysis is too high, the system initiates a server-based analysis as an additional check.
Improved the on-device models.
Updated the run method.
Added new structures:
Added the center hint background customization.
Added new face frame forms (Circle, Square).
Added the antiscam widget and its customization. This feature allows you to alert your customers that the video recording is being conducted, for instance, for loan application purposes. The purpose of this is to safeguard against scammers who may attempt to deceive an individual into approving a fraudulent transaction.
Fixed the issue with the server-based One shot analysis.
Improved the SDK algorithms.
Fixed error handling when uploading a file to API. From this version, an error will be raised to a host application in case of an error during file upload.
Improved the on-device Liveness.
Fixed the animation for sunglasses/mask.
Fixed the bug with the .document analysis.
Updated the descriptions of customization methods and structures.
Updated the TensorFlow version to 2.11.
Fixed several bugs, including the Biometry check failures on some phone models.
Added customization for the hint animation.
Integrated a new model.
Added the uploadMedia method to AnalysisRequest. The addMedia method is now deprecated.
Fixed the combo analysis error.
Implemented a range of options and switched to the new design. To restore the previous settings, please refer to .
The run method now works similar to the one in Android SDK and returns an array of analysis' results.
Synchronized the version numbers with Android SDK.
Added a new field to the Analysis structure. The params field is for any additional parameters, for instance, if you need to set extracting the best shot on server to true. The best shot algorithm chooses the most high-quality frame from a video.
Fixed some localization issues.
The Zoom in and Zoom out gestures are no longer supported.
Added a new simplified analysis structure – AnalysisRequest.
Added methods of on-device analysis: runOnDeviceLivenessAnalysis and runOnDeviceBiometryAnalysis.
You can choose the installation version. Standard installation gives access to full functionality. The core version (OzLivenessSDK/Core) installs SDK without the on-device functionality.
Added the Turkish locale.
Added the Kyrgyz locale.
Added Completion Handler for analysis results.
Added Error User Info to telemetry to show detailed info in case of an analysis error.
Added local on-device analysis.
Added oval and rectangular frames.
Added Xcode 12.5.1+ support.
Added SDK configuration with licenses.
Added the One Shot gesture.
Improved OZVerificationResult: added bestShotURL which contains the best shot image and preferredMediaURL which contains an URL to the best quality video.
When performing a local check, you can now choose a main or back camera.
Authorization sessions extend automatically.
Updated authorization interfaces.
Added the Kazakh locale.
Added license error texts.
You can cancel network requests.
You can specify Bundle for license.
Added analysis parameterization documentAnalyse.
Added license support.
Added Xcode 12 support instead of 11.
Fixed the documentAnalyse error where you had to fill analyseStates to launch the analysis.
Oz Liveness Mobile SDK implements the ready-to-use face capture user interface that is essential for seamless customer experience and accurate liveness results.
This guide walks you through your first liveness check using Mobile SDK (iOS or Android) and Oz API.
The described flow combines:
Capture mode – the Mobile SDK captures the Liveness video in the app and the Client backend forwards it to Oz API. Capture results are not sent from the SDK straight to Oz API; the Client backend acts as an intermediary.
OzCapsula – a proprietary encrypted binary container. The SDK packages the captured media into it; only Oz API can decrypt and process it. On the device it is an opaque blob – you cannot decode or inspect it, only forward it as-is.
Each step is marked:
[Oz SDK] – call our SDK API.
[Your code] – call your own backend or your own code.
{{host}} in the examples below is the base URL of your Oz API deployment, provided to you during deployment setup.
Use Content-Type: application/octet-stream for any container uploaded to Oz API.
Before you begin, make sure you have Oz API credentials. When using SaaS API, you get them :
For the on-premise Oz API, you need to create a user yourself or ask your team that manages the API. See the . Consider the proper user role (CLIENT in most cases or CLIENT ADMIN, if you are going to make SDK work with the pre-created folders from other API users). In the end, you need to obtain a similar set of credentials as you would get for the SaaS scenario.
These parameters are mandatory for OzCapsula to work. Define them in your API configuration file.
We also recommend that you use our logging service called telemetry, as it helps a lot in investigating attacks' details. For Oz API users, the service is enabled by default. For on-premise installations, we'll provide you with credentials.
Oz Liveness Mobile SDK requires a license. License is bound to the bundle_id of your application, e.g., com.yourcompany.yourapp.
Call once per app launch.
OzCapsula uses a session token. The token is mandatory for OzCapsula.
Your backend requests a session token from Oz API. Request it before each capture session, as close to the moment the user starts capture as possible.
Endpoint:
With these steps, you are done with basic integration of Mobile SDKs. You will be able to access recorded media and analysis results in Web Console via browser or programmatically via API.
In developer guides, you can also find instructions for customizing the SDK look-and-feel and access the full list of our Mobile SDK methods. Check out the table below:
onErrorResolved an issue where a video recorded under heavy device load could be unusable for analysis.
The capture screen no longer hangs without a result when the recorded video cannot be read.
Refined internal processes.
Enhanced security.
Liveness no longer fails in debug builds that contain the Flex library.
Updated sample.
Updated the SDK to comply with Apple Required Reasons API.
The unbalanced dispatch_group_leave() crash on session timeout in view controller no longer occurs.
Removed the OZ_ prefix from cases of the ContainerType.
We now send the One Shot gesture media as ZIP instead of JPEG.
Enhanced security.
Resolved the issue with SQLCipher integration conflict.
Updated dependencies.
Security updates.
Security updates.
Security and logging updates.
hintAnimationCustomizationhintGradientColorGot back the iOS 11 support.
Added a new method to retrieve the telemetry (logging) identifier: getEventSessionId.
The setPermanentAccessToken, configure and login methods are now deprecated. Please use the setApiConnection method instead.
The setLicense(from path:String) method is now deprecated. Please use the setLicense(licenseSource: LicenseSource) method instead.
Fixed some bugs and improved the SDK work.
RequestStatusResultMediaRequestResultThe updated AnalysisResult structure should be now used instead of OzAnalysisResult.
For the OZMedia object, you can now specify additional tags that are not included into our tags list.
The Selfie video length is now about 0.7 sec, the file size and upload time are reduced.
The hint text width can now exceed the frame width (when using the main camera).
The methods below are no longer supported:
documentAnalyse
AnalysisRequest.run
uploadAndAnalyse
AnalysisRequest.run
runOnDeviceBiometryAnalysis
AnalysisRequest.run
runOnDeviceLivenessAnalysis
AnalysisRequest.run
addMedia
uploadMedia
Added the Spanish locale.
iOS 11 is no longer supported, the minimal required version is 12.
Added a button to reset the SDK theme and language settings.
Fixed some bugs and localization issues.
Extended the network request timeout to 90 sec.
Added a setting for the animation icon size.
Changed the Combo gesture.
Now you can launch the Liveness check to analyze images taken with another SDK.
uploadAndAnalyse.Improved the licensing process, now you can add a license when initializing SDK: OZSDK(licenseSources: [LicenseSource], completion: @escaping ((LicenseData?, LicenseError?) -> Void)), where LicenseSource is a path to physical location of your license, LicenseData contains the license information.
Added the setLicense method to force license adding.
Fixed logging.
Removed method
Replacement
analyse
AnalysisRequest.run
addToFolder
uploadMedia
Flutter
10.0.0
The authorization mechanism for calls to Oz API (access_token) depends on your installation settings: when using Instant API, you can integrate it under your own authorization scheme. If access token is required in your case, please check Authentication. Also, please note that access and session token are different tokens issued for different purposes.
Response:
This token is short-lived (default lifetime: 900 seconds for API Full, 120 seconds for Instant API). Request one per capture session and pass it to the SDK immediately – do not cache or reuse tokens across sessions.
Send the encrypted container to your own backend as raw bytes (application/octet-stream). Your backend forwards it to Oz API and returns the analysis response.
Your backend submits the container to Oz API in a single synchronous POST request.
Endpoint (Instant API):
POST {{host}}/api/instant/folders/Endpoint (Full API):
POST {{host}}/api/folders/Headers:
Content-Type: application/octet-stream (mandatory).
X-Forensic-Access-Token: {{access_token}}. (optional, depends on installation settings).
Request body: the raw container bytes – no JSON envelope, no multipart, no base64 wrapping.
Request (Instant API):
Request (Full API):
On success: HTTP 201 with a JSON folder object describing the result. Check Step 7.
On container-level error: HTTP 400 – see .
This guide covers the Liveness analysis. To perform a Face Matching analysis within the OzCapsula flow, see .
Your backend now has the response – a JSON folder object describing the result.
Make the accept/reject decision using only these two top-level fields:
$.resolution_status // "FINISHED" – analyses completed; "FAILED" – error during analysis processing
$.system_resolution // "SUCCESS", "DECLINED", or "FAILED"Interpret system_resolution:
SUCCESS – all checks passed; accept the user.
DECLINED – one or more checks failed; reject the user.
FAILED – a system error prevented at least one analysis from completing; do not treat as accept or reject.
For per-analysis verdicts (for example, to know whether liveness passed but biometry failed), read $.analyses[*].resolution_status with the values described above.
Oz API
6.6.1
iOS SDK
10.0.0
Android SDK
Login: j.doe@yourcompany.com
Password: …
API: https://<link>.ozforensics.com
Web Console: https://<link>.ozforensics.comOZ_SESSION_TOKEN_LIFETIME=<your_ttl_for_session_token>
OZ_JWT_PRIVATE_KEY_PATH=<jwt_private_key_path>
OZ_JWT_PUBLIC_KEY_PATH=<jwt_public_key_path>
OZ_MALEWICZ_ANALYSIS_ENABLED=trueGET {{host}}/api/authorize/session_tokenAndroid sample app source code
iOS sample app source code
Flutter sample app source code
Android SDK Developer Guide
iOS SDK Developer Guide
Flutter SDK Developer Guide
Demo app in PlayMarket
Demo app in TestFlight
10.0.0
curl --location -g '{{host}}/api/authorize/session_token' \
--header 'X-Forensic-Access-Token: {{access_token}}' ## optional, depends on installation settings{
"session_token": "<session_token>"
}curl -X POST '{{host}}/api/instant/folders/' \
--header 'X-Forensic-Access-Token: {{access_token}}' ## optional, depends on installation settings
-H 'Content-Type: application/octet-stream' \
--data-binary '@/path/to/container.dat'curl -X POST '{{host}}/api/folders/' \
--header 'X-Forensic-Access-Token: {{access_token}}' ## optional, depends on installation settings
-H 'Content-Type: application/octet-stream' \
--data-binary '@/path/to/container.dat'val captureRequest = CaptureRequest(
listOf(
AnalysisProfile(
Analysis.Type.QUALITY,
listOf(MediaRequest.ActionMedia(OzAction.Blank))
)
)
)
val intent = OzLivenessSDK.createMediaCaptureScreen(captureRequest, sessionToken)
startActivityForResult(intent, REQUEST_LIVENESS_CONTAINER)let mediaRequest = MediaRequest.action(.selfie)
let profile = AnalysisProfile(
mediaList: [mediaRequest],
type: .quality,
params: [:]
)
let request = CaptureRequest(
analysisProfileList: [profile],
cameraPosition: .front
)
let livenessVC = try OZSDK.createMediaCaptureScreen(
delegate,
request,
sessionToken: sessionToken // from Step 3
)
livenessVC.modalPresentationStyle = .fullScreen
parent.present(livenessVC, animated: true)final sessionToken = await _getSessionToken();
OZSDK.createMediaCaptureScreen(
CaptureRequest(
analysisProfileList: [
AnalysisProfile(
Type.quality,
mediaList: [ActionMedia(VerificationAction.blank)]
),
],
),
sessionToken,
);override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_LIVENESS_CONTAINER) {
when (resultCode) {
OzLivenessResultCode.SUCCESS -> {
val container = OzLivenessSDK.getContainerFromIntent(data)
handleContainer(container)
}
OzLivenessResultCode.USER_CLOSED_LIVENESS -> { /* user closed the screen */ }
else -> {
val errorMessage = OzLivenessSDK.getErrorFromIntent(data)
/* show error */
}
}
}
}extension YourViewController: LivenessDelegate {
func onResult(container: DataContainer) {
// Pass container to Step 6
handleContainer(container)
}
func onError(status: OZVerificationStatus?) {
// user cancelled, capture failed, etc.
}
}@override
void initState() {
super.initState();
_subscription = OZSDK.livenessResult.listen((result) {
if (result is DataContainer) {
// OzCapsula media
}
}, onError: (Object error) {
// handle error, in most cases PlatformException
});
}private fun handleContainer(container: DataContainer?) {
if (container == null) return
YourBackend.uploadOzContainer(
container = container.getBytes(),
contentType = "application/octet-stream"
)
}func handleContainer(_ container: DataContainer) {
YourBackend.uploadOzContainer(
container,
contentType: "application/octet-stream"
) { result in
DispatchQueue.main.async {
self.handleAnalysisResult(result)
}
}
}final Uint8List? containerBytes = await OZSDK.getContainerBytes(dataContainer);
await YourBackend.uploadOzContainer(
container: containerBytes,
contentType: "application/octet-stream",
);OzLivenessSDK.setEnvironment(OzLivenessSDK.Environment.DEBUG)OZSDK.setEnvironment(environment: .debug)OZSDK.setEnvironment(debug)To set your own look-and-feel options, use the style section in the Ozliveness.open method. The options are listed below the example.
OzLiveness.open({
style: {
baseColorCustomization: {
textColorPrimary: "#000000",
backgroundColorPrimary: "#FFFFFF",
textColorSecondary: "#8E8E93",
backgroundColorSecondary: "#F2F2F7",
iconColor: "#00A5BA"
},
baseFontCustomization: {
textFont: "Roboto, sans-serif",
textSize: "16px",
textWeight: "400",
textStyle: "normal"
},
titleFontCustomization: {
textFont: "inherit",
textSize: "36px",
textWeight: "500",
textStyle: "normal"
},
buttonCustomization: {
textFont: "inherit",
textSize: "14px",
textWeight: "500",
textStyle: "normal",
textColorPrimary: "#FFFFFF",
backgroundColorPrimary: "#00A5BA",
textColorSecondary: "#00A5BA",
backgroundColorSecondary: "#DBF2F5",
cornerRadius: "10px"
},
toolbarCustomization: {
closeButtonIcon: "cross",
iconColor: "#707070"
},
centerHintCustomization: {
textFont: "inherit",
textSize: "24px",
textWeight: "500",
textStyle: "normal",
textColor: "#FFFFFF",
backgroundColor: "#1C1C1E",
backgroundOpacity: "56%",
backgroundCornerRadius: "14px",
verticalPosition: "38%"
},
hintAnimation: {
hideAnimation: false,
hintGradientColor: "#00BCD5",
hintGradientOpacity: "100%",
animationIconSize: "80px"
},
faceFrameCustomization: {
geometryType: "oval",
cornersRadius: "0px",
strokeDefaultColor: "#D51900",
strokeFaceInFrameColor: "#00BCD5",
strokeOpacity: "100%",
strokeWidth: "6px",
strokePadding: "4px"
},
documentFrameCustomization: {
cornersRadius: "20px",
templateColor: "#FFFFFF",
templateOpacity: "100%"
},
backgroundCustomization: {
backgroundColor: "#FFFFFF",
backgroundOpacity: "88%"
},
antiscamCustomization: {
enableAntiscam: true,
textMessage: "",
textFont: "inherit",
textSize: "14px",
textWeight: "500",
textStyle: "normal",
textColor: "#000000",
textOpacity: "100%",
backgroundColor: "#F2F2F7",
backgroundOpacity: "100%",
backgroundCornerRadius: "20px",
flashColor: "#FF453A",
verticalPosition: "84%"
},
versionTextCustomization: {
textFont: "inherit",
textSize: "16px",
textWeight: "500",
textStyle: "normal",
textColor: "#000000",
textOpacity: "56%"
},
/* On January 1, 2027, 3D Mask will become unavailable. */
maskCustomization: {
maskColor: "#008700",
glowColor: "#000102",
minAlpha: "30%", /* 0 to 1 or 0% to 100% */
maxAlpha: "100%" /* 0 to 1 or 0% to 100% */
},
switchCameraButtonCustomization: {
enableSwitchCameraButton: true,
},
logo: {
url: 'https://your-website-link/logo.svg', /* custom logo, only if allowed by license */
position: 'bottom-center', /* or 'bottom-left' */
width: 120,
height: 40
},
closeButtonSlot: '<svg>...</svg>', /* HTMLElement or null */
.ozliveness_wrap_overlay .ozliveness_face_stroke {
overflow: hidden;
box-shadow: 0 0 10px rgb(90 201 207);
border: none; /* Important to remove default border */
},
/* for an HTML string, use string; for HTMLElement, insert it via cloneNode(true) */
loaderSlot: yourLoader, /* <string | HTMLElement> */
loaderTransition: {type: 'fade', duration: 500}
}
});Main color settings.
Parameter
Description
Main font settings.
Title font settings.
Buttons’ settings.
Toolbar settings.
Center hint settings.
Hint animation settings.
Face frame settings.
Document capture frame settings.
Background settings.
Scam protection settings: the antiscam message warns user about their actions being recorded.
SDK version text settings.
3D mask settings. The mask has been implemented in 1.2.1. On January 1, 2027, 3D Mask will become unavailable. Please plan your .
Use this setting to hide the Switch Camera button (added in 1.7.14).
Settings for a custom loader (added in 1.7.15).
Loader transition settings (added in 1.8.0).
Use this class to customize the oval (added in 1.9.2). All standard CSS properties are supported.
Manages the logo position (added in 1.9.7).
Replaces the default close button with a custom HTML string or HTMLElement (added in 1.9.7).
Table of parameters' correspondence:
textColorPrimary
Main text color
backgroundColorPrimary
Main background color
textColorSecondary
Secondary text color
backgroundColorSecondary
Secondary background color
iconColor
Icons’ color
Parameter
Description
textFont
Font
textSize
Font size
Parameter
Description
textFont
Font
textSize
Font size
Parameter
Description
textFont
Font
textSize
Parameter
Description
closeButtonIcon
Close button icon
iconColor
Close button icon color
Parameter
Description
textFont
Font
textSize
Parameter
Description
hideAnimation
Disable animation
hintGradientColor
Gradient color
Parameter
Description
geometryType
Frame shape: rectangle or oval
cornersRadius
Frame corner radius (for rectangle)
Parameter
Description
cornersRadius
Frame corner radius
templateColor
Document template color
Parameter
Description
backgroundColor
Background color
backgroundOpacity
Background opacity
Parameter
Description
enableAntiscam
true displays the antiscam message with its settings
textMessage
Parameter
Description
textFont
Font
textSize
Font size
Parameter
Description
maskColor
The color of the mask itself
glowColor
The color of the glowing mask shape
Parameter
Description
enableSwitchCameraButton
true (default) – shows the Switch Camera button,
false – hides the button.
Event
Payload
Is called
loader:init
{os, browser, platform}
immediately after inserting the slot
loader:waitingCamera
Parameter
Description
type
Animation type: none, fade, slide, scale
duration
Animation length in ms
easing (optional)
Parameter
Description
url
URL for custom logo, only if if (additionally charged). Formats: SVG (recommended), PNG, JPG
position
Logo position:
bottom-left (default) – on the left,
bottom-center – in center
Previous design
New design
doc_color
-
face_color_success
faceFrame.faceReady
textWeight
Font weight
textStyle
Font style
textWeight
Font weight
textStyle
Font style
Font size
textWeight
Font weight
textStyle
Font style
textColorPrimary
Main text color
backgroundColorPrimary
Main background color
textColorSecondary
Secondary text color
backgroundColorSecondary
Secondary background color
cornerRadius
Button corner radius
Font size
textWeight
Font weight
textStyle
Font style
textColor
Text color
backgroundColor
Background color
backgroundOpacity
Background opacity
backgroundCornerRadius
Frame corner radius
verticalPosition
Vertical position
hintGradientOpacity
Gradient opacity
animationIconSize
Animation icon size
strokeDefaultColor
Frame color when a face is not aligned properly
strokeFaceInFrameColor
Frame color when a face is aligned properly
strokeOpacity
Stroke opacity
strokeWidth
Stroke width
strokePadding
Padding from stroke
templateOpacity
Document template opacity
Antiscam message text
textFont
Font
textSize
Font size
textWeight
Font weight
textStyle
Font style
textColor
Text color
textOpacity
Text opacity
backgroundColor
Background color
backgroundOpacity
Background opacity
backgroundCornerRadius
Frame corner radius
flashColor
Flashing indicator color
verticalPosition
Vertical position of the antiscam message; if not set, the message is bound the the top of the oval
textWeight
Font weight
textStyle
Font style
textColor
Text color
textOpacity
Text opacity
minAlpha
Minimum mask transparency level. Implemented in 1.3.1
maxAlpha
Maximum mask transparency level. Implemented in 1.3.1
{os, browser, platform, waitedMs}
every waitedMs ms, while waiting for camera access
loader:cameraReady
when access is granted and loader should be hidden
loader:processing
{phase: 'start' | 'end'}
before / after data preparation
loader:uploading
{phase: 'start' | 'progress' | 'end', percent?}
before / during / after data transmission
loader:destroy
when you need to hide the slot
easing: linear, ease-in-out, etc
width
Logo width
height
Logo height
faceFrameCustomization.strokeFaceInFrameColor
face_color_fail
faceFrame.faceNotReady
faceFrameCustomization.strokeDefaultColor
centerHint.textSize
centerHintCustomization.textSize
centerHint.color
centerHintCustomization.textColor
centerHint.yPosition
centerHintCustomization.verticalPosition
centerHint.letterSpacing
-
centerHint.fontStyle
centerHintCustomization.textStyle
closeButton.image
-
backgroundOutsideFrame.color
backgroundCustomization.backgroundColor
Android SDK changes
Added an experimental option that turns on the flashlight during capture with the rear camera: mainCameraFlashModeEnabled. It has no effect on the front camera.
The ON_DEVICE and HYBRID analysis modes are now deprecated and will be removed on January 1, 2027; please plan your migration to SERVER_BASED.
Resolved a BadTokenException crash when a dialog opened while the capture screen was closing.
Added large-screen support for Android 16: if the host app targets SDK 36, capture works in any orientation and when resized on devices with a smallest width of 600 dp or more.
Upload errors with a non-JSON body, such as 502 Bad Gateway, are now retried and show an OzException with the HTTP code instead of a parsing error.
Resolved an issue where devices with swapped camera color channels could cause a false reject; still frames from these devices no longer look blue or purple.
Liveness no longer crashes or hangs on unrecognized gesture rule values, for example, after a downgrade from a newer SDK version.
Fixed a bug where the analysis could sometimes fail with Invalid request: missing a mandatory parameter under certain Oz API configurations.
The app no longer crashes when opening the capture screen on devices that fail to list video encoders. If no encoder is available, onError gets VIDEO_RECORD_ERROR.
OzCapsula capture no longer fails with error code 38 when the user completes the gesture too fast.
Corrected the head-turn prompt direction for the rear camera.
Fixed the rear camera bug: the face oval no longer shrinks when recording starts, users aren’t asked to move away, and the antiScamCustomization banner stays in place.
Refined internal processes.
Enhanced security.
Resolved a rare issue caused by an internal dependency that could affect analysis results in certain host application build configurations.
Videos captured on Xiaomi 12 Turbo no longer turn out green.
Opening the Liveness screen no longer causes an ANR on low-end devices.
The license can now be passed to OzLivenessSDK.init(...) as raw bytes through a new LicenseSource variant LicenseData, so a license fetched over the network needs no file on disk or in assets. LicenseAssetId and LicenseFilePath keep working unchanged.
Minimum supported Android SDK (API Level) version is now 24.
Optimized the custom TFLite native library to reduce SDK size.
The One Shot gesture is now marked as deprecated. On January 1, 2027, it will become unavailable. Please plan your .
The liveness screen hint no longer overlaps with the toolbar or other UI elements – it now renders above all liveness screen elements.
We no longer support CameraX.
On Android 36+, tapping the Back button during a liveness session now returns the correct error.
Resolved a camera launch error on some devices.
Updated internal dependencies.
Enhanced security.
Updated internal dependencies.
Enhanced security.
The files passed via UserMedia in MediaRequest (OzCapsula) are now named using a UUID v4 identifier with the original file extension. The original file name can still be transmitted via the mediaMeta field.
Telemetry observer callbacks (EventObserver.update() and EventObserver.onDetected()) are now dispatched on a background thread.
Added the new addAnalysisProfile method. It allows appending an additional AnalysisProfile (e.g., a reference photo) to an existing OzCapsula container generated during capture, forming a multi-container package for biometric or comprehensive analyses. The session token and the existing OzCapsula instance are read from device memory automatically; no additional parameters are needed. Warning: requires API 6.6.1 and above.
The Scan gesture has been made easier to pass: resolved the issue with conflicting hints.
The Action rules unavailable error, which might have appeared on the first liveness attempt, no longer occurs.
Selfie gesture recording now stops strictly at the configured timeout to normalize video duration across devices.
If user can’t take a video, the new timeout counter for video capture now starts after the error timeout dialog is shown.
Updated internal dependencies.
Fixed the bug with “Unknown Error” being returned even in case of successful video capture.
Resolved the issue with occasional crashes caused by improper preview scaling on some devices.
You can now (if allowed by license).
In case of lost internet connection during license checking, SDK now returns the proper error.
Updated code sample to align with OzCapsula functionality.
Fixed the bug with green videos appearing on some devices.
Resolved the issue with occasional SDK crashes caused by restrictions of device camera.
Fixed minor bugs.
Fixed the bug with SDK crashes caused by the “Invalid to call at Released state” and “Pending dequeue output buffer request cancelled” errors.
Fixed the bug with "java.util.concurrent.TimeoutException" causing crashes.
Android SDK now passes orientation and media type tags along with the action one.
Enhanced security.
Fixed a minor bug.
Fixed occasional SDK crashes in specific cases and / or on specific devices.
Enhanced security.
Improved SDK performance for some devices.
Updated SDK to support the upcoming security features.
Fixed the bug with green videos on some smartphone models.
Resolved the issue with mediaId appearing null.
Enhanced security.
Resolved an issue with warning that could appear when running Fragment.
SDK no longer crashes when calling copyPlane.
When you choose to send compressed videos for a hybrid analysis, SDK no longer saves original media as well as compressed.
Updated Oz Forensics website link.
To support memory page size of 16 KB, switched TensorFlow to LiteRT.
Fixed the bug that caused video duration and file size to increase.
Added support for Google Dynamic Feature Delivery.
Resolved an issue that might have caused crashes when taping the close button on the Liveness screen.
Fixed a bug where the SDK would crash with "CameraDevice was already closed" exception.
Security and telemetry updates.
Resolved the issue with OkHttp compatibility.
Fixed the bug with Fragment missing context.
Resolved a camera access issue affecting some mobile device models.
Security updates.
Security updates.
Security updates.
Resolved the issue with possible SDK crashes when closing the Liveness screen.
Security updates.
Updated the authorization logic.
Improved voiceover.
Fixed the issue with SDK lags and the non-responding error that users might have encountered on some devices after completing the video recording.
Resolved the issue with SDK crashes on some devices that might have occurred because of trying to access non-initialized or closed resources.
Security updates.
You can now disable video validation that has been implemented to avoid recording of extremely short videos (3 frames and less): switch the option off using .
Fixed the bug with green videos on some smartphone models.
Security updates.
Fixed bugs that could have caused crashes on some phone models.
Changed the wording for the head_down gesture: the new wording is “tilt down”.
Added proper focus order for TalkBack when the antiscam hint is enabled.
Added the public setting extract_action_shot in the Demo Application.
Fixed bugs.
Fixed the bug when the recorded videos might appear green.
Resolved codec issues on some smartphone models.
Accessibility updates according to WCAG requirements: the SDK hints and UI controls can be voiced.
Improved user experience with head movement gestures.
Moved the large video compression step to the Liveness screen closure.
Fixed the bug when the best shot frame could contain an image with closed eyes.
Security and telemetry updates.
Security updates.
Security updates.
Security and telemetry updates.
Fixed the RuntimeException error with the server-based Liveness that appeared on some devices.
Security updates.
Security updates.
Bug fixes.
Updated the Android Gradle plugin version to 8.0.0.
Internal SDK improvements.
Internal SDK improvements.
Security updates.
Security updates.
Security updates.
Security updates.
Added a description for the error that occurs when providing an empty string as an ID in the setFolderID method.
Fixed a bug causing an endless spinner to appear if the user switches to another application during the Liveness check.
Fixed some smartphone model specific-bugs.
Upgraded the on-device Liveness model.
Security updates.
The length of the Selfie gesture is now (affects the video file size).
You can instead of Oz logo if your license allows it.
Removed the pause after the Scan gesture.
If the recorded video is larger than 10 MB, it gets compressed.
Changed the master license validation algorithm.
Downgraded the required compileSdkVersion from 34 to 33.
Security updates.
Updated the on-device Liveness model.
Fixed some bugs.
Internal licensing improvements.
Internal SDK improvements.
Bug fixes.
Implemented the possibility of using a master license that works with any bundle_id.
Video compression failure on some phone models is now fixed.
Bug fixes.
The Analysis structure now contains the sizeReductionStrategy field. This field defines what type of media is being sent to the server in case of the hybrid analysis once the on-device analysis is finished successfully.
The messages for the errors that are retrieved from API are now detailed.
If multiple analyses are applied to the folder simultaneously, the system sends them as a group. It means that the “worst” of the results will be taken as resolution, not the latest. Please refer to this article for details.
For the Liveness analysis, the system now treats the highest score as a quantitative result. The Liveness analysis output is described .
Updated the Liveness on-device model.
Added the Portuguese (Brazilian) locale.
You can now add a custom or update an existing language pack. The instructions can be found .
If a media hasn't been uploaded correctly, the system repeats the upload.
Fixed errors.
The SDK now works properly with baseURL set to null.
The dependencies' versions have been brought into line with Kotlin version.
Added the new analysis mode – hybrid (Liveness only). If the score received from an on-device analysis is too high, the system initiates a server-based analysis as an additional check.
Kotlin version requirements lowered to 1.7.21.
Improved the on-device models.
For some phone models, fixed the fatal device error.
Restructured the settings screen.
Added the center hint background customization.
Added new face frame forms (Circle, Square).
Added the antiscam widget and its customization. This feature allows you to alert your customers that the video recording is being conducted, for instance, for loan application purposes. The purpose of this is to safeguard against scammers who may attempt to deceive an individual into approving a fraudulent transaction.
Improved the SDK algorithms.
Updated the model for the on-device analyses.
Fixed the animation for sunglasses/mask.
The oval size for Liveness is now smaller.
Fixed the error with the server-based analyses while using permanentAccessToken for authorization.
Added customization for the .
You can now hide the status bar and system buttons (works with 7.0.0 and newer).
OzLivenessSDK.init now requires context as the first parameter.
Fixed crashes for Android v.6 and below.
Fixed oval positioning for some phone models.
Internal fixes and improvements.
Updated security.
Implemented some internal improvements.
The addMedia method is now deprecated, please use uploadMedia for uploading.
Changed the way of sharing dependencies. Due to security issues, now we share two types of libraries as shown below: sdk is a server analysis only, full provides both server and on-device analyses:
UICustomization has been implemented instead of OzCustomization.
Implemented a range of options and switched to the new design. To restore the previous settings, please refer to .
Added the Spanish locale.
Fixed the bug with freezes that had appeared on some phone models.
SDK now captures videos in 720p.
Synchronized the names of the analysis modes with iOS: SERVER_BASED and ON_DEVICE.
Fixed the bug with displaying of localization settings.
Now you can use Fragment as Liveness screen.
Added a new field to the Analysis structure. The params field is for any additional parameters, for instance, if you need to set extracting the best shot on server to true. The best shot algorithm chooses the most high-quality frame from a video.
The Zoom in and Zoom out gestures are no longer supported.
Updated the biometry model.
Added a new simplified API – AnalysisRequest. With it, it’s easier to create a request for the media and analysis you need.
Published the on-device module for on-device liveness and biometry analyses. To add this module to your project, use:
To launch these analyses, use runOnDeviceBiometryAnalysis and runOnDeviceLivenessAnalysis methods from the OzLivenessSDK class:
Liveness now goes smoother.
Fixed freezes on Xiaomi devices.
Optimized image converting.
New metadata parameter for OzLivenessSDK.uploadMedia and new OzLivenessSDK.uploadMediaAndAnalyze method to pass this parameter to folders.
Added functions for SDK initialization with LicenseSources: LicenseSource.LicenseAssetId and LicenseSource.LicenseFilePath. Use the OzLivenessSDK.init method to start initialization.
Now you can get the license info upon initialization val licensePayload = OzLivenessSDK.getLicensePayload().
Added the Kyrgyz locale.
Added local analysis functions.
You can now configure the face frame.
Fixed version number at the Liveness screen.
Added the main camera support.
Added configuration from license support.
Added the OneShot gesture.
Added new states for OzAnalysisResult.Resolution.
Added the uploadMediaAndAnalyze method to load a bunch of media to the server at once and send them to analysis immediately.
Access token updates automatically.
Renamed accessToken to permanentAccessToken.
Added R8 rules.
Fixed the oval frame.
Removed the unusable parameters from AnalyseRequest.
Removed default attempt limits.
To customize the configuration options, the config property is added instead of baseURL, accessToken, etc. Use OzConfig.Builder for initialization.
Added license support. Licences should be installed as raw resources. To pass them to OzConfig, use setLicenseResourceId.
Replaced the context-dependent methods with analogs.
Each of the new API users should obtain a role to define access restrictions for direct API connections. Set the role in the user_type field when you create a new user.
ADMIN is a system administrator, who has unlimited access to all system objects, but can't change the analyses' statuses;
OPERATOR is a system operator, who can view all system objects and choose the analysis result via the Make Decision button (usually needed if the is OPERATOR_REQUIRED);
CLIENT is a regular consumer account, who can upload media files, process analyses, view results in personal folders, generate reports for analyses.
can_start_analysis_biometry – an additional flag to allow access to analyses (enabled by default);
can_start_analysis_quality
CLIENT ADMIN is a company administrator that can manage their company account and users within it. Additionally, CLIENT ADMIN can view and edit data of all users within their company, delete files in folders, add or delete report templates with or without attachments, the reports themselves and single analyses, check statistics, add new blacklist collections.
CLIENT OPERATOR is similar to OPERATOR within their company.
CLIENT SERVICE is a service user account for automatic connection purposes. Authentication with this user creates a long-live access token (5 years by default). The token lifetime for regular uses is 15 minutes by default (parameterized) and, also by default, the lifetime of a token is extended with each request (parameterized).
Here's the detailed information on access levels.
can_start_analysis_collection – an additional flag to allow access to BLACK LIST analyses (enabled by default).
+
+
+
OPERATOR
-
+
-
-
CLIENT
-
their company data
-
-
CLIENT SERVICE
-
their company data
-
-
CLIENT OPERATOR
-
their company data
-
-
CLIENT ADMIN
-
their company data
their company data
their company data
+
+
+
OPERATOR
+
+
+
-
CLIENT
their folders
their folders
their folders
-
CLIENT SERVICE
within their company
within their company
within their company
-
CLIENT OPERATOR
within their company
within their company
within their company
-
CLIENT ADMIN
within their company
within their company
within their company
within their company
+
+
+
OPERATOR
+
+
+
-
CLIENT
-
within their company
-
-
CLIENT SERVICE
-
within their company
-
-
CLIENT OPERATOR
within their company
within their company
within their company
-
CLIENT ADMIN
within their company
within their company
within their company
within their company
+
OPERATOR
+
+
-
CLIENT
-
within their company
-
CLIENT SERVICE
-
within their company
-
CLIENT OPERATOR
within their company
within their company
-
CLIENT ADMIN
within their company
within their company
within their company
+
OPERATOR
+
+
-
CLIENT
in their folders
in their folders
-
CLIENT SERVICE
within their company
within their company
-
CLIENT OPERATOR
within their company
within their company
-
CLIENT ADMIN
within their company
within their company
within their company
+
+
+
OPERATOR
+
+
+
-
CLIENT
in their folders
in their folders
-
-
CLIENT SERVICE
within their company
within their company
within their company
-
CLIENT OPERATOR
within their company
within their company
within their company
-
CLIENT ADMIN
within their company
within their company
within their company
within their company
+
+
+
OPERATOR
-
+
-
-
CLIENT
-
within their company
-
-
CLIENT SERVICE
within their company
within their company
-
-
CLIENT OPERATOR
-
within their company
-
-
CLIENT ADMIN
within their company
within their company
within their company
within their company
+
OPERATOR
-
+
-
CLIENT
-
within their company
-
CLIENT SERVICE
within their company
within their company
-
CLIENT OPERATOR
-
within their company
-
CLIENT ADMIN
within their company
within their company
within their company
+
OPERATOR
-
+
-
CLIENT
-
within their company
-
CLIENT SERVICE
-
within their company
-
CLIENT OPERATOR
-
within their company
-
CLIENT ADMIN
within their company
within their company
within their company
+
+
+
OPERATOR
-
+
their data
-
CLIENT
-
their data
their data
-
CLIENT SERVICE
-
within their company
their data
-
CLIENT OPERATOR
-
within their company
their data
-
CLIENT ADMIN
within their company
within their company
within their company
within their company
Create
Read
Update
Delete
ADMIN
Create
Read
Update
Delete
ADMIN
Create
Read
Update
Delete
ADMIN
Create
Read
Delete
ADMIN
+
Create
Read
Delete
ADMIN
+
Create
Read
Update
Delete
ADMIN
Create
Read
Update
Delete
ADMIN
Create
Read
Delete
ADMIN
+
Create
Read
Delete
ADMIN
+
Create
Read
Update
Delete
ADMIN
+
+
+
+
+
+
+
+
+
+
faceAlignmentTimeout from OzConfig is applied again: liveness closes with an error when no face is detected within the configured timeout.
Resolved green artifacts in video capture on Pixel 3a XL that left the face undetected and failed the analysis.
Moved generation of the new event_session_id into createStartIntent, so OzLivenessSDK.getEventSessionId() returns the current id as soon as the screen is opened and two consecutive sessions no longer share one id.
The camera now closes cleanly when the app is minimized and restored during liveness capture.
Refined internal processes.
Enhanced security.
Internal improvements.
Removed the OzForensics namespace reference from the Android manifest.
Rebuilt TensorFlow Lite with 16 KB page alignment to comply with Google's updated requirements; the RELRO alignment warning at build/publish no longer occurs.
A rare codec-related crash during liveness recording no longer appears.
The sample app now covers the scenario of biometric authentication using OzCapsula.
Videos captured in the Hybrid analysis flow are now compressed correctly.
Sessions that might have failed with the CameraDevice was already closed error due to a camera pipeline race condition now complete successfully. The VIDEO_RECORD_ERROR result code is now correctly returned for the remaining edge cases.
Added edge-to-edge display support required for Android 16. The UI now correctly adapts to system insets — the close button no longer overlaps the status bar.
Enhanced security.
Security updates.
Security updates.
Minor bug fixes and telemetry updates.
Security and logging updates.
Created a new method to retrieve the telemetry (logging) identifier: getEventSessionId.
The login and auth methods are now deprecated. Use the setAPIConnection method instead.
OzConfig.baseURL and OzConfig.permanentAccessToken are now deprecated.
If a user closes the screen during video capture, the appropriate error is now being handled by SDK.
Fixed some bugs and improved the SDK work.
The hint text width can now exceed the frame width (when using the main camera).
Photos taken during the One Shot analysis are now being sent to the server in the original size.
Removed the OzAnalysisResult class. The onSuccess method ofAnalysisRequest.run now uses the RequestResult structure instead of List<OzAnalysisResult>.
All exceptions are moved to the com.ozforensics.liveness.sdk.core.exceptions package (See changes below).
Classes related to AnalysisRequest are moved to the com.ozforensics.liveness.sdk.analysispackage (See changes below).
The methods below are no longer supported:
OzLivenessSDK.runOnDeviceBiometryAnalysis
AnalysisRequest.run
OzLivenessSDK.runOnDeviceLivenessAnalysis
AnalysisRequest.run
AnalysisRequest.build(): AnalysisRequest
-
AnalysisRequest.Builder.addMedia
AnalysisRequest.Builder.uploadMedia
The OzLivenessSDK::init method no longer crashes if there is a StatusListener parameter passed.
Changed the scan gesture animation.
OzAnalysisResult now shows the server-based analyses' scores properly.
Fixed initialization issues, displaying of wrong customization settings, authorization failures on Android <7.1.1.
OzMedia is renamed to OzAbstractMedia and got subclasses for images and videos.
Fixed camera bugs for some devices.
Configuration became easier: config settings are mutable.
Improved the image analysis.
Removed unusable dependencies.
Fixed logging.
Removed method
Replacement
OzLivenessSDK.uploadMediaAndAnalyze
AnalysisRequest.run
OzLivenessSDK.uploadMedia
AnalysisRequest.Builder.uploadMedia
implementation 'com.ozforensics.liveness:full:7.0.0'
implementation 'com.ozforensics.liveness:sdk:7.0.0' implementation 'com.ozforensics.liveness:on-device:6.3.4'val mediaList: List<OzAbstractMedia> = ...
val biometryAnalysisResult: OzAnalysisResult = OzLivenessSDK.runOnDeviceBiometryAnalysis(mediaList)
val livenessAnalysisResult: OzAnalysisResult = OzLivenessSDK.runOnDeviceLivenessAnalysis(mediaList)TokenException from com.ozforensics.liveness.sdk.exceptions в com.ozforensics.liveness.sdk.core.exceptions
NoMediaInAnalysisException from com.ozforensics.liveness.sdk.exceptions to com.ozforensics.liveness.sdk.core.exceptions
EmptyMediaListException from com.ozforensics.liveness.sdk.exceptions to com.ozforensics.liveness.sdk.core.exceptions
NoSuchMediaException from com.ozforensics.liveness.sdk.exceptions to com.ozforensics.liveness.sdk.core.exceptions
LicenseException from com.ozforensics.liveness.sdk.exceptions to com.ozforensics.liveness.sdk.security.exception
Analysis from com.ozforensics.liveness.sdk.analysis.entity to com.ozforensics.liveness.sdk.core.model
AnalysisRequest from com.ozforensics.liveness.sdk.analysis to com.ozforensics.liveness.sdk.core
AnalysisListener from com.ozforensics.liveness.sdk.analysis to com.ozforensics.liveness.sdk.core
AnalysisStatus from com.ozforensics.liveness.sdk.analysis to com.ozforensics.liveness.sdk.core
AnalysisRequest.Builder from com.ozforensics.liveness.sdk.analysis to com.ozforensics.liveness.sdk.core
OzException from com.ozforensics.liveness.sdk.exceptions to com.ozforensics.liveness.sdk.core.exceptions
Removed runOnDeviceLivenessAnalysis
Use this method to check what versions of components are used (available from 1.1.1).
Call GET /version
-
GET localhost/version
In case of success, the method returns a message with the following parameters.
HTTP response content type: “application/json”.
Use this method to check whether the biometric processor is ready to work.
Call GET /v1/face/pattern/health
-
GET localhost/v1/face/pattern/health
In case of success, the method returns a message with the following parameters.
HTTP response content type: “application/json”.
The method is designed to extract a biometric template from an image.
HTTP request content type: “image / jpeg” or “image / png”
Call POST /v1/face/pattern/extract
In case of success, the method returns a biometric template.
The content type of the HTTP response is “application/octet-stream”.
The method is designed to compare two biometric templates.
The content type of the HTTP request is “multipart / form-data”.
CallPOST /v1/face/pattern/compare
In case of success, the method returns the result of comparing the two templates.
HTTP response content type: “application/json”.
The method combines the two methods from above, extract and compare. It extracts a template from an image and compares the resulting biometric template with another biometric template that is also passed in the request.
The content type of the HTTP request is “multipart / form-data”.
Call POST /v1/face/pattern/verify
In case of success, the method returns the result of comparing two biometric templates and the biometric template.
The content type of the HTTP response is “multipart/form-data”.
The method also combines the two methods from above, extract and compare. It extracts templates from two images, compares the received biometric templates, and transmits the comparison result as a response.
The content type of the HTTP request is “multipart / form-data”.
Call POST /v1/face/pattern/extract_and_compare
In case of success, the method returns the result of comparing the two extracted biometric templates.
HTTP response content type: “application / json”.
Use this method to compare one biometric template to N others.
The content type of the HTTP request is “multipart/form-data”.
Call POST /v1/face/pattern/compare_n
In case of success, the method returns the result of the 1:N comparison.
HTTP response content type: “application / json”.
The method combines the extract and compare_n methods. It extracts a biometric template from an image and compares it to N other biometric templates that are passed in the request as a list.
The content type of the HTTP request is “multipart/form-data”.
Call POST /v1/face/pattern/verify_n
In case of success, the method returns the result of the 1:N comparison.
HTTP response content type: “application / json”.
This method also combines the extract and compare_n methods but in another way. It extracts biometric templates from the main image and a list of other images and then compares them in the 1:N mode.
The content type of the HTTP request is “multipart/form-data”.
Call POST /v1/face/pattern/extract_and_compare_n
In case of success, the method returns the result of the 1:N comparison.
HTTP response content type: “application / json”.
HTTP response content type: “application / json”.
Use this method to check whether the liveness processor is ready to work.
Call GET /v1/face/liveness/health
None.
GET localhost/v1/face/liveness/health
In case of success, the method returns a message with the following parameters.
HTTP response content type: “application/json”.
The detect method is made to reveal presentation attacks. It detects a face in each image or video (since 1.2.0), sends them for analysis, and returns a result.
The method supports the following content types:
image/jpeg or image/png for an image;
multipart/form-data for images, videos, and archives. You can use payload to add any parameters that affect the analysis.
To run the method, call POST /{version}/face/liveness/detect.
Accepts an image in JPEG or PNG format. No payload attached.
Accepts the multipart/form-data request.
Each media file should have a unique name, e.g., media_key1, media_key2.
The payload parameters should be a JSON placed in the payload field.
To extract the best shot from your video or archive, in analyses, set extract_best_shot = true (as shown in the request example below). In this case, API Lite will analyze your archives and videos, and, in response, will return the best shot. It will be a base64 image in analysis->output_images->image_b64.
HTTP response content type: “application / json”.
Parameter name
Type
Description
core
String
API Lite core version number.
tfss
String
TFSS version number.
200 OK
Content-Type: application/json
{
2 "core": "core_version",
3 "tfss": "tfss_version",
4 "models": [
5 {
6 "name": "model_name",
7 "version": "model_version"
8 }
9 ]
10}Parameter name
Type
Description
status
Int
0 – the biometric processor is working correctly.
3 – the biometric processor is inoperative.
200 OK
Content-Type: application/json
{“status”: 0, message: “”}Parameter name
Type
Description
Not specified*
Stream
Required parameter. Image to extract the biometric template.
The “Content-Type” header field must indicate the content type.
POST localhost/v1/face/pattern/extract
Content-Type: image/jpeg
{Image byte stream}Parameter name
Type
Description
Not specified*
Stream
A biometric template derived from an image
200 OK
Content-Type: application/octet-stream
{Biometric template byte stream}Parameter name
Type
Description
bio_feature
Stream
Required parameter.
First biometric template.
POST localhost/v1/face/pattern/compare
Content-Type: multipart/form-data;
boundary=--BOUNDARY--
Content-Length: Message body length
--BOUNDARY--
Content-Disposition: form-data; name=”bio_feature”
Content_type: application/octet-stream
{Biometric template byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”bio_template”
Content_type: application/octet-stream
{Biometric template byte stream}
--BOUNDARY--Parameter name
Type
Description
score
Float
The result of comparing two templates
200 OK
Content-Type: application/json
{“score”: 1.0, “decision”: “approved”}Parameter name
Type
Description
sample
Stream
Required parameter.
Image to extract the biometric template.
POST localhost/v1/face/pattern/verify
Content-Type: multipart/form-data;
boundary=--BOUNDARY--
Content-Length: Message body length
--BOUNDARY--
Content-Disposition: form-data; name=”bio_template”
Content_type: application/octet-stream
{Biometric template byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”sample”
Content_type: image/jpeg
{Image byte stream}
--BOUNDARY--Parameter name
Type
Description
score
Float
The result of comparing two templates
200 OK
Content-Type: multipart/form-data;
boundary=--BOUNDARY--
Content-Length: Message body length
--BOUNDARY--
Content-Disposition: form-data; name=”score”
Content_type: application/json
{“score”: 1.0}
--BOUNDARY--
Content-Disposition: form-data; name=”bio_feature”
Content_type: application/octet-stream
{Biometric template byte stream}
--BOUNDARY--Parameter name
Type
Description
sample_1
Stream
Required parameter.
First image.
POST localhost/v1/face/pattern/extract_and_compare
Content-Type: multipart/form-data;
boundary=--BOUNDARY--
Content-Length: Message body length
--BOUNDARY--
Content-Disposition: form-data; name=”sample_1”
Content_type: image/jpeg
{Image byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”sample_2”
Content_type: image/jpeg
{Image byte stream}
--BOUNDARY--Parameter name
Type
Description
score
Float
The result of comparing the two extracted templates.
200 OK
Content-Type: application/json
{“score”: 1.0, “decision”: “approved”}Parameter name
Type
Description
template_1
Stream
This parameter is mandatory. The first (main) biometric template
POST localhost/v1/face/pattern/compare_n
Content-Type: multipart/form-data;
boundary=--BOUNDARY--
Content-Length: message body length
--BOUNDARY--
Content-Disposition: form-data; name=”template_1”
Content_type: application/octet-stream
{biometric template byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”templates_n”; filename=”1.template”
Content_type: application/octet-stream
{biometric template byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”templates_n”; filename=”2.template”
Content_type: application/octet-stream
{biometric template byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”templates_n”; filename=”3.template”
Content_type: application/octet-stream
{biometric template byte stream}
--BOUNDARY--Parameter name
Type
Description
results
List[JSON]
A list of N comparison results. The Nth result contains the comparison result for the main and Nth templates. The result has the fields as follows:
200 OK
Content-Type: application/json
{'results': [
{'filename': '1.template', 'score': 0.0, 'decision': 'declined'},
{'filename': '2.template', 'score': 1.0, 'decision': 'approved'},
{'filename': '3.template', 'score': 0.21, 'decision': 'declined'}
]}Parameter name
Type
Description
sample_1
Stream
This parameter is mandatory. The main image.
POST localhost/v1/face/pattern/verify_n
Content-Type: multipart/form-data;
boundary=--BOUNDARY--
Content-Length: message body length
--BOUNDARY--
Content-Disposition: form-data; name=”sample_1”
Content_type: image/jpeg
{image byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”templates_n”; filename=”1.template”
Content_type: application/octet-stream
{biometric template byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”templates_n”; filename=”2.template”
Content_type: application/octet-stream
{biometric template byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”templates_n”; filename=”3.template”
Content_type: application/octet-stream
{biometric template byte stream}
--BOUNDARY--Parameter name
Type
Description
results
List[JSON]
A list of N comparison results. The Nth result contains the comparison result for the template derived from the main image and the Nth template. The result has the fields as follows:
200 OK
Content-Type: application/json
{'results': [
{'filename': '1.template', 'score': 0.0, 'decision': 'declined'},
{'filename': '2.template', 'score': 1.0, 'decision': 'approved'},
{'filename': '3.template', 'score': 0.21, 'decision': 'declined'}
]}Parameter name
Type
Description
sample_1
Stream
This parameter is mandatory. The first (main) image.
POST localhost/v1/face/pattern/extract_and_compare_n
Content-Type: multipart/form-data;
boundary=--BOUNDARY--
Content-Length: message body length
--BOUNDARY--
Content-Disposition: form-data; name=”sample_1”
Content_type: image/jpeg
{image byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”samples_n”; filename=”1.jpeg”
Content_type: image/jpeg
{image byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”samples_n”; filename=”2.jpeg”
Content_type: image/jpeg
{image byte stream}
--BOUNDARY--
Content-Disposition: form-data; name=”samples_n”; filename=”3.jpeg”
Content_type: image/jpeg
{image byte stream}
--BOUNDARY--Parameter name
Type
Description
results
List[JSON]
A list of N comparison results. The Nth result contains the comparison result for the main and Nth images. The result has the fields as follows:
200 OK
Content-Type: application/json
{'results': [
{'filename': '1.jpeg', 'score': 0.0, 'decision': 'declined'},
{'filename': '2.jpeg', 'score': 1.0, 'decision': 'approved'},
{'filename': '3.jpeg', 'score': 0.21, 'decision': 'declined'}
]}HTTP response codes
The value of the “code” parameter
Description
400
BPE-002001
Invalid Content-Type of HTTP request
Parameter name
Type
Description
status
Int
0 – the liveness processor is working correctly.
3 – the liveness processor is inoperative.
200 OK
Content-Type: application/json
{“status”: 0, message: “”}HTTP response codes
The value of the “code” parameter
Description
400
LDE-002001
Invalid Content-Type of HTTP request
models
[String]
An array of model versions, each record contains model name and model version number.
message
String
Message.
bio_template
Stream
Required parameter.
Second biometric template.
decision
String
Recommended solution based on the score.
approved – positive. The faces match.
operator_required – additional operator verification is required.
declined – negative result. The faces don't match.
bio_template
Stream
Required parameter.
The biometric template to compare with.
bio_feature
Stream
Biometric template derived from image
sample_2
Stream
Required parameter.
Second image
decision
String
Recommended solution based on the score.
approved – positive. The faces are match.
operator_required – additional operator verification is required.
declined – negative result. The faces don't match.
templates_n
Stream
A list of N biometric templates. Each of them should be passed separately but the parameter name should be templates_n. You also need to pass the filename in the header.
*filename
String
A filename for the Nth template.
*score
Float
The result of comparing the main and Nth templates.
*decision
String
Recommended solution based on the score.
approved – positive. The faces are match.
operator_required – additional operator verification is required.
declined – negative result. The faces don't match.
templates_n
Stream
A list of N biometric templates. Each of them should be passed separately but the parameter name should be templates_n. You also need to pass the filename in the header.
*filename
String
A filename for the Nth template.
*score
Float
The result of comparing the template derived from the main image and the Nth template.
*decision
String
Recommended solution based on the score.
approved – positive. The faces are match.
operator_required – additional operator verification is required.
declined – negative result. The faces don't match.
samples_n
Stream
A list of N images. Each of them should be passed separately but the parameter name should be samples_n. You also need to pass the filename in the header.
*filename
String
A filename for the Nth image.
*score
Float
The result of comparing the main and Nth images.
*decision
String
Recommended solution based on the score.
approved – positive. The faces are match.
operator_required – additional operator verification is required.
declined – negative result. The faces don't match.
400
BPE-002002
Invalid HTTP request method
400
BPE-002003
Failed to read the biometric sample*
400
BPE-002004
Failed to read the biometric template
400
BPE-002005
Invalid Content-Type of the multiparted HTTP request part
400
BPE-003001
Failed to retrieve the biometric template
400
BPE-003002
The biometric sample* is missing face
400
BPE-003003
More than one person is present on the biometric sample*
500
BPE-001001
Internal bioprocessor error
400
BPE-001002
TFSS error. Call the biometry health method.
message
String
Message.
400
LDE-002002
Invalid HTTP request method
400
LDE-002004
Failed to extract the biometric sample*
400
LDE-002005
Invalid Content-Type of the multiparted HTTP request part
500
LDE-001001
Liveness detection processor internal error
400
LDE-001002
TFSS error. Call the Liveness health method.

POST /v1/face/liveness/detect HTTP/1.1
Host: localhost
Content-Type: image/jpeg
Content-Length: [the size of the message body]
[Image byte stream]HTTP/1.1 200 OK
Content-Type: application/json
{
"passed": false,
"score": 0.999484062
}POST /v1/face/liveness/detect HTTP/1.1
Host: localhost
Content-Length: [the size of the message body]
Content-Type: multipart/form-data; boundary=--BOUNDARY--
--BOUNDARY--
Content-Disposition: form-data; name="media_key1"; filename="video.mp4"
Content-Type: multipart/form-data;
[media file byte stream]
--BOUNDARY--
Content-Disposition: form-data; name="payload"
{
"folder:meta_data": {
"partner_side_folder_id": "partner_side_folder_id_if_needed",
"person_info": {
"first_name": "John",
"middle_name": "Jameson",
"last_name": "Doe"
}
},
"resolution_endpoint": "https://www.your-custom-endpoint.com",
"media:meta_data": {
"media_key1": {
"foo": "bar2"
}
},
"media:tags": {
"media_key1": [
"video_selfie",
"video_selfie_blank"
]
},
"analyses": [
{
"type": "quality",
"meta_data": {
"example1": "some_example1"
},
"params": {
"threshold_spoofing": 0.6,
"extract_best_shot": false
}
}
]
}
--BOUNDARY--{
"company_id": null,
"time_created": 1720180784.769608,
"folder_id": "folder_id", // temporary ID
"user_id": null,
"resolution_endpoint": "https://www.your-custom-endpoint.com",
"resolution_status": "FINISHED",
"resolution_comment": "[]",
"system_resolution": "SUCCESS",
"resolution_time": null,
"resolution_author_id": null,
"resolution_state_hash": null,
"operator_comment": null,
"operator_status": null,
"is_cleared": null,
"meta_data": {
"partner_side_folder_id": "partner_side_folder_id_if_needed",
"person_info": {
"first_name": "John",
"middle_name": "Jameson",
"last_name": "Doe"
}
},
"technical_meta_data": {},
"time_updated": 1720180787.531983,
"media": [
{
"folder_id": "folder_id", // temporary ID
"media_id": "video_id", // temporary ID
"media_type": "VIDEO_FOLDER",
"info": {
"thumb": null,
"video": {
"duration": 3.76,
"FPS": 22.83,
"width": 960,
"height": 720,
"md5": "8879b4fa9ee7add77aceb8d7d5d7b92d",
"size": 6017119,
"mime-type": "video/mp4"
}
},
"tags": [
"video_selfie",
"video_selfie_blank",
"orientation_portrait"
],
"original_name": "video-5mb.mp4",
"original_url": null,
"company_id": null,
"technical_meta_data": {},
"time_created": 1719573752.78253,
"time_updated": 1720180787.531801,
"meta_data": {
"foo4": "bar5"
},
"thumb_url": null,
"folder_time_created": null,
"video_id": "video_id", // temporary ID
"video_url": null
}
],
"analyses": [
{
"analyse_id": null,
"analysis_id": null,
"folder_id": "folder_id", // temporary ID
"folder_time_created": null,
"type": "QUALITY",
"state": "FINISHED",
"company_id": null,
"group_id": null,
"results_data": null,
"confs": {
"threshold_replay": 0.5,
"extract_best_shot": false,
"threshold_liveness": 0.5,
"threshold_spoofing": 0.42
},
"error_message": null,
"error_code": null,
"resolution_operator": null,
"technical_meta_data": {},
"time_created": 1720180784.769944,
"time_updated": 1720180787.531877,
"meta_data": {
"some_key": "some_value"
},
"source_media": [
{
"folder_id": "folder_id", // temporary ID
"media_id": "video_id", // temporary ID
"media_type": "VIDEO_FOLDER",
"info": {
"thumb": null,
"video": {
"duration": 3.76,
"FPS": 22.83,
"width": 960,
"height": 720,
"md5": "8879b4fa9ee7add77aceb8d7d5d7b92d",
"size": 6017119,
"mime-type": "video/mp4"
}
},
"tags": [
"video_selfie",
"video_selfie_blank",
"orientation_portrait"
],
"original_name": "video-5mb.mp4",
"original_url": null,
"company_id": null,
"technical_meta_data": {},
"time_created": 1719573752.78253,
"time_updated": 1720180787.531801,
"meta_data": {
"foo4": "bar5"
},
"thumb_url": null,
"folder_time_created": null,
"video_id": "video_id", // temporary ID
"video_url": null
}
],
"results_media": [
{
"company_id": null,
"media_association_id": "video_id", // temporary ID
"analysis_id": null,
"results_data": {
"confidence_spoofing": 0.000541269779
},
"source_media_id": "video_id", // temporary ID
"output_images": [],
"collection_persons": [],
"folder_time_created": null
}
],
"resolution_status": "SUCCESS",
"resolution": "SUCCESS"
}
]
}POST /v1/face/liveness/detect HTTP/1.1
Host: localhost
Content-Length: [the size of the message body]
Content-Type: multipart/form-data; boundary=--BOUNDARY--
--BOUNDARY--
Content-Disposition: form-data; name="media_key1"; filename="video.mp4"
Content-Type: multipart/form-data;
[media file byte stream]
--BOUNDARY--
Content-Disposition: form-data; name="payload"
{
"folder:meta_data": {
"partner_side_folder_id": "partner_side_folder_id_if_needed",
"person_info": {
"first_name": "John",
"middle_name": "Jameson",
"last_name": "Doe"
}
},
"resolution_endpoint": "https://www.your-custom-endpoint.com",
"media:meta_data": {
"media_key1": {
"foo": "bar2"
}
},
"media:tags": {
"media_key1": [
"video_selfie",
"video_selfie_blank"
]
},
"analyses": [
{
"type": "quality",
"meta_data": {
"example1": "some_example1"
},
"params": {
"extract_best_shot": true
}
}
]
}
--BOUNDARY--{
"company_id": null,
"time_created": 1720177371.120899,
"folder_id": "folder_id", // temporary ID
"user_id": null,
"resolution_endpoint": "https://www.your-custom-endpoint.com",
"resolution_status": "FINISHED",
"resolution_comment": "[]",
"system_resolution": "SUCCESS",
"resolution_time": null,
"resolution_author_id": null,
"resolution_state_hash": null,
"operator_comment": null,
"operator_status": null,
"is_cleared": null,
"meta_data": {
"partner_side_folder_id": "partner_side_folder_id_if_needed",
"person_info": {
"first_name": "John",
"middle_name": "Jameson",
"last_name": "Doe"
}
},
"technical_meta_data": {},
"time_updated": 1720177375.531137,
"media": [
{
"folder_id": "folder_id", // temporary ID
"media_id": "media_id", // temporary ID
"media_type": "VIDEO_FOLDER",
"info": {
"thumb": null,
"video": {
"duration": 3.76,
"FPS": 22.83,
"width": 960,
"height": 720,
"md5": "8879b4fa9ee7add77aceb8d7d5d7b92d",
"size": 6017119,
"mime-type": "video/mp4"
}
},
"tags": [
"video_selfie",
"video_selfie_blank",
"orientation_portrait"
],
"original_name": "video-5mb.mp4",
"original_url": null,
"company_id": null,
"technical_meta_data": {},
"time_created": 1719573752.781861,
"time_updated": 1720177373.772401,
"meta_data": {
"foo4": "bar5"
},
"thumb_url": null,
"folder_time_created": null,
"video_id": "media_id", // temporary ID
"video_url": null
}
],
"analyses": [
{
"analyse_id": null,
"analysis_id": null,
"folder_id": "folder_id", // temporary ID
"folder_time_created": null,
"type": "QUALITY",
"state": "FINISHED",
"company_id": null,
"group_id": null,
"results_data": null,
"error_message": null,
"error_code": null,
"resolution_operator": null,
"technical_meta_data": {},
"time_created": 1720177371.121241,
"time_updated": 1720177375.531043,
"meta_data": {
"some_key": "some_value"
},
"source_media": [
{
"folder_id": "folder_id", // temporary ID
"media_id": "media_id", // temporary ID
"media_type": "VIDEO_FOLDER",
"info": {
"thumb": null,
"video": {
"duration": 3.76,
"FPS": 22.83,
"width": 960,
"height": 720,
"md5": "8879b4fa9ee7add77aceb8d7d5d7b92d",
"size": 6017119,
"mime-type": "video/mp4"
}
},
"tags": [
"video_selfie",
"video_selfie_blank",
"orientation_portrait"
],
"original_name": "video-5mb.mp4",
"original_url": null,
"company_id": null,
"technical_meta_data": {},
"time_created": 1719573752.781861,
"time_updated": 1720177373.772401,
"meta_data": {
"foo4": "bar5"
},
"thumb_url": null,
"folder_time_created": null,
"video_id": "media_id", // temporary ID
"video_url": null
}
],
"results_media": [
{
"company_id": null,
"media_association_id": "media_id", // temporary ID
"analysis_id": null,
"results_data": {
"confidence_spoofing": 0.000541269779
},
"source_media_id": "media_id", // temporary ID
"output_images": [
{
"folder_id": "folder_id", // temporary ID
"media_id": "media_id", // temporary ID
"media_type": "IMAGE_RESULT_ANALYSIS_SINGLE",
"info": {
"thumb": null,
"original": {
"md5": "e6effeceb94e79b8cb204c6652283b57",
"width": 720,
"height": 960,
"size": 145178,
"mime-type": "image/jpeg"
}
},
"tags": [],
"original_name": "<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=720x960 at 0x766811DF8E90>",
"original_url": null,
"company_id": null,
"technical_meta_data": {},
"time_created": 1719573752.781861,
"time_updated": 1719573752.781871,
"meta_data": null,
"folder_time_created": null,
"image_b64": "",
"media_association_id": "media_id" // temporary ID
}
],
"collection_persons": [],
"folder_time_created": null
}
],
"resolution_status": "SUCCESS",
"resolution": "SUCCESS"
}
]
}{
"folder:meta_data": {
"partner_side_folder_id": "partner_side_folder_id_if_needed",
"person_info": {
"first_name": "John",
"middle_name": "Jameson",
"last_name": "Doe"
} },
"resolution_endpoint": "https://www.your-custom-endpoint.com",
"media:meta_data": {
"media_key1": {
"foo": "bar2",
"additional_info": "additional_info" // might affect the score
},
"media_key2": {
"foo2": "bar3"
},
"media_key3": {
"foo4": "bar5"
}
},
"media:tags": {
"media_key1": [
"video_selfie",
"video_selfie_blank",
"orientation_portrait"
],
"media_key2": [
"photo_selfie"
],
"media_key3": [
"video_selfie",
"video_selfie_blank",
"orientation_portrait"
]
},
"analyses": [
{
"type": "quality",
"meta_data": {
"some_key": "some_value"
},
"params": {
"extract_best_shot":true // analysis will return the best shot
}
}
]
}A singleton for Oz SDK.
Initializes OZSDK with the license data. The closure is either license data or LicenseError.
licenseSources
Returns
-
Forces the license installation.
Sets connection to Oz API.
Returns
The access token or an error.
Sets connection to the telemetry server.
Returns
The access token or an error.
Checks whether an access token exists.
Parameters
-
Returns
The result – the true or false value.
Deletes the saved access token
Parameters
-
Returns
-
Creates the Liveness check controller.
Returns
UIViewController or an exception.
Creates the Liveness check controller.
Returns
UIViewController or an exception.
Deletes all videos.
Parameters
-
Returns
-
Retrieves the telemetry session ID.
Parameters
-
Returns
The telemetry session ID (String parameter).
Sets the bundle to look for translations in.
Returns
-
Sets the name of the localization table to look for translations in.
Returns
-
Sets the length of the Selfie gesture (in milliseconds).
Generates the payload with media signatures.
Returns
Payload to be sent along with media files that were used for generation.
Sets the SDK environment.
SDK locale (if not set, works automatically).
The host to call for Liveness video analysis.
The holder for attempts counts before SDK returns error.
The SDK version.
A delegate for OZSDK.
Gets the Liveness check results.
Returns
-
The error processing method.
Returns
-
A protocol for performing checks.
Creates the AnalysisRequest instance.
Returns
The AnalysisRequest instance.
Adds an analysis to the AnalysisRequest instance.
Returns
-
Uploads media on server.
Returns
-
Adds the folder ID to upload media to a certain folder.
Returns
-
Adds metadata to a folder.
Returns
-
Runs the analyses.
Returns
The analysis result or an error.
Manages interaction with . Set to true to enable the non-persistent API mode (useInstantMode(true)).
Customization for OzLivenessSDK (use OZSDK.customization).
A set of customization parameters for the toolbar.
A set of customization parameters for the center hint that guides a user through the process of taking an image of themselves.
A set of customization parameters for the hint animation.
A set of customization parameters for the frame around the user face.
A set of customization parameters for the background outside the frame.
A set of customization parameters for the SDK version text.
A set of customization parameters for the alert message that warns user about their actions being recorded. This message is placed above the oval.
Logo customization parameters. Custom logo should be allowed by license. By default, logo is placed on the bottom left.
A source of a license.
The license data.
Contains action from the captured video.
On January 1, 2027, the One Shot gesture will become unavailable. Please plan your .
Contains the locale code according to .
Contains all the information on the media captured.
The type of media captured.
Error description.
Contains information on what media to analyze and what analyses to apply.
The type of the analysis.
The mode of the analysis.
Shows the media processing status.
Shows the files' uploading status.
Shows the analysis processing status.
Describes the analysis result for the single media.
Contains the consolidated analysis results for all media.
Contains the results of the checks performed.
The general status for all analyses applied to the folder created.
Contains the results for single analyses.
Frame shape settings.
Possible license errors.
The authorization type.
Defines the settings for the repeated media upload.
Defines what type of media is being sent to the server in case of the hybrid analysis once the on-device analysis is finished successfully. By default, the system uploads the compressed video.
Contains information about the .
Defines what environment to use.
The method affects security checks only; the SDK functionality does not change.
The methods below apply to the new feature – that has been implemented in 8.22.
This method replaces addAnalysis in the AnalysisRequest structure when you use the data container flow.
Input
Captures media file with all information you need and packages it into a data container.
Input
Output
Detects a request for video capture.
Contains information on media files and analyses that should be applied to them.
Stores information about a media file.
If during the capture process an error prevents a user from completing the workflow, the data container is deleted.
The source of the license
licenseSource
Source of the license
apiConnection
Authorization parameters
eventsConnection
Telemetry authorization parameters
delegate
The delegate for Oz Liveness
actions
actions
Captured action
FaceCaptureCompletion
type alias used as follows:
public typealias FaceCaptureCompletion = (_ results: [OZMedia]?, _ error: OZVerificationStatus?) -> Void
languageBundle
Bundle
The bundle that contains translations
localizableTableName
String
The name of the .strings table in Bundle.main containing UI translations. If specified, the SDK uses this table and falls back to its built-in strings for missing keys
selfieLength
Int
The length of the Selfie gesture (in milliseconds). Should be within 500-5000 ms, the default length is 700
media
An array of media files
folderMeta
[String]
environment
The SDK environment
localizationCode
The localization code
host
String
Host address
singleCount
Int
Attempts on a single action/gesture
commonCount
Int
version
String
Version number
results
[]
An array of the OzMedia objects.
status
The error description.
folderId (optional)
String
The identifier to define when you need to upload media to a certain folder.
analysis
A structure containing information on the analyses required.
media
Media or an array of media objects to be uploaded.
folderId
String
The folder identifier.
meta
[String]
An array of metadata as follows:
["meta1": "data1"]
statusHandler
A callback function as follows:
statusHandler: @escaping ((_ status: ) -> Void)
The handler that is executed when the scenario state changes
errorHandler
A callback function as follows:
errorHandler: @escaping ((_ error: Error) -> Void)
closeButtonIcon
UIImage
An image for the close button
closeButtonColor
UIColor
textFont
UIFont
Center hint text font
textColor
UIColor
hideAnimation
Bool
A switcher for hint animation, if True, the animation is hidden
animationIconSize
CGfloat
geometryType
The frame type: oval, rectangle, circle, or square
cornerRadius
CGFloat
backgroundColor
UIColor
Background color
textFont
UIFont
SDK version text font
textColor
UIColor
customizationEnableAntiscam
Bool
Adds the antiscam message
customizationAntiscamTextMessage
String
image
UIImage
Logo image
size
CGSize
licenseFilePath
An absolute path to a license (String)
licenseFileName
The name of the license file
appIDS
[String]
An array of bundle IDs
expires
TimeInterval
smile
Smile
eyes
Blink
scanning
en
English
hy
Armenian
kk
movement
User action type
mediaType
movement
A media with an action
documentBack
The back side of the document
documentFront
userNotProcessed
The Liveness check was not processed
failedBecauseUserCancelled
The check was interrupted by user
failedBecauseCameraPermissionDenied
media
[]
An array of the OzMedia objects
type
biometry
The algorithm that allows comparing several media and check if the people on them are the same person or not
quality
The algorithm that aims to check whether a person in a video is a real human acting in good faith, not a fake of any kind.
document
onDevice
The on-device analysis with no server needed. We recommend using server-based analyses whenever possible, as on-device ones tend to produce less accurate results
serverBased
The server-based analysis
hybrid
addToFolder
The system is creating a folder and adding files to this folder
addAnalyses
The system is adding analyses
waitAnalysisResult
media
The object that is being uploaded at the moment
index
Int
status
Processing analysis status
progressStatus
resolution
Consolidated analysis result
sourceId
String
resolution
Consolidated analysis result
folderId
String
resolution
Analysis resolution
type
INITIAL
No analyses have been applied yet
PROCESSING
The analyses are in progress
FAILED
analyseResolutionStatus
The analysis status
type
oval
Oval frame
rectangle(cornerRadius: CGFloat)
Rectangular frame (with corner radius)
circle
licenseFileNotFound
The license is not found
licenseParseError
Cannot parse the license file, the license might be invalid
licenseBundleError
fromServiceToken
Authorization with a token:
host: String
token: String
pins (optional): a list of
fromCredentials
Authorization with credentials:
host: String
login: String
password: String
pins (optional): a list of
attemptsCount
Int
Number of attempts for media upload
attemptsTimeout
Int
uploadOriginal
The original video
uploadCompressed
The compressed video
uploadBestShot
publicKeyHash
String
SHA256 key hash in base64
expirationDate
UNIX timestamp, UTC time
debug
Strictness of the SDK security checks is lowered so that the application can run with a debugger attached. Intended for development and debugging
production (default)
All security checks are enabled. Intended for release builds
DataContainer
Data
An encrypted file containing media and collateral info, the output of the method
request
Detects a request for video capture
session_token
String
DataContainer
Data
An encrypted file containing media and collateral info
analysisProfileList
List<>
A list of objects that contain information on media and analyses that should be applied to them
folderMeta (optional)
Map<String, Any>
mediaList
List<>
A list of media to be analyzed
type
id
String (UUID v4)
Media ID
actionMedia
session_token_is_empty
Session token must not be empty
Missing session token which is a mandatory parameter
data_container_internal_failure_1
Internal failure occurred while processing the data container
Captured action
cameraPosition (optional)
AVCaptureDevice.Position
front – front camera (default),
back – rear camera
The handler that is executed when the method completes. The closure is either an array of objects or an .
cameraPosition (optional)
AVCaptureDevice.Position
front – front camera (default),
back – rear camera
Additional folder metadata
Total number of attempts on all actions/gestures if you use a sequence of them
faceAlignmentTimeout
Float
Time needed to align face into frame
uploadMediaSettings
Sets the number of attempts and timeout between them
Error handler
completionHandler
A callback function as follows:
completionHandler: @escaping (_ results : ) -> Void)
The handler that is executed when the run method completes.
Close button tintColor
titleFont
UIFont
Toolbar title text font
titleColor
UIColor
Toolbar title text color
backgroundColor
UIColor
Toolbar background color
titleText
String
Text on the toolbar
Center hint text color
backgroundColor
UIColor
Center hint text background
verticalPosition
Int
Center hint vertical position from the screen top (in %, 0-100)
hideTextBackground
Bool
Hides text background
backgroundCornerRadius
Int
Center hint background frame corner radius
A side size of the animation icon square
hintGradientColor
UIColor
The close-to-frame gradient color
Rectangle corner radius (in dp)
strokeFaceNotAlignedColor
UIColor
Frame color when a face is not aligned properly
strokeFaceAlignedColor
UIColor
Frame color when a face is aligned properly
strokeWidth
CGFloat
Frame stroke width (in dp, 0-20)
strokePadding
CGFloat
A padding from the stroke to the face alignment area (in dp, 0-10)
SDK version text color
Antiscam message text
customizationAntiscamTextFont
UIFont
Antiscam message text font
customizationAntiscamTextColor
UIColor
Antiscam message text color
customizationAntiscamBackgroundColor
UIColor
Antiscam message text background color
customizationAntiscamCornerRadius
CGFloat
Background frame corner radius
customizationAntiscamFlashColor
UIColor
Color of the flashing indicator close to the antiscam message
Logo size (in dp)
verticalPosition
Int (0-100), default: 100
Vertical offset
horizontalPosition
Int (0-100), default: 0
Horizontal offset
The expiration interval
features
Features
License features
configs (optional)
ABTestingConfigs
Additional configuration
Scan
selfie
A selfie with face alignment check
one_shot
The best shot from the video taken
left
Head turned left
right
Head turned right
down
Head tilted downwards
up
Head lifted up
Kazakh
ky
Kyrgyz
tr
Turkish
es
Spanish
pt-BR
Portuguese (Brazilian)
custom(String)
Custom language (language ISO 639-1 code, two letters)
Type of media
metaData
[String] as follows:
["meta1": "data1"]
Metadata if any
videoURL
URL
URL of the Liveness video
bestShotURL
URL
URL of the best shot in PNG
preferredMediaURL
URL
URL of the API media container
timestamp
Date
Timestamp for the check completion
The front side of the document
The Liveness check can't be performed: no camera access
failedBecauseOfBackgroundMode
The Liveness check can't be performed: background mode
failedBecauseOfTimeout
The Liveness check can't be performed: timeout
failedBecauseOfAttemptLimit
The Liveness check can't be performed: attempts limit exceeded
failedBecausePreparingTimout
The Liveness check can't be performed: face alignment timeout
failedBecauseOfLowMemory
The Liveness check can't be performed: no memory left
The type of the analysis
mode
The mode of the analysis
sizeReductionStrategy
Defines what type of media is being sent to the server in case of the hybrid analysis once the on-device analysis is finished successfully. On January 1, 2027, on-device and hybrid analysis modes will become unavailable. Use server-based analysis instead.
params (optional)
String
Additional parameters
The analysis that aims to recognize the document and check if its fields are correct according to its type. Starting July 1, 2027, the Documents analysis will no longer be available.
blacklist
The analysis that compares a face on a captured media with faces from the pre-made media database.
The hybrid analysis for Liveness: if the score received from an on-device analysis is too high, the system initiates a server-based analysis as an additional check.
The system is waiting for the result
Number of this object in a list
from
Int
Objects quantity
progress
Progress
Object uploading status
Media uploading status
Media identifier
isOnDevice
Bool
Analysis mode. On January 1, 2027, on-device and hybrid analysis modes will become unavailable. Use server-based analysis instead.
confidenceScore
Float
Resulting score
mediaType
String
Media file type: VIDEO / IMAGE / SHOT_SET
media
Media that is being analyzed
error
AnalysisError (inherits from Error)
Error
Folder identifier
analysisResults
[]
A list of analysis results
Analysis type
mode
Analysis mode
analysisId
String
Analysis identifier
error
AnalysisError (inherits from Error)
Error
resultMedia
[]
Results of the analysis for single media files
confidenceScore
Float
The resulting score
serverRawResponse
String
Server response
One or more analyses failed due to some error and couldn't get finished
FINISHED
The analyses are finished
DECLINED
The check failed (e.g., faces don't match or some spoofing attack detected)
SUCCESS
Everything went fine, the check succeeded (e.g., faces match or liveness confirmed)
OPERATOR_REQUIRED
The result should be additionally checked by a human operator
The analysis type
folderID
String
The folder identifier
score
Float
The result of the check performed
Circular frame
square(cornerRadius: CGFloat)
Square frame (with corner radius)
The bundle_id in the license file doesn't match with bundle_id used
licenseExpired
The license is expired
Timeout between attempts
The best shot taken from the video
uploadNothing
Nothing is sent (note that no folder will be created)
The date of certificate expiration
Token required for OzCapsula flow
Additional folder metadata
additionalMediaList (optional)
List<>
Media files that you need to upload to server, but it’s not necessary for analyses
cameraPosition (optional)
String
front (default) – front camera
back – rear camera
Analysis type
params (optional)
Map<String, Any>
Additional analysis parameters
An action that user should perform in a video
userMedia
An external media file, e.g., a reference or a document photo
Not enough memory
data_container_internal_failure_2
data_container_internal_failure_3
data_container_internal_failure_4
Internal failure occurred while processing the data container
Couldn't generate a container
data_container_internal_failure_1000
Internal failure occurred while processing the data container
Any other error not mentioned above
A singleton for Oz SDK.
Deletes all action videos from file system.
Parameters
-
Returns
-
Creates an intent to start the Liveness activity.
Returns
-
Utility function to get the SDK error from OnActivityResult's intent.
Returns
The – String.
Retrieves the SDK license payload.
Parameters
-
Returns
The license payload () – the object that contains the extended info about licensing conditions.
Utility function to get SDK results from OnActivityResult's intent.
Returns
A list of OzAbstractMedia objects.
Initializes SDK with license sources.
Returns
-
Enables logging using the Oz Liveness SDK logging mechanism.
Returns
-
Sets connection to Oz API.
Sets connection to the telemetry server.
Deletes the saved token.
Parameters
-
Returns
-
Retrieves the telemetry session ID.
Parameters
-
Returns
The telemetry session ID (String).
Retrieves the SDK version.
Parameters
-
Returns
The SDK version (String).
Generates the payload with media signatures.
Returns
Payload to be sent along with media files that were used for generation.
Sets the SDK environment for debugging or production.
A class for performing checks.
The analysis launching method.
A builder class for AnalysisRequest.
Creates the AnalysisRequest instance.
Parameters
-
Returns
The class instance.
Adds an analysis to your request.
Returns
Error if any.
Adds a list of analyses to your request. Allows executing several analyses for the same folder on the server side.
Returns
Error if any.
Adds metadata to a folder you create (for the server-based analyses only). You can add a pair key-value as additional information to the folder with the analysis result on the server side.
Returns
Error if any.
Uploads one or more media to a folder.
Returns
Error if any.
For the previously created folder, sets a folderId. The folder should exist on the server side. Otherwise, a new folder will be created.
Returns
Error if any.
Manages interaction with . Set to true to enable the non-persistent API mode (useInstantMode(true)).
Configuration for OzLivenessSDK (use OzLivenessSDK.config).
Sets the length of the Selfie gesture (in milliseconds).
Returns
Error if any.
The possibility to enable additional debug info by clicking on version text.
The number of attempts before SDK returns error.
Settings for repeated media upload.
Timeout for face alignment (measured in milliseconds).
Interface implementation to retrieve error by Liveness detection.
Locale to display string resources.
Logging settings.
Uses the main (rear) camera instead of the front camera for liveness detection.
Disables the option that prevents videos to be too short (3 frames or less).
Turns on the flashlight during capture with the rear camera. Experimental option.
Customization for OzLivenessSDK (use OzLivenessSDK.config.customization).
Hides the status bar and the three buttons at the bottom. The default value is True.
A set of customization parameters for the toolbar.
A set of customization parameters for the center hint that guides a user through the process of taking an image of themselves.
A set of customization parameters for the hint animation.
A set of customization parameters for the frame around the user face.
A set of customization parameters for the background outside the frame.
A set of customization parameters for the SDK version text.
A set of customization parameters for the alert message that warns user about their actions being recorded. This message is placed above the oval.
Logo customization parameters. Custom logo should be allowed by license. By default, logo is placed on the bottom left.
Contains the action from the captured video.
On January 1, 2027, the One Shot gesture will become unavailable. Please plan your .
Contains the extended info about licensing conditions.
A class for the captured media that can be:
A document photo.
A set of shots in an archive.
A Liveness video.
Contains an action from the captured video.
On January 1, 2027, the One Shot gesture will become unavailable. Please plan your .
A class for license that can be:
Contains the license ID.
Contains the path to a license.
A class for analysis status that can be:
This status means the analysis is launched.
This status means the media is being uploaded.
The type of the analysis.
The mode of the analysis.
Contains information on what media to analyze and what analyses to apply.
The general status for all analyses applied to the folder created.
Holder for attempts counts before SDK returns error.
Contains the locale code according to .
Contains logging settings.
A class for color that can be (depending on the value received):
Frame shape settings.
Exception class for AnalysisRequest.
Structure that describes media used in AnalysisRequest.
Structure that describes the analysis result for the single media.
Consolidated result for all analyses performed.
Result of the analysis for all media it was applied to.
Defines the authentication method.
Authentication via token.
Authentication via credentials.
Defines the settings for the repeated media upload.
Defines what type of media is being sent to the server in case of the hybrid analysis once the on-device analysis is finished successfully. By default, the system uploads the compressed video.
Contains information about the .
Defines what environment to use.
The method affects security checks only; the SDK functionality does not change.
The methods below apply to the new feature – that has been implemented in 8.22.
This method replaces addAnalysis in the AnalysisRequest structure when you use the data container flow.
Input
Captures media file with all information you need and packages it into a data container.
Input
Output
Detects a request for video capture.
Contains information on media files and analyses that should be applied to them.
Stores information about a media file.
If during the capture process an error prevents a user from completing the workflow, the data container is deleted.
statusListener
StatusListener
Optional listener to check the license load result
onSuccess
A callback function as follows:
onSuccess(result: ) {
handleResults() }
The function is executed when all the analyses are completed
titleFont
Int (@FontRes)
Toolbar title text font
titleFontStyle
Int (values from android.graphics.Typeface properties, e.g., Typeface.BOLD)
Toolbar title text font style
titleSize
Int
Toolbar title text size (in sp, 12-18)
titleAlpha
Int
Toolbar title text opacity (in %, 0-100)
titleColor
Color
Toolbar title text color
backgroundColor
Color
Toolbar background color
backgroundAlpha
Int
Toolbar background opacity (in %, 0-100)
isTitleCentered
Boolean
Defines whether the text on the toolbar is centered or not
titleText
String
Text on the toolbar
textSize
Int
Center hint text size (in sp, 12-34)
textColor
Center hint text color
textAlpha
Int
Center hint text opacity (in %, 0-100)
verticalPosition
Int
Center hint vertical position from the screen bottom (in %, 0-100)
backgroundColor
Color
Center hint background color
backgroundOpacity
Int
Center hint background opacity
backgroundCornerRadius
Int
Center hint background frame corner radius (in dp, 0-20)
animationIconSize
Int
A side size of the animation icon square
hideAnimation
Boolean
A switcher for hint animation, if True, the animation is hidden
strokeFaceAlignedColor
Frame color when a face is aligned properly
strokeAlpha
Int
Frame opacity (in %, 0-100)
strokeWidth
Int
Frame stroke width (in dp, 0-20)
strokePadding
Int
A padding from the stroke to the face alignment area (in dp, 0-10)
verticalPosition
Int
Frame vertical position from the screen top (in %, 0-100)
textColor
SDK version text color
textAlpha
Int
SDK version text opacity (in %, 20-100)
textStyle
Int (@StyleRes)
SDK version text style: a style resource. Can be set only through the constructor
textSize
Int
Antiscam message text size (in px, 12-18)
textColor
Antiscam message text color
textAlpha
Int
Antiscam message text opacity (in %, 0-100)
textStyle
Int (@StyleRes)
Antiscam message text style: a style resource
backgroundColor
Antiscam message background color
backgroundOpacity
Int
Antiscam message background opacity
cornerRadius
Int
Background frame corner radius (in px, 0-20)
flashColor
Color of the flashing indicator close to the antiscam message
verticalPosition
Int (0-100), default: 100
Vertical offset
horizontalPosition
Int (0-100), default: 0
Horizontal offset
HeadRight
Head turned right
HeadLeft
Head turned left
HeadDown
Head tilted downwards
HeadUp
Head lifted up
EyeBlink
Blink
Smile
Smile
appIDS
List<String>
An array of bundle IDs
additionalTags (optional)
String
Additional tags if needed (including those not from the OzMediaTag enum)
metaData
Map<String, String>
Media metadata
additionalTags (optional)
String
Additional tags if needed (including those not from the OzMediaTag enum)
metaData
Map<String, String>
Media metadata
bestShotPath (optional)
String
URL of the best shot in PNG
preferredMediaPath (optional)
String
URL of the API media container
additionalTags (optional)
String
Additional tags if needed (including those not from the OzMediaTag enum)
metaData
Map<String, String>
Media metadata
VideoSelfieScan
A video with the scanning gesture
VideoSelfieEyes
A video with the blink gesture
VideoSelfieSmile
A video with the smile gesture
VideoSelfieHigh
A video with the lifting head up gesture
VideoSelfieDown
A video with the tilting head downwards gesture
VideoSelfieRight
A video with the turning head right gesture
VideoSelfieLeft
A video with the turning head left gesture
PhotoIdPortrait
A photo from a document
PhotoIdBack
A photo of the back side of the document
PhotoIdFront
A photo of the front side of the document
from
Int
Objects quantity
percentage
Int
Completion percentage
mediaList
[]
An array of the OzAbstractMedia objects
params (optional)
Map<String, Any>
Additional parameters
sizeReductionStrategy
Defines what type of media is being sent to the server in case of the hybrid analysis once the on-device analysis is finished successfully. On January 1, 2027, on-device and hybrid analysis modes will become unavailable. Use server-based analysis instead.
OPERATOR_REQUIRED
The result should be additionally checked by a human operator
KY
Kyrgyz
TR
Turkish
ES
Spanish
PT-BR
Portuguese (Brazilian)
journalObserver
StatusListener
An event listener to receive journal events on the application side
Square
Square frame
Type of the media
originalName
String
Original media name
ozMedia
Media object
tags
List<String>
Tags for media
resolution
Consolidated analysis result
sourceMedia
Source media
type
Type of the analysis
resolution
Consolidated analysis result
mode
Resulting score
resultMedia
List<>
A list of results of the analyses for single media
confidenceScore
Float
Resulting score
analysisId
String
Analysis identifier
params
@RawValue Map<String, Any>
Additional folder parameters
error
Error if any
serverRawResponse
String
Response from backend
sslPins (optional)
List<>
Whitelisted certificates
password
String
Password
sslPins (optional)
List<>
Whitelisted certificates
UPLOAD_NOTHING
Nothing is sent (note that no folder will be created)
additionalMediaList (optional)
List<>
Media files that you need to upload to server, but it’s not necessary for analyses
cameraPosition (optional)
String
front (default) – front camera
back – rear camera
params (optional)
Map<String, Any>
Additional analysis parameters
userMedia
An external media file, e.g., a reference or a document photo.
VIDEO_RECORD_ERROR = 5
Error by video record.
An error happened during video recording
NO_ACTIONS_ERROR = 6
Error. OzLivenessSDK started without actions.
No found in a video
FORCE_CLOSED = 7
Error. Liveness activity is force closed from client application.
A user closed the Liveness screen during video recording
DEVICE_HAS_NO_FRONT_CAMERA = 8
Error. Device has not front camera.
No front camera found
DEVICE_HAS_NO_MAIN_CAMERA = 9
Error. Device has not main camera.
No rear camera found
DEVICE_CAMERA_CONFIGURATION_NOT_SUPPORTED = 10
Error. Device camera configuration is not supported.
Oz Liveness doesn't support the camera configuration of the device
FACE_ALIGNMENT_TIMEOUT = 12
Error. Face alignment timeout in milliseconds
Time limit for the is exceeded
ERROR = 13
The check was interrupted by user
User has closed the screen during the Liveness check.
data_container_internal_failure_2
data_container_internal_failure_3
data_container_internal_failure_4
Internal failure occurred while processing the data container
Couldn't generate a container
data_container_internal_failure_1000
Internal failure occurred while processing the data container
Any other error not mentioned above
actions
A list of possible actions
data
Intent
The object to test
data
Intent
The object to test
context
Context
The Context class
licenseSources
tag
String
Message tag
log
String
connection
Connection type
statusListener
StatusListener<String?>
connection
Connection type
statusListener
StatusListener<String?>
media
An array of media files
folderMeta (optional)
[string:any]
environment
The SDK environment
onStatusChange
A callback function as follows:
onStatusChange(status: AnalysisRequest.AnalysisStatus) { handleStatus() }
The function is executed when the status of the AnalysisRequest changes
onError
A callback function as follows:
onError(error: OzException) { handleError() }
analysis
A structure for analysis
analysis
[Analysis]
A list of Analysis structures
key
String
Key for metadata
value
String
mediaList
An OzAbstractMedia object or a list of objects
folderID
String
A folder identifier
selfieLength
Int
The length of the Selfie gesture (in milliseconds). Should be within 500-5000 ms, the default length is 700
allowDebugVisualization
Boolean
Enables or disables the debug info
attemptsSettings
Sets the number of attempts
uploadMediaSettings
Sets the number of attempts and timeout between them
faceAlignmentTimeout
Long
A timeout value
livenessErrorCallback
ErrorHandler
A callback value
localizationCode
A locale code
logging
Logging settings
useMainCamera
Boolean
True – rear camera,
False – front camera
disableFramesCountValidation
Boolean
True – validation is off,
False – validation is on
mainCameraFlashModeEnabled
Boolean
True – flashlight is on,
False (default) – flashlight is off
closeButtonIcon
Int (@DrawableRes)
An image for the close button
closeButtonColor
textFont
Int (@FontRes)
Center hint text font
textStyle
Int (@StyleRes)
hintGradientColor
Gradient color
hintGradientOpacity
Int
geometryType
The frame type: oval, rectangle, circle, square. For a rectangle, the corner radius is set in the type itself: GeometryType.Rectangle(10)
strokeFaceNotAlignedColor
backgroundColor
Background color
backgroundAlpha
Int
textFont
Int (@FontRes)
SDK version text font
textSize
Int
textMessage
String
Antiscam message text
textFont
Int (@FontRes)
image
Bitmap (@DrawableRes)
Logo image
size
Size
OneShot
The best shot from the video taken
Blank
A selfie with face alignment check
Scan
expires
Float
The expiration interval
features
Features
tag
A tag for a document photo
photoPath
String
tag
A tag for a shot set
archivePath
String
tag
A tag for a video
videoPath
String
Blank
A video with no gesture
PhotoSelfie
A selfie photo
VideoSelfieOneShot
id
Int
License ID
path
String
An absolute path to a license
analysis
Contains information on what media to analyze and what analyses to apply
media
The object that is being uploaded at the moment
index
Int
BIOMETRY
The algorithm that allows comparing several media and check if the people on them are the same person or not
QUALITY
The algorithm that aims to check whether a person in a video is a real human acting in good faith, not a fake of any kind.
DOCUMENTS
ON_DEVICE
The on-device analysis with no server needed
SERVER_BASED
The server-based analysis
HYBRID
type
Type
The type of the analysis
mode
Mode
FAILED
One or more analyses failed due to some error and couldn't get finished
DECLINED
The check failed (e.g., faces don't match or some spoofing attack detected)
SUCCESS
singleCount
Int
Attempts on a single action/gesture
commonCount
Int
EN
English
HY
Armenian
KK
allowDefaultLogging
Boolean
Allows logging to LogCat
allowFileLogging
Boolean
colorRes
Int
Link to the color in the Android resource system
colorHex
String
Color hex (e.g., #FFFFFF)
colorInt
Int
The Int value of a color in Android
Oval
Oval frame
Rectangle
Rectangular frame. Takes the corner radius: GeometryType.Rectangle(10)
Circle
apiErrorCode
Int
Error code
message
String
mediaId
String
Media identifier
mediaType
confidenceScore
Float
Resulting score
isOnDevice
Boolean
analysisResults
List<AnalysisResult>
Analysis result
folderId
String
resolution
Consolidated analysis result
type
host
String
API address
token
String
host
String
API address
username
String
attemptsCount
Int
Number of attempts for media upload
attemptsTimeout
Int
UPLOAD_ORIGINAL
The original video
UPLOAD_COMPRESSED
The compressed video
UPLOAD_BEST_SHOT
hash
String
SHA256 key hash in base64
expiredAt
UNIX timestamp, UTC time
DEBUG
Strictness of the SDK security checks is lowered so that the application can run with a debugger attached. Intended for development and debugging
PRODUCTION (default)
All security checks are enabled. Intended for release builds
DataContainer
bytearray[]
An encrypted file containing media and collateral info, the output of the createMediaCaptureScreen method
request
Detects a request for video capture
session_token
String
DataContainer
bytearray[]
An encrypted file containing media and collateral info
analysisProfileList
List<AnalysisProfile>
A list of objects that contain information on media and analyses that should be applied to them
folderMeta (optional)
Map<String, Any>
mediaList
List<MediaRequest>
A list of media to be analyzed
type
String (Type)
id
String (UUID v4)
Media ID
actionMedia
ERROR = 3
Error.
An unknown error has happened
ATTEMPTS_EXHAUSTED_ERROR = 4
Error. Attempts exhausted for liveness action.
session_token_is_empty
Session token must not be empty
Missing session token which is a mandatory parameter
data_container_internal_failure_1
Internal failure occurred while processing the data container
A list of license references
Message log
Listener
Listener
Additional folder metadata
The function is executed in case of errors
Value for metadata
Close button color
Center hint text style
Gradient opacity
Frame color when a face is not aligned properly
Background opacity (in %, 0-100)
SDK version text size (in sp, 12-16)
Antiscam message text font
Logo size (in dp)
Scan
License features
An absolute path to a photo
A path to an archive
A path to a video
A video with the best shot taken
Number of this object in a list
The analysis that aims to recognize the document and check if its fields are correct according to its type. Starting July 1, 2027, the Documents analysis will no longer be available.
The hybrid analysis for Liveness: if the score received from an on-device analysis is too high, the system initiates a server-based analysis as an additional check.
The mode of the analysis
Everything went fine, the check succeeded (e.g., faces match or liveness confirmed)
Total number of attempts on all actions/gestures if you use a sequence of them
Kazakh
Allows logging to an internal file
Circular frame
Error message
String
Mode of the analysis. On January 1, 2027, on-device and hybrid analysis modes will become unavailable. Use server-based analysis instead.
Folder identifier
Type of the analysis
Access token
User name
Timeout between attempts
The best shot taken from the video
The date of certificate expiration
Token required for OzCapsula flow
Additional folder metadata
Analysis type
An action that user should perform in a video
The number of action is exceeded
Not enough memory
API changes
In Full API, repeating a Quality analysis on OzCapsula media now returns the earlier result instead of running the analysis again. A repeat after a failed analysis returns error_code 14. Additionally, Oz API removes redundant media data from the database, which saves database space.
Video previews are no longer stored as separate copies. For new videos, preview_url and video_url now return the original video URL, with no _preview suffix. If your code adds _preview to build preview links, or expects preview_url to differ from original_url, it needs to change. Videos uploaded before the upgrade keep their old preview links.
Added the claims mode for external identity provider integration. In this mode, Oz API takes user roles and attributes from the token it receives from the provider.
The One Shot gesture is deprecated and will be removed in 7.0.0. Use video_selfie_blank instead.
The Celery mode is now marked as deprecated. Switch to OZ_ANALYSIS_BACKEND_TYPE=LOCAL.
A rejected OzCapsula container now keeps its metadata and media tags in the saved folder.
Media captured on iPad is now recognized as iOS and goes through the same checks.
System roles can now address report templates by name. A PATCH without name no longer clears the template name.
Refined internal processes.
Enhanced security.
Webhook result delivery via the resolution_endpoint folder field is DEPRECATED and will be removed in 7.0.0.
Resolved the slowdown on GET /api/folders/ when resolution_status, analyse.type and analyse.resolution_status are combined with the with_analyses=true
Added GET api/folders/{folder_id}/artifacts to download all folder artifacts as a .zip with filename pattern: artifacts_<folder_id>_<company_id>_<request_date>.zip.
resolution_endpoint must now use HTTPS and resolve to a publicly routable address.
Confidence values can now be returned as
Updated models.
GET /api/healthcheck/ now contains the license/billing status.
Nginx can now check the validity of X-Forensic-Access-Token for static file requests.
Bug fix.
Implemented transaction tracking to support billing for on-premises clients for the full API mode. This functionality requires setting additional permissions: see .
Implemented transaction tracking to support billing for on-premises clients (Instant API). This functionality requires setting additional permissions: see .
Optimized performance of GET /api/folders/, GET /api/folders/{folder_id}/media/, and GET /api/folders/{folder_id}/analyses/ endpoints.
Extended log collection for OLAP.
API now can process an OzCapsula container that has other OzCapsula containers inside. This applies to the Mobile SDK integration flow only.
We now support OpenTelemetry.
You can now obtain the full-size action shot from API for the Liveness analysis. In the payload, set extract_action_shot to 1 or true. In an API response, check analyses[].results_media[].output_images[]
Updated internal dependencies.
Updated models.
API no longer returns a 500 error when viewing analysis details or printing reports under the CLIENT role in Web UI.
Added integration with OLAP.
Improved performance under high load.
Increased the total attachment size (OZ_ATTACHMENT_MAX_SIZE) from 10 MB to 24 MB.
Resolved the issue with improper processing of POST /api/folders/{{folder_id}}/media/request
You can now add a container to an existing folder using the POST api/folders/{folder_id}/media method.
Improved performance of the Collection analysis.
You can now trim a video if it is too long. Set the OZ_FFMPEG_VIDEO_CROPPING_ENABLED parameter to true to enable automatic trimming of videos longer than OZ_VIDEO_DURATION_MAX
Instant API now can save static and JSON payload to S3. To enable this functionality, set oz_instant_save_artifacts_s3 to true.
Resolved the issue with occasional false rejections using videos received from Web SDK.
The Collection analysis now ignores images tagged with photo_id_back.
Updated API to support upcoming features.
Fixed bugs that could cause the GET /api/folders/ request to return incorrect results.
Updated API to support upcoming features.
Fixed bugs.
Resolved an issue with POST /api/instant/folders/ and POST /api/folders/ returning “500 Internal Server Error” when the video sent is corrupted. Now system returns “400 Bad Request”.
Updated API to support upcoming features.
You can remove admin rights from a CLIENT ADMIN user and change their role to CLIENT via PATCH /api/users/{{user_id}}.
You can generate a service token for a user with the OPERATOR role.
Enhanced security.
Optimization and performance updates.
Analyses can now be done in parallel with each other. To enable this feature, add the OZ_ANALYSE_PARALLELED_CHECK_MEDIA_ENABLED parameter to config.py and set it to true (the default value is false).
For the instant mode, authorization can be disabled. Add the OZ_AUTHORIZE_DISABLED_STATELESS parameter to config.py and set it to true
Please note: this version doesn't support the Kazakhstan regulatory requirements.
Optimized storage and database.
Implemented the which involves creating a folder and executing analyses in a single request by attaching a part of the analysis in the payload.
Implemented the without storing any data locally or in a database. This mode can be used either with or without other API components.
You can now combine working systems based on asynchronous method or celery worker (local processing, celery processing). Added S3 storage mechanics for each of the combinations.
Improved the resource efficiency of server-based biometry analysis.
API can now extract action shots from videos of a person performing gestures. This is done to comply with the new Kazakhstan regulatory requirements for biometric identification.
Created a new report template that also complies with the requirements mentioned above.
If action shots are enabled, the thumbnails for the report are generated from them.
Updated the Postman collection. Please see the new collection here and at .
Added the new method to check the timezone settings: GET {{host}}/api/config
Added parameters to the GET {{host}}/api/event_sessions method:
Security updates.
Face Identification 1:N is now live, significantly increasing the data processing capacity of the Oz API to find matches. Even huge face databases (containing millions of photos and more) are no longer an issue.
The Liveness (QUALITY) analysis now ignores photos tagged with photo_id, photo_id_front, or photo_id_back, preventing these photos from causing the tag-related analysis error.
Security updates.
You can now apply the Liveness (QUALITY) analysis to a single image.
Fixed the bug where the Liveness analysis could finish with the SUCCESS result with no media uploaded.
The default value for the extract_best_shot parameter is now True.
Security updates.
Set the autorotation of logs.
Added the CLI command for user deletion.
You can now switch off the video preview generation.
The ADMIN access token is now valid for 5 years.
For the sliced video, the system now deletes the unnecessary frames.
Added new methods: GET and POST at media/<media_id>/snapshot/.
Replaced the default report template.
The Photo Expert and KYC modules are now removed.
The endpoint for the user password change is now POST users/user_id/change-password instead of PATCH.
Provided log for the Celery app.
Added filters to the Folder [LIST] request parameters: analyse.time_created, analyse.results_data for the Documents analysis, results_data for the Biometry analysis, results_media_results_data for the QUALITY analysis. To enable filters, set the with_results_media_filter query parameter to True.
Added a new attribute for users – is_active (default True). If is_active == False, any user operation is blocked.
Added a new exception code (1401 with status code 401) for the actions of the blocked users.
Added shots sets preview.
You can now save a shots set archive to a disk (with the original_local_path, original_url attributes).
A new original_info attribute is added to store md5, size, and mime-type of a shots set
Added health check at GET api/healthcheck.
Fixed the shots set thumbnail URL.
Now, the first frame of shots set becomes this shots set's thumbnail URL.
Modified the retry policy – the default max count of analysis attempts is increased to 3 and jitter configuration introduced.
Changed the callback algorithm.
Refactored and documented the command line tools.
Refactored modules.
Changed the delete personal information endpoint and method from delete_pi to /pi and from POST to DELETE, respectively.
Improved the delete personal information algorithm.
It is now forbidden to add media to cleaned folders.
Changed the authorize/restore endpoint name from auth to auth_restore.
Added a new tag – video_selfie_oneshot.
Added the password validation setting (OZ_PASSWORD_POLICY
Fixed a bug with no error while trying to synchronize empty collections.
If persons are uploaded, the analyse collection TFSS request is sent.
Added the fields_to_check parameter to document analysis (by default, all fields are checked).
Added the double_page_spread parameter to document analysis (True by default).
Fixed collection synchronization.
Authorization token can be now refreshed by expire_token.
Added support for application/x-gzip.
Renamed shots_set.images to shots_set.frames.
Added user sessions API.
Users can now change a folder owner (limited by permissions).
Changed dependencies rules.
Changed the access_token prolongation policy to fix bug of prolongation before checking the expiration permission.
Move oz_collection_binding (collection synchronization functional) to oz_core.
Simplified the shots sets functionality. One archive keeps one shot set.
Improved document-side recognition for the Docker version.
Moved the orientation tag check to liveness at quality analysis.
Added a default report template for Admin and Operator.
Updated the biometric model.
A new ShotsSet object is not created if there are no photos for it.
Updated the data exchange format for the documents' recognition module.
You can’t delete a Collection if there are associated analyses with Collection Persons.
Added time marks to analysis: time_task_send_to_broker, time_task_received, time_task_finished.
Added a new authorization engine. You can now connect with Active Directory by LDAP (settings configuration required).
A new type of media in Folders – "shots_set".
You can’t delete a CollectionPerson if there are analyses associated with it.
Renamed the folder field resolution_suggest to operator_status.
Added a folder text field operator_comment.
The folder fields operator_status
Fixed a deletion error: when report author is deleted, their reports get deleted as well.
Client can now view only their own profile.
Client Operator can now edit only their profile.
Client can't delete own folders, media, reports, or analyses anymore.
Client Service can now create Collection Person and read reports within their company.
Client, Client Admin, and Client Operator have read access to users' profiles only in their company.
A/B testing is now available.
Added support for expiration date header.
Added document recognition module Standalone/Dockered binding support.
Added a new role of Client Operator (like Client Admin without permissions for company and account management).
Client Admin and Client Operator can change the analysis status.
Only Admin and Client Admin (for their company) can create, update and delete operations for Collection and CollectionPerson models from now on.
Refined internal processes.
Enhanced security.
0.01.0The DOCUMENTS analysis no longer takes all folder media as sources, only those listed in source_media or marked with photo_id, photo_id_front, or photo_id_back. If there is no such media, untagged media is picked; if there is none, the API returns 400 Can't start analysis without media. To restore the previous behavior, set OZ_DOCUMENTS_MEDIA_TAGS_FILTRATION_ENABLED to false (default: true).
Updated the default report template, so reports now properly display media with analyses other than QUALITY.
Refined internal processes.
Enhanced security.
results_data for the CLIENT role.For Instant API, a container rejected for an expired session_token now saves its artifacts under the client company_id from the token instead of the default company.
Best shot original and thumb now return mime-type: image/jpeg instead of image/png.
The Prometheus counter no longer loses metrics on the gunicorn worker restart.
Internal improvements.
Enhanced security.
The /api/authorize/session_token/ endpoint now supports POST along with GET.
Improved TFSS resource efficiency.
Improved biometry analysis performance by up to 16% (single gesture) and up to 39% (multi-gesture).
Added the optional X-Forensic-Company-Id request header to GET /api/authorize/session_token/. In multi-tenant Instant API deployments, use this header to pass a tenant company_id (UUID) when obtaining a session token. The value is embedded in the token and used to attribute transactions to the correct tenant in billing and analytics.
media_association_id in output_images for best_shot and action_shot now correctly reflects the ID of the source media from which the frame was extracted.
preview_url for video media now includes the _preview suffix, consistent with shotset behavior.
original_nameResultImageActionShot.jpegOptimized shotset processing.
To prevent TFSS overload, you can now manage the number of concurrent requests API sends to TFSS. Please refer to API Configuration for details.
We no longer hide the best shot in base64 from response by default. The best shot can be found in analyses[].results_media[].output_images[].image_b64.
OzCapsula requests now include the analyses[] section in the response even when the request is declined with a non-null decline_reason, so integrations relying on analyses[] (e.g., using the on_complete callback in Web SDK) work properly.
expire_date in the /api/authorize/auth response is no longer affected by the timezone that is set in API.
By default, all OzCapsula-related errors now return the "Invalid request data" error message. Error codes stay unchanged.
To S3, we now save multiple engine_response.json files for a single media file: one for each analysis applied (naming: {analysis_id}_{source_media_id}_engine_response.json).
GET /api/collections/{collection_id}/persons/ no longer returns a 500 Internal Server Error for legacy image path formats; an invalid path now produces a meaningful error without a stack trace.
Resolved an AttributeError that might have occurred in case of failed JSON serialization.
Enhanced security.
Added timezone-safe handling for database records to ensure consistent timestamps regardless of the timezone used.
OzCapsula now returns specific error codes for different container damage types instead of a generic "Invalid Data Container" error.
Resolved API errors in multi-storage mode.
Setting OZ_STATIC_S3_BUCKET_URL as an empty string no longer leads to the S3 misconfiguration error.
Sending a container without media no longer causes a 500 error.
Fixed the bug where Instant API could save artifacts to local storage when persistence was disabled.
Fixed the bug where Instant API might create a database record when processing an invalid container.
Fixed the bug with time_created and time_updated that might have appeared incorrect.
Enhanced security.
If a container cannot be processed (error 14), we now save the corresponding order’s data to ease investigation.
If a container is considered invalid, API logs now include the corresponding folder_id to simplify the search.
Fixed folder deletion in local-local and local-s3 configurations to properly remove static files.
Internal improvements.
falseFixed the issue with MP4 videos that sometimes could not be played after downloading from SDK.
We now return the correct error for the non-authorized requests.
Fixed the bug with “spontaneous” error 500 that had been caused by too few frames in video. Added the check for the number of frames and more descriptive error messages.
Performance, security, and installation updates.
Enhanced security.
We no longer support RAR archives.
We no longer support Active Directory. This functionality will be returned in the upcoming releases.
Improved mechanics for calculating analysis time.
Replaced the is_admin and is_service flags for the CLIENT role with new roles: CLIENT ADMIN and CLIENT SERVICE, respectively. Set the roles in user_type.
To issue a service token for a user via {{host}}/api/authorize/service_token/, this user must have the CLIENT SERVICE role. You can also create a token for another user with this role: call {{host}}/api/authorize/service_token/{user_id}.
Removed collection and person attributes from COLLECTION.analysis.
We no longer store separate objects for each frame in SHOTS_SET. If you want to save an image from your video, consider enabling best shot.
We no longer support Podman for installation.
Updated the API reference: Oz API 6.0.
Changed endpoints and parameters:
analyse_id
analysis_id
can_start_analyse_biometry
can_start_analysis_biometry
can_start_analyse_collection
can_start_analysis_collection
can_start_analyse_documents
can_start_analysis_documents
can_start_analyse_quality
can_start_analysis_quality
expire_date in {{host}}/api/authorize/auth and {{host}}/api/authorize/refresh
access_token.exp from payload
session_id in {{host}}/api/authorize/auth and {{host}}/api/authorize/refresh
token_id
time_created
time_created.min
time_created.max
time_updated
time_updated.min
time_updated.max
session_id
session_id.exclude
sorting
offset
limit
total_omit
If you create a folder using SHOT_SET, the corresponding video will be in media.video_url.
Fixed the bug with CLIENT ADMIN being unable to change passwords for users from their company.
By default, analyses.results_media.results_data now contain the confidence_spoofing parameter. However, if you need all three parameters for the backward compatibility, it is possible to change the response back to three parameters: confidence_replay, confidence_liveness, and confidence_spoofing.
Updated the default PDF report template.
The name of the PDF report now contains folder_id.
Added the folder identifier folder_id to the report name.
Fixed bugs and optimized the API work.
ADMIN and OPERATOR receive system_company as a company they belong to.
Added the company_id attribute to User, Folder, Analyse, Media.
Added the Analysis group_id attribute.
Added the system_resolution attribute to Folder and Analysis.
The analysis resolution_status now returns the system_resolution value.
Removed the PATCH method for collections.
Added the resolution_status filter to Folder Analyses [LIST] and analyse.resolution_status filter to Folder [LIST].
Added the audit log for Folder, User, Company.
Improved the company deletion algorithm.
Reforged the blacklist processing logic.
Fixed a few bugs.
Fixed ReportInfo for shots sets.
Added auth, rest_unauthorized, rps_with_token throttling (use OZ_THROTTLING_RATES in configuration. Off by default).
User permissions are now used to access static files (OZ_USE_PERMISSIONS_FOR_STATIC in configuration, false by default).
Added a new folder endpoint – /delete_pi. It clears all personal information from a folder and analyses related to this folder.
operator_commentOnly Admin and Client Admin can delete folder, folder media, report template, report template attachments, reports, and analyses (within their company).
Collection creation now returns status code 201 instead of 200.
PATCH users/{{user_id}}/ to change user password
POST /api/users/{{user_id}}/change-password
DELETE images|media/<media_id> to delete an image of a person from collection
DELETE collections/<collection_id>/persons/<person_id>/images/<media_id>/
image_id, video_id, and shots_set_id
media_id
Deletes all action videos from file system (iOS 8.4.0 and newer, Android).
Returns
Future<Void>.
Returns the SDK version.
Returns
Future<String>.
Initializes SDK with license sources.
Returns
Authentication via credentials.
Returns
Authentication via access token.
Returns
Connection to the telemetry server via credentials.
Returns
Connection to the telemetry server via access token.
Returns
Checks whether an access token exists.
Returns
Deletes the saved access token.
Returns
Nothing (void).
Returns the list of SDK supported languages.
Returns
List<>.
Starts the Liveness video capturing process.
Sets the length of the Selfie gesture (in milliseconds).
Returns
Error if any.
Launches the analyses.
Returns
List<>.
Sets the SDK localization.
The number of attempts before SDK returns error.
Sets the UI customization values for OzLivenessSDK. The values are described in the Customization structures section. Structures can be found in the lib\customization.dart file.
Sets the timeout for the face alignment for actions.
Add fonts and drawable resources to the application/ios project.
Fonts and images should be placed into related folders:
ozforensics_flutter_plugin\android\src\main\res\drawable ozforensics_flutter_plugin\android\src\main\res\font
These are defined in the customization.dart file.
Contains the information about customization parameters.
Toolbar customization parameters.
Center hint customization parameters.
Hint animation customization parameters.
Frame around face customization parameters.
SDK version customization parameters.
Background customization parameters.
Defined in the models.dart file.
Stores the language information.
The type of media captured.
The type of media captured.
Contains an action from the captured video.
The One Shot gesture is being discontinued. Support will end on December 31, 2026. Please plan your migration.
Stores information about media.
Stores information about the analysis result.
Stores data about a single analysis.
Analysis type.
Analysis mode.
Contains the action from the captured video.
On January 1, 2027, the One Shot gesture will become unavailable. Please plan your .
The general status for all analyses applied to the folder created.
Defines what type of media is being sent to the server in case of the hybrid analysis once the on-device analysis is finished successfully. By default, the system uploads the compressed video.
Contains information about the .
This is a Map to define the platform-specific resources on the plugin level.
This key is a Map for the close button icon.
This key is a Map containing the data on the uploaded fonts.
This key is a Map containing the data on the uploaded font styles.
This key is a Map containing the data on grame shape.
The methods below apply to the new feature – that has been implemented in 9.1.0.
Captures media file with all information you need and packages it into a data container.
Returns
Void. The captured container is delivered via the livenessResult stream: Stream<DataContainer>.
Retrieves the raw bytes of a data container. Use this when sending media to the backend yourself.
Returns
Future<Uint8List?>.
This signature replaces uploadMedia in the analyze method when you use the data container flow.
Returns
List<RequestResult>.
Detects a request for video capture.
Contains information on media files and analyses that should be applied to them.
Stores information about a media file.
A media file with an action the user should perform.
An external media file, e.g., a reference or a document photo.
Parameter
Type
Description
licenses
List<String>
A list of licences
Case
Text
True
Initialization has completed successfully
False
Initialization error
Parameter
Type
Description
String
User email
Case
Text
Success
Nothing (void)
Failed
PlatformException:
code = AUTHENTICATION_FAILED
message = exception details
Parameter
Type
Description
token
String
Access token
Case
Text
Success
Nothing (void)
Failed
PlatformException:
code = AUTHENTICATION_FAILED
message = exception details
Parameter
Type
Description
String
User email
Case
Text
Success
Nothing (void)
Failed
PlatformException:
code = AUTHENTICATION_FAILED
message = exception details
Parameter
Type
Description
token
String
Access token
Case
Text
Success
Nothing (void)
Failed
PlatformException:
code = AUTHENTICATION_FAILED
message = exception details
Case
Returns
Token exists
True
Token does not exist
False
Parameter
Type
Description
actions
List<>
Actions to execute
Parameter
Type
Description
selfieLength
Int
The length of the Selfie gesture (in milliseconds). Should be within 500-5000 ms, the default length is 700
Parameter
Type
Description
analysis
List<>
The list of Analysis structures
folder ID (optional)
Parameter
Type
Description
locale
The SDK language
Parameter
Type
Description
singleCount
int
Attempts on a single action/gesture
Parameter
Type
Description
timeout
int
Timeout in milliseconds
Parameter
Type
Description
closeButtonIcon
String
Close button icon received from plugin
Parameter
Type
Description
textFont
String
Text font
Parameter
Type
Description
hideAnimation
bool
Hides the hint animation
Parameter
Type
Description
geometryType
String
Frame shape received from plugin
Parameter
Type
Description
textFont
String
Text font
Parameter
Type
Description
backgroundColor
String
Color #XXXXXX
Case
Description
en
English
hy
Armenian
Case
Description
movement
A media with an action
documentBack
The back side of the document
Case
Description
documentPhoto
A photo of a document
video
A video
Case
Description
blank
A video with no gesture
photoSelfie
Parameter
Type
Description
Platform
fileType
Parameter
Type
Description
Platform
folderId
String
Parameter
Type
Description
type
The type of the analysis
Case
Description
biometry
The algorithm that allows comparing several media and check if the people on them are the same person or not
quality
The algorithm that aims to check whether a person in a video is a real human acting in good faith, not a fake of any kind.
Case
Description
onDevice
The on-device analysis with no server needed
serverBased
The server-based analysis
Case
Description
oneShot
The best shot from the video taken
blank
Case
Description
failed
One or more analyses failed due to some error and couldn't get finished
declined
The check failed (e.g., faces don't match or some spoofing attack detected)
uploadCompressed
The compressed video
uploadBestShot
The best shot taken from the video
Parameter
Type
Description
hash
String
SHA256 key hash in base64
Key
Value
Close
Android drawable resource / iOS Pods resource
Arrow
Android drawable resource / iOS Pods resource
Key
Value
Flutter application font name
Android font resource / iOS Pods resource, used to retrieve the font on the plugin level
Key
Value
Flutter application font style name
Name of the style retrieved for the font creation on the plugin level
Key
Value
Oval
Oval shape
Rectangle
Rectangular shape
Parameter
Type
Description
request
CaptureRequest
Detects a request for video capture
sessionToken
String
Parameter
Type
Description
dataContainer
DataContainer
The captured data container, result of the request
Parameter
Type
Description
analysis
List<>
The list of Analysis structures
dataContainer
DataContainer
Parameter
Type
Description
analysisProfileList
List<>
A list of objects that contain information on media and analyses that should be applied to them
folderMeta (optional)
Parameter
Type
Description
type
Type
Analysis type
mediaList
List<>
Parameter
Type
Description
id (optional)
String (UUID v4)
Media ID. Auto-generated if not provided
actionMedia
Parameter
Type
Description
action
An action that user should perform in a video
id (optional)
String (UUID v4)
Parameter
Type
Description
media
The external media file
id (optional)
String
password
String
User password
host
String
Server URL
sslPins (optional)
Whitelisted certificates
host
String
Server URL
sslPins (optional)
Whitelisted certificates
password
String
User password
host
String
Server URL
sslPins (optional)
Whitelisted certificates
host
String
Server URL
sslPins (optional)
Whitelisted certificates
mainCamera
Boolean
Use main (True) or front (False) camera
String
Folder ID, if you want to perform an anaoysis for a particular folder
uploadMedia
List<>
The list of the captures videos
params
Map<String, Any>
Additional parameters
commonCount
int
Total number of attempts on all actions/gestures if you use a sequence of them
closeButtonColor
String
Color #XXXXXX
titleText
String
Header text
titleFont
String
Text font
titleSize
int
Font size
titleFontStyle
String
Font style
titleColor
String
Color #XXXXXX
titleAlpha
int
Header text opacity
isTitleCentered
bool
Sets the text centered
backgroundColor
String
Header background color #XXXXXX
backgroundAlpha
int
Header background opacity
textFontStyle
String
Font style
textColor
String
Color #XXXXXX
textSize
int
Font size
verticalPosition
int
Y position
textAlpha
int
Text opacity
centerBackground
bool
Sets the text centered
animationIconSize
int
Animation icon size in px (40-160)
hintGradientColor
String
Color #XXXXXX
hintGradientOpacity
int
Gradient color
geometryTypeRadius
int
Corner radius for rectangle
strokeWidth
int
Frame stroke width
strokeFaceNotAlignedColor
String
Color #XXXXXX
strokeFaceAlignedColor
String
Color #XXXXXX
strokeAlpha
int
Stroke opacity
strokePadding
int
Stroke padding
textFontStyle
String
Font style
textColor
String
Color #XXXXXX
textSize
int
Font size
textAlpha
int
Text opacity
backgroundAlpha
int
Background opacity
kk
Kazakh
ky
Kyrgyz
tr
Turkish
es
Spanish
pt_br
Portuguese (Brazilian)
documentFront
The front side of the document
shotSet
A frame archive
A selfie photo
videoSelfieOneShot
A video with the best shot taken
videoSelfieScan
A video with the scanning gesture
videoSelfieEyes
A video with the blink gesture
videoSelfieSmile
A video with the smile gesture
videoSelfieHigh
A video with the lifting head up gesture
videoSelfieDown
A video with the tilting head downwards gesture
videoSelfieRight
A video with the turning head right gesture
videoSelfieLeft
A video with the turning head left gesture
photoIdPortrait
A photo from a document
photoIdBack
A photo of the back side of the document
photoIdFront
A photo of the front side of the document
The type of the file
Android
movement
An action on a media
iOS
mediatype
String
A type of media
iOS
videoPath
String
A path to a video
bestShotPath
String
path of the best shot in PNG for video or image path for liveness
preferredMediaPath
String
URL of the API media container
photoPath
String
A path to a photo
archivePath
String
A path to an archive
tag
A tag for media
Android
The folder identifier
type
The analysis type
errorCode
int
The error code
Android only
errorMessage
String
The error message
mode
The mode of the analysis
confidenceScore
Double
The resulting score
resolution
The completed analysis' result
status
Boolean
The analysis state:
true- success;
false- failed
mode
The mode of the analysis
mediaList
List<>
Media to analyze
params
Map<String, String>
Additional analysis parameters
sizeReductionStrategy
Defines what type of media is being sent to the server in case of the hybrid analysis once the on-device analysis is finished successfully. On January 1, 2027, on-device and hybrid analysis modes will become unavailable. Use server-based analysis instead.
hybrid
The hybrid analysis for Liveness: if the score received from an on-device analysis is too high, the system initiates a server-based analysis as an additional check.
A selfie with face alignment check
scan
Scan
headRight
Head turned right
headLeft
Head turned left
headDown
Head tilted downwards
headUp
Head lifted up
eyeBlink
Blink
smile
Smile
success
Everything went fine, the check succeeded (e.g., faces match or liveness confirmed)
operatorRequired
The result should be additionally checked by a human operator
uploadNothing
Nothing is sent (note that no folder will be created)
expired_at
UNIX timestamp, UTC time
The date of certificate expiration, ms
Token required for OzCapsula flow
The captured data container, result of the request
Map<String, dynamic>
Additional folder metadata
additionalMediaList (optional)
List<>
Media files that you need to upload to server, but it's not necessary for analyses
cameraPosition (optional)
CameraPosition
front (default) – front camera; back – rear camera
A list of media to be analyzed
params (optional)
Map<String, dynamic>
Additional analysis parameters
An action that user should perform in a video
userMedia
An external media file, e.g., a reference or a document photo
mediaMeta (optional)
Map<String, dynamic>
Media metadata
Media ID. Auto-generated if not provided
mediaMeta (optional)
Map<String, dynamic>
Media metadata
Media ID
mediaMeta (optional)
Map<String, dynamic>
Media metadata
Oz API is the most important component of the system – it connects all the other components together, and it is the unified REST interface you call to run Liveness and Biometry analyses. Oz API:
provides the unified REST API interface to run the Liveness and Biometry analyses,
processes authorization and user-permission management,
tracks and records requested orders and analyses to the database (for example, in 6.0 the database size for 100 000 orders with analyses is ~4 GB),
archives the inbound media files,
collects telemetry from connected mobile apps,
provides settings for specific device models,
generates reports with analyses' results.
For the latest API methods collection, please refer to our .
Oz API runs the same analyses in two modes that differ mostly in what is stored:
Instant API is part of Oz API, not a separate product: it exposes the same analyses through a non-persistent endpoint, and it supports both submission modes described below.
You can submit your media and analyses in two ways, available in both the persistent and Instant modes:
– send all the media together with the analysis request in one call and receive the results in the same response. This removes the need for multiple API calls – one is sufficient. Introduced in API 6.0.
Multi-request – create the folder, upload the media, assign the analyses, and then poll for the result or receive it via a webhook. Use this for larger media, deferred analysis, or operator review.
For maximum protection of the captured media, the Oz SDKs can pack a capture into – a proprietary, encrypted, integrity-protected data container tied to a single capture session by a short-lived session_token. The container is an opaque blob: it is forwarded to the API as-is (with Content-Type: application/octet-stream) and validated server-side, which defends against injection, tampering, and replay of the captured data.
Oz API calls are with a token passed in the X-Forensic-Access-Token header. You obtain it by logging in with credentials or by using a long-lived service token for server-to-server integrations. Instant API can optionally be run without authorization.
Persistent (/api/folders/)
Non-persistent – Instant API (/api/instant/folders/)
What is stored
Creates a folder; media, analyses, results, and reports are stored and can be retrieved later
Nothing is stored – the result exists only in the HTTP response. However, you can set up S3 storage to save the Instant API artifacts.
Best for
Case history, the Web Console, reports, webhooks, re-analysis
Sensitive data, GDPR compliance, a minimal storage footprint
You can generate the trial license here or contact us by email to get a productive license. To create the license, your applicationId (bundle id) is required.
To pass your license file to the SDK, call the OzLivenessSDK.init method with a list of LicenseSources. Use one of the following:
LicenseSource.LicenseAssetId should contain a path to a license file called forensics.license, which has to be located in the project's res/raw folder.
LicenseSource.LicenseFilePath should contain a file path to the place in the device's storage where the license file is located.
LicenseSource.LicenseData should contain the contents of the license file as a byte array.
In case of any license errors, the onError function is called. Use it to handle the exception as shown above. Otherwise, the system will return information about license. To check the license data manually, use the getLicensePayload method.
The license data is missing. Please check it.
License error. Cannot parse license from (your_URI), invalid format
The license file is somehow damaged. Please email us the file.
License error. Bundle company.application.id is not in the list allowed by license (bundle.id1, bundle.id2)
The bundle (application) identifier you specified is missing in the allowed list. Please check the spelling, if it is correct, you need to get another license for your application.
License error. Current date yyyy-mm-dd hh:mm:ss is later than license expiration date yyyy-mm-dd hh:mm:ss
Your license has expired. Please contact us.
License is not initialized. Call 'OzLivenessSDK.init before using SDK
You haven't initialized the license. Call OzLivenessSDK.init with your license data as explained above.
License error. License not found
The license file is missing. Please check its name.
License error. License at (your_URI) not found
The license file is missing. Please check path to the file.
OzLivenessSDK.init(context,
listOf(
LicenseSource.LicenseAssetId(R.raw.your_license_name),
LicenseSource.LicenseFilePath("absolute_path_to_your_license_file"),
LicenseSource.LicenseData(your_license_byte_array)
),
object : StatusListener<LicensePayload> {
override fun onSuccess(result: LicensePayload) { /*check the license payload*/ }
override fun onError(error: OzException) { /*handle the exception */ }
}
)OzLivenessSDK.INSTANCE.getConfig().setBaseURL(BASE_URL);
OzLivenessSDK.INSTANCE.init(context,
Arrays.asList(
new LicenseSource.LicenseAssetId(R.raw.forensics),
new LicenseSource.LicenseFilePath("absolute_path_to_your_license_file"),
new LicenseSource.LicenseData(your_license_byte_array)
),
new StatusListener<LicensePayload>() {
@Override public void onStatusChanged(@Nullable String s) {}
@Override public void onSuccess(LicensePayload licensePayload) { /*check the license payload*/ }
@Override public void onError(@NonNull OzException e) { /*handle the exception */
}
);License error. License data is empty