> ## Documentation Index
> Fetch the complete documentation index at: https://docs-platform.services-valid.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Implementação

> Inicie uma verificação de liveness com o LivenessIdentySDK Web e trate o resultado

Este guia mostra a API pública do `LivenessIdentySDK` Web e o fluxo completo de uma verificação no browser.

O bundle expõe `window.LivenessIdentySDK` com uma fábrica que cria a instância do SDK:

```javascript theme={"theme":"catppuccin-latte"}
const sdk = window.LivenessIdentySDK.createIdentySDK();
const result = await sdk.run(config); // config: LivenessConfig
```

`sdk.run(config)` orquestra o fluxo completo (sessão, captura, envio e análise) em uma única chamada e resolve com o `LivenessResult` da verificação.

## Como funciona

**1. Carregamento**

O script começa a se preparar assim que carrega na página.

**2. run()**

Estado `initializing`. O SDK chama o seu `onInit({ ssid })` para obter uma sessão.

**3. Sessão**

O seu backend cria a sessão (`POST /api/v1/sessions`) e devolve `{ sessionId, sessionToken }`.

**4. Captura**

Estado `capturing`: tela de instruções e câmera.

**5. Análise**

Estado `processing`: a tela de captura fecha e a captura é analisada no servidor (5 a 14 s).

**6. Resultado**

Estado `completed`, depois `onSuccess` / `onFailure` e a `Promise` do `run()`.

O que fica com você:

