> For the complete documentation index, see [llms.txt](https://docs.facephi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.facephi.com/docs.facephi-en/sdks/backend-sdk/iad.md).

# IAD Service

**Rest API for Injection Attack Detection (Injection Attack Detection)** — Protect your biometric systems against spoofing attacks.

## What is IAD Service?

IAD Service is a Rest API microservice that detects injection attacks in biometric captures. It verifies that biometric data comes from real sources, not from replays or synthetic inputs.

> **Breaking change notice (2.0.0)** Version 2.0.0 breaks compatibility of the public Rest API with all previous 1.x.x versions. Integrations upgrading from 1.x.x must update endpoint paths, multipart request field names, and the parsing of successful responses.

| 1.x.x contract                                                                                 | 2.0.0 contract                                                                                                                          |
| ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /api/v1/iad/check-capture`                                                               | `POST /api/v1/iad/liveness/evaluate`                                                                                                    |
| `POST /api/v1/iad/extract-image`                                                               | `POST /api/v1/iad/extract`                                                                                                              |
| multipart field `file`                                                                         | required multipart field `capture`; `file` is rejected when missing `capture`                                                           |
| Legacy private success payloads (`capture_liveness`, `capture_type`, `rejection`, `mime_type`) | Facephi public payloads (`diagnostic`, `reason`, `probability`, `score`, `faceProbability`, `sdkDuration`, `queueDuration`, `mimeType`) |

**Use it for:**

* Extract valid images from authenticated captures
* Monitor system status and performance
* Integrate it seamlessly with your authentication flows

## Quick start

### Requirements

| Component | Requirement                              |
| --------- | ---------------------------------------- |
| OS        | Linux x86\_64 (Ubuntu 24.04 recommended) |
| License   | Valid Facephi License file               |

### Docker deployment

```bash
docker run -d \\
  -p 6982:6982 \\
  -v /path/to/license:/app/license \\
  -v /path/to/config:/app/config \\
  --name iad-service \\
  facephicorp.jfrog.io/docker-pro-fphi/facephi-iad-service:2.2.0
```

### Verify that it works

```bash
# Check health
curl http://localhost:6982/api/v1/iad/health

# Check version
curl http://localhost:6982/api/v1/iad/version
```

Typical responses:

```json
{
  "message": "Healthy"
}
```

```json
{
  "message": "2.2.0 Copyright © 2026 FacePhi Biometria. All rights reserved."
}
```

## API endpoints

> **Compatibility note** The routes documented on this page are valid only for version 2.0.0 and later.

### Main operations

| Endpoint                        | Method | Purpose                                                                         |
| ------------------------------- | ------ | ------------------------------------------------------------------------------- |
| `/api/v1/iad/liveness/evaluate` | POST   | Evaluates the liveness of an encrypted capture with the Facephi public contract |
| `/api/v1/iad/extract`           | POST   | Extracts the image from a validated capture                                     |

### Management

| Endpoint                         | Method   | Purpose                                                                        |
| -------------------------------- | -------- | ------------------------------------------------------------------------------ |
| `/api/v1/iad/version`            | GET      | Service version and license status                                             |
| `/api/v1/iad/health`             | GET      | Active health check (includes snapshot `initialized` and `engine.lastHealth*`) |
| `/api/v1/iad/metrics`            | GET      | JSON snapshot of operational and quality metrics                               |
| `/api/v1/iad/metrics/prometheus` | GET      | Equivalent snapshot in Prometheus format                                       |
| `/api/v1/iad/config`             | GET/POST | Get or update the configuration                                                |

`/health` and `/metrics` have different purposes:

* `/health` runs the engine active check and updates the health snapshot.
* `/metrics` exposes counters and in-memory snapshots, without running expensive active checks on each scrape.

## Experimental replay attack mitigation

The service can apply a freshness window to incoming capture payloads. This experimental protection is disabled by default.

* Enable it with `FACEPHI_IAD_REPLAY_ATTACK_CHECKER_ENABLED=true`
* Adjust the freshness window with `FACEPHI_IAD_REPLAY_ATTACK_TOLERANCE_TIME=<seconds>`
* Default freshness window: `300` seconds
* It applies to capture processing endpoints such as `POST /api/v1/iad/liveness/evaluate` and `POST /api/v1/iad/extract`
* When the freshness window is exceeded, the service returns HTTP `400` with `message` equal to `Replay attack detected`

Deployment example:

```bash
docker run -d \\
  -p 6982:6982 \\
  -e FACEPHI_IAD_REPLAY_ATTACK_CHECKER_ENABLED=true \\
  -e FACEPHI_IAD_REPLAY_ATTACK_TOLERANCE_TIME=60 \\
  -v /path/to/license:/app/license \\
  -v /path/to/config:/app/config \\
  --name iad-service \\
  facephicorp.jfrog.io/docker-pro-fphi/facephi-iad-service:2.2.0
```

This functionality is configured only at startup through environment variables. It is not part of `config.json` or exposed through `GET|POST /api/v1/iad/config`.

## JWT authentication

JWT authentication is optional and disabled by default.

* Configure it at startup with `config.json` with `auth_enabled`, `auth_jwt_secret`, `auth_accept_authorization_header`, `auth_accept_api_key_header` and `auth_api_key_header_name`
* Override those same values via environment variables `FACEPHI_IAD_REST_AUTH_*`
* `GET /api/v1/iad/config` omits all JWT authentication keys
* `POST /api/v1/iad/config` rejects all JWT authentication keys; use startup configuration instead

Example snippet of `config.json`:

```json
{
  "auth_enabled": true,
  "auth_jwt_secret": "replace-with-secret",
  "auth_accept_authorization_header": true,
  "auth_accept_api_key_header": true,
  "auth_api_key_header_name": "x-api-key"
}
```

Example environment variables:

```bash
export FACEPHI_IAD_REST_AUTH_ENABLED=true
export FACEPHI_IAD_REST_AUTH_JWT_SECRET=replace-with-secret
export FACEPHI_IAD_REST_AUTH_ACCEPT_AUTHORIZATION_HEADER=true
export FACEPHI_IAD_REST_AUTH_ACCEPT_API_KEY_HEADER=true
export FACEPHI_IAD_REST_AUTH_API_KEY_HEADER_NAME=x-api-key
```

## Public error contract

In public HTTP responses `400`, the service returns public messages documented in the standard response body.

### Liveness result

Successful responses from `POST /api/v1/iad/liveness/evaluate` expose only the following public fields:

| Field             | Meaning                                                     |
| ----------------- | ----------------------------------------------------------- |
| `diagnostic`      | High-level result: `Live` or `NoLive`                       |
| `reason`          | Public reason value returned by the service                 |
| `probability`     | Public probability of the capture                           |
| `score`           | Public confidence score                                     |
| `faceProbability` | Optional public facial liveness probability, when available |
| `sdkDuration`     | Capture analysis duration in milliseconds                   |
| `queueDuration`   | Queue duration reported by RestManager in milliseconds      |

The possible values for `reason` are:

* `None`
* `Unknown`
* `UntrustedEnvironment`
* `SuspiciousActivity`
* `UntrustedDevice`
* `SdkIntegrityViolation`
* `UntrustedCorruptedPayload`
* `UntrustedContent`
* `UntrustedContentLowConfidence`

| `reason`                        | Meaning                                                                                                                                      |
| ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `None`                          | The capture was accepted as `Live` and no rejection reason applies.                                                                          |
| `Unknown`                       | The service could not assign the response to a documented public rejection reason.                                                           |
| `UntrustedEnvironment`          | The capture was rejected because the runtime environment is not considered trusted.                                                          |
| `SuspiciousActivity`            | The capture was rejected because the device showed activity patterns associated with an attack.                                              |
| `UntrustedDevice`               | The capture was rejected because the device could not be trusted to be what it claims to be.                                                 |
| `SdkIntegrityViolation`         | The capture was rejected because the capture SDK or its libraries appear to have been altered.                                               |
| `UntrustedCorruptedPayload`     | The capture was rejected because the payload appears to be corrupt or tampered with.                                                         |
| `UntrustedContent`              | The capture was rejected because an injection attack was detected.                                                                           |
| `UntrustedContentLowConfidence` | The capture was rejected because the service detected signs of a lower-confidence injection attack; it must still be treated as a rejection. |

When there are multiple rejection causes, the service returns the first documented public rejection value according to the service response order.

### Normalized validation errors

For the endpoint `POST /api/v1/iad/liveness/evaluate`, capture validation failures are returned as HTTP `400` with documented `message` values, such as:

| Scenario                                      | `message` public                  |
| --------------------------------------------- | --------------------------------- |
| Face too close                                | `NoneBecauseFaceTooClose`         |
| Face not found                                | `NoneBecauseFaceNotFound`         |
| Face cropped                                  | `NoneBecauseFaceCropped`          |
| Face occluded                                 | `NoneBecauseFaceOccluded`         |
| Too many faces                                | `NoneBecauseTooManyFaces`         |
| Face angle too large                          | `NoneBecauseAngleTooLarge`        |
| Face too small                                | `NoneBecauseFaceTooSmall`         |
| Face too close to the border                  | `NoneBecauseFaceTooCloseToBorder` |
| Eyes closed                                   | `NoneBecauseEyesClosed`           |
| Unable to process the image or payload        | `NoneBecauseImageDataError`       |
| License issue reported by the service runtime | `NoneBecauseLicenseError`         |
| Replay freshness window exceeded              | `Replay attack detected`          |
| Unclassified liveness failure                 | `ErrorProcessing`                 |

For the endpoint `POST /api/v1/iad/extract`, payload analysis and decryption failures are returned as `NoneBecauseImageDataError`; expired captures rejected by replay protection return `Replay attack detected`; unclassified extraction failures are returned as `ErrorFacialImage`.

## Usage example

> **Update note** The following examples intentionally use the 2.x public contract introduced in version 2.0.0: the multipart field `capture` and the public response schema.

### Evaluate Liveness

```bash
curl -X POST \\
  -F "capture=@biometric_capture.bin" \\
  http://localhost:6982/api/v1/iad/liveness/evaluate
```

**Response:**

```json
{
  "diagnostic": "Live",
  "reason": "None",
  "probability": 1,
  "score": 1,
  "sdkDuration": 12,
  "queueDuration": 3
}
```

### Extract image

```bash
curl -X POST \\
  -F "capture=@biometric_capture.bin" \\
  http://localhost:6982/api/v1/iad/extract
```

**Response:**

```json
{
  "image": "base64_encoded_image...",
  "mimeType": "image/jpeg"
}
```

### Get configuration

Returns the public view of the runtime configuration. JWT authentication keys are intentionally omitted.

```bash
curl http://localhost:6982/api/v1/iad/config
```

### Update configuration

`POST /api/v1/iad/config` expects a JSON object with the field `config_json_string`, which contains the full configuration serialized as a JSON string. JWT authentication keys are rejected by this endpoint and must be set only at startup.

```bash
curl -X POST \\
  -H "Content-Type: application/json" \\
  -d '{"config_json_string":"{\"port\":6982,\"number_of_threads\":1,\"engine_url\":\"http://localhost:8080\",\"engine_pool_size\":8}"}' \\
  http://localhost:6982/api/v1/iad/config
```

**Response:**

```json
{
  "message": "Configuration updated successfully"
}
```

## Configuration

Creates `/app/config/config.json`:

```json
{
  "port": 6982,
  "number_of_threads": 1,
  "connection_timeout": 60,
  "keep_alive_request_number": 0,
  "client_max_body_size": 100,
  "logger_level": "info",
  "logger_path": "/app/logs",
  "logger_rotation": "daily",
  "logger_max_files": 7,
  "auth_enabled": false,
  "auth_jwt_secret": "",
  "auth_accept_authorization_header": true,
  "auth_accept_api_key_header": true,
  "auth_api_key_header_name": "x-api-key",
  "engine_connection_timeout": 10000,
  "engine_request_timeout": 60000,
  "engine_max_retries": 3,
  "engine_retry_delay": 1000,
  "engine_verify_ssl": false,
  "engine_verbose": false,
  "engine_pool_size": 4,
  "engine_url": "http://localhost:8080"
}
```

### Key parameters

| Parameter                          | Default                 | Description                                               |
| ---------------------------------- | ----------------------- | --------------------------------------------------------- |
| `port`                             | 6982                    | Service listening port                                    |
| `number_of_threads`                | 1                       | Worker threads for request processing                     |
| `connection_timeout`               | 60                      | Rest::Manager connection Timeout                          |
| `keep_alive_request_number`        | 0                       | Maximum number of keep-alive requests                     |
| `client_max_body_size`             | 100                     | Maximum request body size in MB                           |
| `logger_level`                     | "info"                  | Log level (trace/debug/info/warn/error)                   |
| `auth_enabled`                     | false                   | Requires JWT authentication for protected endpoints       |
| `auth_jwt_secret`                  | ""                      | HS256 shared secret used to validate JWTs                 |
| `auth_accept_authorization_header` | true                    | Accepts `Authorization: Bearer <jwt>`                     |
| `auth_accept_api_key_header`       | true                    | Accepts JWT in the configured API key header              |
| `auth_api_key_header_name`         | "x-api-key"             | Header name used when API key token extraction is enabled |
| `engine_connection_timeout`        | 10000                   | Connection Timeout (ms)                                   |
| `engine_request_timeout`           | 60000                   | Request Timeout (ms)                                      |
| `engine_max_retries`               | 3                       | Engine retry attempts                                     |
| `engine_retry_delay`               | 1000                    | Delay between engine retries in ms                        |
| `engine_verify_ssl`                | false                   | Verifies capture analysis SSL certificates                |
| `engine_verbose`                   | false                   | Enables detailed capture analysis proxy logs              |
| `engine_pool_size`                 | 4                       | Connection pool size                                      |
| `engine_url`                       | `http://localhost:8080` | Base URL of the capture analysis runtime                  |

## Architecture overview

```mermaid
flowchart TD
    Client["Cliente<br/>Aplicación"]

      Client -->|HTTP/REST| IADService

      subgraph IADService["Facephi IAD Service"]
        Components["• License<br/>• Endpoints<br/>• Capture validation<br/>• Replay attack mitigation<br/>• Connection pool<br/>• Configuration management"]
      end

      style Client fill:#4a9eff,stroke:#333,stroke-width:2px,color:#000
      style IADService fill:#111111,stroke:#333,stroke-width:2px,color:#000
      style Components fill:#60a5fa,stroke:#333,stroke-width:2px,color:#000
```

## Support

For License inquiries or Technical Support, contact your Facephi representative.
