> For the complete documentation index, see [llms.txt](https://doc.ozforensics.com/oz-knowledge-ru/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://doc.ozforensics.com/oz-knowledge-ru/obshaya-informaciya/kratkie-rukovodstva-po-integracii/kak-integrirovat-oz-liveness-s-ispolzovaniem-instant-api-rezhima-bez-sokhraneniya-dannykh.md).

# Как интегрировать Oz Liveness с использованием Instant API (режима без сохранения данных)

{% hint style="warning" icon="display" %}
Внимание: это машинный перевод.
{% endhint %}

Это руководство охватывает полный цикл интеграции: получение session token, съемка медиа с помощью SDK, отправка полученного контейнера `OzCapsula` в Oz API Instant, чтение ответа, принятие решения о допуске или отклонении, уменьшение размера ответа и базовая диагностика.

В описании процесса упоминаются:

* **Режим съемки** – Web SDK (или Mobile SDK) снимает видео для Liveness в браузере или приложении, а бэкенд клиента передает его в Oz API. Результаты съемки не отправляются из SDK напрямую в Oz API: бэкенд клиента выступает посредником.
* **OzCapsula** – [проприетарный зашифрованный бинарный контейнер](/oz-knowledge-ru/obshaya-informaciya/opisanie-sistemy-oz-forensics/konteiner-dannykh-ozcapsula.md). SDK упаковывает в него снятые медиаданные и метаданные; Oz API расшифровывает и обрабатывает его. Контейнер защищает снятые данные от изменения на пути от устройства пользователя до Oz API. Контейнер — это **непрозрачный зашифрованный blob**. Вы **не можете** декодировать его, просматривать его содержимое или извлекать из него отдельные изображения, кадры или метаданные на стороне клиента. Контейнер необходимо передать на бэкенд в исходном виде. Если вам нужен доступ к снятым изображениям (например, к лучшему кадру), получайте их из ответа Oz API на стороне сервера.
* **Instant API** – режим Oz API без сохранения данных. Результаты возвращаются сразу в ответе, ничего не сохраняется.

Вместе: SDK снимает медиа и упаковывает их в OzCapsula → ваш бэкенд передает контейнер в Oz API Instant → Oz API синхронно возвращает результат, ничего не сохраняя.

## Глоссарий

Несколько терминов, используемых в этом руководстве.

* `{{host}}` – базовый URL вашего развертывания Oz API. Предоставляется вам при настройке.
* **Session token** – краткосрочный токен, который привязывает OzCapsula к конкретной сессии съемки и предотвращает повторное использование того же контейнера позже. Обязателен для OzCapsula.
* **Folder (папка)** – объект ответа, который Oz API создает для одной отправки. Он группирует отправленные медиа и примененные к ним анализы.
* **Тип анализа** – то, что Oz API выполняет над медиа. API возвращает `QUALITY` для анализов **Liveness** и `BIOMETRY` для анализов **Face Matching**.

## Версии компонентов

| Компонент                 | Минимальная версия |
| ------------------------- | ------------------ |
| Oz API                    | 6.6.1              |
| Mobile SDK (iOS, Android) | 10.0.0             |
| Web SDK                   | 1.9.10             |

{% stepper %}
{% step %}

## Получите session token

OzCapsula требует session token для каждой сессии съемки.

Чтобы включить функциональность session token, сгенерируйте пару ключей JWT. Инструкции по их созданию см. в helm-чарте API Instant: перейдите к `readme.md` и в разделе **Preparation** найдите подраздел **Create a JWT secret**. Получив ключи, создайте папку в вашей установке, поместите ключи туда и укажите этот путь в `API_KEYS_DIR` (например, `API_KEYS_DIR=/opt/oz/api/keys`). Это выполняется один раз для установки.

Запросите session token у Oz API Instant. Запрашивайте его перед каждой сессией съемки — как можно ближе к моменту, когда пользователь начинает съемку.

**Эндпойнт:**

```
GET {{host}}/api/authorize/session_token
```

**Заголовки:**

* `Content-Type: application/json`

**Запрос:**

```shell
curl -L 'https://{{host}}/api/authorize/session_token' \
  -H 'Content-Type: application/json'
```

**Ответ:**

```json
{
  "session_token": "<session_token>"
}
```

Токен краткосрочный (время жизни по умолчанию: 900 секунд для API Full, 120 секунд для Instant API). Запрашивайте один токен на сессию съемки и сразу же передавайте его в SDK — не кэшируйте и не используйте повторно в разных сессиях.

Механизм авторизации при вызове Oz API зависит от установки; по умолчанию токен доступа в заголовках не требуется. Если в вашем случае он требуется, см. раздел [Аутентификация](/oz-knowledge-ru/rukovodstva/rukovodstvo-razrabotchika/api/oz-api/autentifikaciya-i-obrabotka-dannykh/tokens.md).
{% endstep %}

{% step %}

## Съемка и упаковка на устройстве

SDK снимает медиа пользователя и упаковывает их в контейнер `OzCapsula`.

### Mobile SDK (iOS, Android)

Запустите анализ с session token. Контейнер возвращается через коллбэк результата.

#### Android (Kotlin)

```kotlin
// 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 */
            }
        }
    }
}
```

#### iOS (Swift)

```swift
// 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 5
        handleContainer(container)
    }

    func onError(status: OZVerificationStatus?) {
        // user cancelled, capture failed, etc.
    }
}
```

Контейнер возвращается как `bytearray` (Android) или `DataContainer` (iOS). Передайте его на бэкенд без каких-либо преобразований.

### Web SDK

Вызовите `OzLiveness.Open()` с session token. По завершении съемки SDK вызывает коллбэк `on_capture_complete`. Контейнер передается вторым аргументом.

```javascript
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 */ }
});
```

Контейнер приходит как `Blob` с MIME-типом `application/octet-stream`. Передайте его на бэкенд без каких-либо преобразований.
{% endstep %}

{% step %}

## Анализ Liveness: отправьте контейнер в Instant API

Ваш бэкенд передает контейнер в одном синхронном `POST`-запросе.

**Эндпойнт:**

```
POST {{host}}/api/instant/folders/
```

**Заголовки:**

* `Content-Type: application/octet-stream` (обязательно)

**Тело запроса:** необработанные байты контейнера — без JSON-обертки, без multipart, без base64.

```shell
curl -X POST '{{host}}/api/instant/folders/' \
  -H 'Content-Type: application/octet-stream' \
  --data-binary '@/path/to/container.dat'
```

**При успехе:** HTTP `201` с JSON-объектом папки, описывающим результат.

**При ошибке на уровне контейнера:** HTTP `400` (см. раздел «Неуспешные результаты»).

Анализ `QUALITY` (Liveness) предоставляет лучший кадр. Найдите запись `QUALITY` в массиве `analyses[]` и читайте:

```json
$.analyses[*].results_media[*].output_images[*].image_b64
```

Значение — это JPEG в кодировке base64. Декодируйте его в JPEG.
{% endstep %}

{% step %}

## Анализ Biometry (Face Matching) (опционально)

Если сопоставление лиц вам не нужно, пропустите этот шаг и переходите сразу к **шагу 5**.

Вызовите `POST /api/instant/folders/` с вашим эталонным фото и лучшим кадром, полученным из анализа Liveness на **шаге 3**.

{% hint style="info" %}
**Ключи ваших медиафайлов и соответствующие имена файлов должны совпадать.**
{% endhint %}

Тело запроса:

```json
{
  "media:tags": {
    "UUID_of_reference_photo.jpeg": ["photo_selfie"],
    "best_shot.jpeg": ["photo_selfie"]
  },
  "analyses": [
    { "type": "biometry" }
  ]
}
```

Ответ будет содержать результат анализа biometry.
{% endstep %}

{% step %}

## Прочитайте ответ

#### Поля верхнего уровня

| Поле                 | Назначение                                                                                                                                        |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `folder_id`          | Уникальный идентификатор запроса                                                                                                                  |
| `resolution_status`  | Завершена ли обработка: `FINISHED` или `FAILED`                                                                                                   |
| `system_resolution`  | Общий результат: `SUCCESS`, `DECLINED` или `FAILED`                                                                                               |
| `resolution_comment` | Примечание о разрешении анализа. Полезно при `FAILED` (перечисляет, какие анализы не прошли)                                                      |
| `meta_data`          | Блок метаданных. Содержит `event_session_id` — идентификатор сессии, необходимый для соотнесения запроса с сессией пользователя в вашем фронтенде |
| `media`              | Медиафайлы, отправленные в контейнере                                                                                                             |
| `analyses`           | Массив результатов по каждому анализу                                                                                                             |

#### Внутри `analyses[]`

| Поле                          | Назначение                                                                                                    |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `type`                        | `QUALITY` для Liveness, `BIOMETRY` для сопоставления лиц                                                      |
| `state`                       | Состояние обработки этого анализа: `FINISHED` или `FAILED`                                                    |
| `resolution_status`           | Результат этого анализа: `SUCCESS`, `DECLINED` или `FAILED`                                                   |
| `error_code`, `error_message` | Отображаются только при технической ошибке анализа                                                            |
| `results_data`                | Агрегированные значения результата                                                                            |
| `results_media`               | Сгенерированные медиаэлементы. Для анализа `QUALITY` содержит лучший кадр в `output_images[]` — см. **шаг 3** |
| `source_media`                | Входные медиа                                                                                                 |

### Примите решение о допуске или отклонении

Используйте только эти два поля верхнего уровня:

```json
$.resolution_status   // "FINISHED" — анализы завершены; "FAILED" — ошибка при обработке анализа
$.system_resolution   // "SUCCESS", "DECLINED" или "FAILED"
```

Интерпретация значений `system_resolution`:

* `SUCCESS` — все проверки пройдены; пользователь допускается.
* `DECLINED` — одна или несколько проверок не пройдены; пользователь отклоняется.
* `FAILED` — системная ошибка не позволила завершить хотя бы один анализ; не следует трактовать как допуск или отклонение (см. раздел «Неуспешные результаты»).

Для получения результатов по каждому анализу отдельно (например, чтобы узнать, прошла ли Liveness, но не прошло сопоставление лиц) читайте `$.analyses[*].resolution_status` с теми же тремя значениями.

### Прочие поля

Ответ также содержит внутренние идентификаторы (`group_id`, `media_association_id`), хеши файлов, поля, связанные с оператором (`operator_comment`, `operator_status`, `is_cleared`), и другие системные поля. Для потока интеграции, описанного в этом руководстве, они не нужны.
{% endstep %}

{% step %}

## Неуспешные результаты

### Недопустимый контейнер – HTTP `400`

Когда контейнер не проходит валидацию, Oz API отвечает HTTP `400` и `error_message: "Invalid request data"`. Конкретный `error_code` указывает на причину:

| `error_code` | Условие                                                                                                  |
| ------------ | -------------------------------------------------------------------------------------------------------- |
| `3`          | Отсутствует payload                                                                                      |
| `4`          | В контейнере нет медиа                                                                                   |
| `5`          | Контейнер поврежден                                                                                      |
| `13`         | В запросе нет контейнера                                                                                 |
| `14`         | Недопустимый контейнер — любая причина (ошибка расшифровки, подписи, хеша или валидации `session_token`) |

Коды `13` и `14` срабатывают до распаковки контейнера; коды `3`, `4`, `5` срабатывают после распаковки, когда сам payload не проходит бизнес-валидацию.

Для кода `14` отправьте экземпляр контейнера и `error_code` в поддержку Oz Forensics — конкретная причина доступна только в серверных логах.

### Отклонено – HTTP `201`

Контейнер был валиден и анализы выполнились, но хотя бы одна проверка не прошла.

* `resolution_status: FINISHED`.
* `system_resolution: DECLINED`.
* `resolution_comment: "[]"` (неинформативно — причина отклонения неявно содержится в результате по каждому анализу).
* По каждому анализу `resolution_status: DECLINED`.

### Ошибка – HTTP `201`

Системная ошибка не позволила завершить хотя бы один анализ.

* `resolution_status: FAILED`.
* `system_resolution: FAILED`.
* `resolution_comment` — строка с перечислением того, какие анализы не прошли и с каким кодом.
* По каждому анализу `state: FAILED`, `resolution_status: FAILED`, заполнены `error_code` и `error_message`.
  {% endstep %}
  {% endstepper %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://doc.ozforensics.com/oz-knowledge-ru/obshaya-informaciya/kratkie-rukovodstva-po-integracii/kak-integrirovat-oz-liveness-s-ispolzovaniem-instant-api-rezhima-bez-sokhraneniya-dannykh.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