* **Criar a sessão** no seu backend, com a sua `x-api-key`.
* **Mostrar um loading** enquanto o servidor analisa a captura (estado `processing`).
* **Mostrar as mensagens** de sucesso e de falha ao usuário — veja [Solução de problemas](https://docs-platform.services-valid.com.br/plataforma/liveness/identy/sdk/web/troubleshooting.md).

## Configuração

```typescript theme={"theme":"catppuccin-latte"}
interface LivenessConfig {
  onInit: (params: { ssid?: string }) => Promise<{ sessionId: string; sessionToken: string }>;
  options?: LivenessOptions;
  onSuccess?: (result: LivenessResult) => void;
  onFailure?: (error: LivenessFailureError) => void;
  onProgress?: (state: 'initializing' | 'capturing' | 'processing' | 'completed') => void;
}
```

| Parâmetro | Tipo | Obrigatório | Descrição |
| - | - | - | - |
| `onInit` | `(params) => Promise<SessionTokens>` | Sim | Chama o seu backend para criar a sessão. Veja [Criando a sessão](#criando-a-sessão). |
| `options` | `LivenessOptions` | Não | Idioma, segurança, captura e visual. Veja [Customização](https://docs-platform.services-valid.com.br/plataforma/liveness/identy/sdk/web/customizacao.md). |
| `onSuccess` | `(result: LivenessResult) => void` | Não | Verificação aprovada. Veja [Resultado](#resultado). |
| `onFailure` | `(error: LivenessFailureError) => void` | Não | Verificação reprovada ou erro. Veja [Solução de problemas](https://docs-platform.services-valid.com.br/plataforma/liveness/identy/sdk/web/troubleshooting.md). |
| `onProgress` | `(state) => void` | Não | Mudanças de estado. Veja [Estados](#estados). |

Callbacks e `Promise` são equivalentes: use o estilo que preferir. `onSuccess` e `onFailure` são chamados **antes** de a `Promise` resolver ou rejeitar.

## Criando a sessão

A `x-api-key` **nunca** deve ir para o browser. O SDK chama o seu `onInit`, que pede a sessão ao seu backend e devolve à página apenas `sessionId` e `sessionToken`.

```typescript theme={"theme":"catppuccin-latte"}
interface SessionParams {
  ssid?: string; // identificador do dispositivo — repasse no POST /api/v1/sessions
}

interface SessionTokens {
  sessionId: string;
  sessionToken: string; // usado pelo SDK para enviar a captura; vale para uma captura
}
```

Se `onInit` rejeitar, ou não devolver os dois campos, o `run()` falha com `SESSION_FAILED`.

> [!NOTE]
>
> Nem sempre o SDK consegue obter o `ssid`. Repasse-o ao seu backend quando estiver presente; quando ausente, o serviço cria a sessão normalmente. Veja [Serviço](https://docs-platform.services-valid.com.br/plataforma/liveness/identy/servico.md#metadados-complementares).

## Estados

`onProgress` recebe o estado atual do fluxo:

| Estado | Quando |
| - | - |
| `initializing` | Início do `run()`: sessão sendo criada, câmera sendo preparada |
| `capturing` | Tela de captura aberta (instruções, câmera) |
| `processing` | A tela fechou e a captura está sendo analisada — **5 a 14 s**, sem nada na tela |
| `completed` | Resultado pronto, logo antes de `onSuccess`/`onFailure` |

> [!WARNING]
>
> O SDK **não** mostra loading durante `processing`. Mostre o seu (spinner, "Validando sua captura…") e esconda em `completed` ou no `finally` do `run()`.

## Fluxo de uso

**1. Crie a instância do SDK**

Você pode reaproveitar a instância em várias verificações, inclusive em novas tentativas.

```javascript theme={"theme":"catppuccin-latte"}
const sdk = window.LivenessIdentySDK.createIdentySDK();
```

**2. Implemente o onInit chamando o seu backend**

```javascript theme={"theme":"catppuccin-latte"}
async function onInit({ ssid }) {
  const r = await fetch('/api/create-session', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ssid }),
  });

  if (!r.ok) throw new Error(`Falha ao criar sessão: ${r.status}`);

  return r.json(); // { sessionId, sessionToken }
}
```

**3. Dispare a verificação**

```javascript theme={"theme":"catppuccin-latte"}
document.getElementById('iniciar-verificacao').addEventListener('click', async () => {
  try {
    const result = await sdk.run({
      onInit,
      options: { locale: 'pt-BR' },
      onProgress: (state) => {
        meuLoading.hidden = state !== 'processing';
      },
    });
    // aprovado: result.verified === true
    console.log('sessionId', result.sessionId);
  } catch (failure) {
    // reprovado ou erro: failure.type / failure.failureReason
    console.error(failure.type, failure.failureReason);
  } finally {
    meuLoading.hidden = true;
  }
});
```

**4. Trate o resultado**

Em caso de aprovação, use o `sessionId` para reconciliar a verificação no seu fluxo. Em caso de falha, mostre a mensagem adequada ao `type` e ofereça nova tentativa — veja [Solução de problemas](https://docs-platform.services-valid.com.br/plataforma/liveness/identy/sdk/web/troubleshooting.md).

### Tentando de novo

Chame `run()` de novo: cada chamada cria uma nova sessão (`onInit` é chamado outra vez). Não chame `run()` enquanto outro está em andamento na mesma instância — a segunda chamada falha com `INITIALIZATION_FAILED`.

## Resultado

Quando a verificação é aprovada, o SDK entrega o objeto abaixo via `onSuccess` e resolve a `Promise` do `run()` com ele:

```typescript theme={"theme":"catppuccin-latte"}
interface LivenessResult {
  sessionId: string;
  verified: true;
  image?: string;           // JPEG base64 da captura
  templates?: {             // só os formatos pedidos em requiredTemplates
    PNG?: string;
    ISO_19794_5?: string;
    ISO_39794_5?: string;
  };
  icao?: CaptureIcao;       // só com enableICAOChecks
  iso?: CaptureIso;         // só com enableICAOChecks
  processingTime: number;   // ms do início do run() ao resultado
}
```

```json theme={"theme":"catppuccin-latte"}
{ "sessionId": "…", "verified": true, "image": "/9j/4AAQ…", "processingTime": 8123 }
```

> [!WARNING]
>
> O resultado no browser serve à experiência do usuário. Quem controla o dispositivo pode alterá-lo — não use apenas ele para decisões críticas. Hoje não há uma rota para o seu backend consultar o resultado da sessão.

### ICAO e ISO

Disponíveis só com [`enableICAOChecks: true`](https://docs-platform.services-valid.com.br/plataforma/liveness/identy/sdk/web/customizacao#captura). São **informativos**: não alteram o `verified`. Use para orientar o usuário (luz, pose, oclusão) ou para exigir uma foto "de documento" no seu fluxo. Todos os campos são opcionais.

`icao` (`CaptureIcao`):

| Campo | Tipo | Significado |
| - | - | - |
| `isCompliant` | boolean | A foto está em conformidade ICAO |
| `multipleFaces` | boolean | Mais de um rosto na imagem |
| `eyesFullVisibility` | boolean | Olhos totalmente visíveis |
| `backgroundContinuity` | number | Uniformidade do fundo |
| `illuminationUniformity` | number | Uniformidade da iluminação no rosto |
| `overExposure` / `underExposure` | number | Super / subexposição |
| `noseVisibility` / `mouthVisibility` | number | Visibilidade do nariz / da boca |
| `topVisibility` / `bottomVisibility` | number | Rosto inteiro visível em cima / embaixo |
| `eyeLVisibility` / `eyeRVisibility` | number | Visibilidade do olho esquerdo / direito |
| `sideLVisibility` / `sideRVisibility` | number | Visibilidade da lateral esquerda / direita |

`iso` (`CaptureIso`) — scores de qualidade, todos `number`:

| Grupo | Campos |
| - | - |
| Geral | `unifiedQualityScore` |
| Fundo e luz | `backgroundUniformity`, `illuminationUniformity`, `luminanceMean`, `luminanceVariance`, `underExposurePrevention`, `overExposurePrevention`, `sharpness` |
| Rosto | `singleFacePresent`, `eyesOpen`, `mouthClosed`, `eyesVisible`, `mouthOcclusionPrevention`, `faceOcclusionPrevention`, `noHeadCoverings` |
| Enquadramento | `interEyeDistance`, `headSize`, `leftwardCropOfFaceInImage`, `rightwardCropOfFaceInImage`, `marginAboveTheFaceInImage`, `marginBelowTheFaceInImage` |
| Pose | `headPoseYaw`, `headPosePitch`, `headPoseRoll` |

## Outros métodos

| Membro | Descrição |
| - | - |
| `sdk.unload()` | Fecha a tela de captura se estiver aberta (ex.: o usuário saiu da página no meio). O `run()` em andamento termina com falha. |
| `LivenessIdentySDK.SDK_VERSION` | Versão do SDK. Informe-a ao reportar problemas. |

## Tipagem (TypeScript)

O SDK é carregado por `<script>`, então não vem com tipos. Se o seu projeto usa TypeScript, copie o arquivo abaixo (ex.: `src/types/liveness-sdk.d.ts`) — ele tipa `window.LivenessIdentySDK` com tudo o que esta documentação descreve.

```typescript liveness-sdk.d.ts theme={"theme":"catppuccin-latte"}
export {};

declare global {
  interface Window {
    LivenessIdentySDK: {
      SDK_VERSION: string;
      createIdentySDK(): LivenessSDK;
    };
  }

  interface LivenessSDK {
    run(config: LivenessConfig): Promise<LivenessResult>;
    unload(): Promise<void>;
  }

  interface LivenessConfig {
    onInit: (params: { ssid?: string }) => Promise<{ sessionId: string; sessionToken: string }>;
    options?: LivenessOptions;
    onSuccess?: (result: LivenessResult) => void;
    onFailure?: (error: LivenessFailureError) => void;
    onProgress?: (state: "initializing" | "capturing" | "processing" | "completed") => void;
  }

  type LivenessLevel =
    | "HIGHEST" | "VERY_HIGH" | "BALANCED_VERY_HIGH" | "HIGH"
    | "BALANCED_HIGH" | "MODERATE" | "MEDIUM" | "LOW";

  interface LivenessOptions {
    locale?: "pt-BR" | "en-US";
    strings?: Record<string, string>;
    enableAS?: boolean;
    asThreshold?: LivenessLevel;
    enableDF?: boolean;
    dfThreshold?: LivenessLevel;
    showCaptureTraining?: boolean;
    captureTimeout?: number;
    enableRetakeScreen?: boolean;
    allowClose?: boolean;
    assisted?: boolean;
    requiredTemplates?: ("PNG" | "ISO_19794_5" | "ISO_39794_5")[];
    enableICAOChecks?: boolean;
    precaptureCheck?: boolean;
    precaptureOptions?: Partial<Record<
      "GLASSES" | "SUNGLASSES" | "HAT" | "MASK" | "HAND" | "EYE_OPENNESS" | "MOUTH_CLOSURE",
      boolean
    >>;
    appUI?: "STANDARD" | "TICKING";
    enableEyesStatusDetector?: boolean;
    allowCameraSelect?: boolean;
    showOrientationDialog?: boolean;
    showResults?: boolean;
    silentInit?: boolean;
    enableBackgroundRemoval?: boolean;
    backgroundColor?: string;
    sessionData?: string;
    allowUnknownBrowsers?: { name: string; version: number; osVersion?: number }[];
    htmlTemplates?: {
      ROTATION_INCORRECT_DIALOG?: string;
      CAPTURE_TIMEOUT_DIALOG?: string;
    };
    graphics?: {
      canvas?: {
        canvasBackground?: string;
        canvasBackgroundAssisted?: string;
        labelBackground?: string;
        ovalBorderBackground?: string;
        ovalBorderErrorBackground?: string;
        tickerDefaultBackground?: string;
        tickerActiveBackground?: string;
      };
      FACE_TRAINING?: string;
    };
    events?: {
      onBusy?: () => void;
      onIdle?: () => void;
      onImageQualityDetected?: (quality: unknown) => void;
      onCaptured?: (base64: string) => void;
      onStatusChanged?: (status: unknown) => void;
      onOrientationChanged?: (...args: unknown[]) => void;
      onBeforeTrainingDialogClose?: (...args: unknown[]) => void;
      showCustomTrainingDialog?: (...args: unknown[]) => void;
      onInputDevicesDetected?: (devices: MediaDeviceInfo[]) => Promise<string>;
    };
  }

  interface LivenessResult {
    sessionId: string;
    verified: true;
    image?: string;
    templates?: { PNG?: string; ISO_19794_5?: string; ISO_39794_5?: string };
    icao?: Record<string, boolean | number>;
    iso?: Record<string, number>;
    processingTime: number;
  }

  interface LivenessFailureError {
    sessionId?: string;
    verified: false;
    type:
      | "LIVENESS_FAILED" | "USER_CANCELLED" | "CAPTURE_TIMEOUT" | "CAPTURE_FAILED"
      | "CAMERA_PERMISSION_DENIED" | "CAMERA_NOT_FOUND" | "BROWSER_NOT_SUPPORTED"
      | "SESSION_FAILED" | "NETWORK_ERROR" | "SUBMISSION_FAILED"
      | "INITIALIZATION_FAILED" | "UNKNOWN_ERROR";
    failureReason?: string;
    nativeCode?: number;
    nativeType?: string;
  }
}
```

Os campos de `icao` e `iso` estão em [ICAO e ISO](#icao-e-iso); tipe-os em detalhe se for usá-los.

## Exemplo completo

```html theme={"theme":"catppuccin-latte"}
<!doctype html>
<html lang="pt-BR">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Identy Demo</title>
    <script src="https://cdn.hub-liveness-service.app/identy/v7/latest/prd/identy-sdk.js"></script>
  </head>
  <body>
    <button id="iniciar">Iniciar Verificação</button>
    <p id="loading" hidden>Validando sua captura…</p>
    <pre id="resultado"></pre>

    <script>
      const sdk = window.LivenessIdentySDK.createIdentySDK();
      const loadingEl = document.getElementById('loading');
      const resultadoEl = document.getElementById('resultado');

      async function onInit({ ssid }) {
        const r = await fetch('/api/create-session', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ ssid }),
        });
        if (!r.ok) throw new Error(`Sessão falhou: ${r.status}`);
        return r.json();
      }

      document.getElementById('iniciar').addEventListener('click', () => {
        resultadoEl.textContent = '';
        sdk
          .run({
            onInit,
            options: { locale: 'pt-BR' },
            onProgress: (state) => {
              loadingEl.hidden = state !== 'processing';
            },
            onSuccess: (result) => {
              resultadoEl.textContent = `Aprovado — sessão ${result.sessionId}`;
            },
            onFailure: (error) => {
              resultadoEl.textContent = `Não aprovado: ${error.type} ${error.failureReason ?? ''}`;
            },
          })
          .catch(() => {}) // falha já tratada no onFailure
          .finally(() => {
            loadingEl.hidden = true;
          });
      });
    </script>
  </body>
</html>
```

## Próximos passos

> **[Customização](https://docs-platform.services-valid.com.br/plataforma/liveness/identy/sdk/web/customizacao.md)**
>
> Idioma, segurança, captura e visual da tela

> **[Solução de problemas](https://docs-platform.services-valid.com.br/plataforma/liveness/identy/sdk/web/troubleshooting.md)**
>
> Mapeamento de erros e diagnóstico


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.