> ## 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

> Inicialize o LivenessFacetecSDK Web v10 e dispare uma verificação de liveness FaceTec

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

O bundle expõe `window.LivenessFacetecSDK` com uma fábrica que cria a instância do SDK. A única interface que você precisa conhecer é a `FaceTecSDKConfig` — o objeto de configuração que você passa para executar uma verificação.

```javascript theme={"theme":"catppuccin-latte"}
const sdk = window.LivenessFacetecSDK.createFaceTecSDK();
const result = await sdk.run(config); // config: FaceTecSDKConfig
```

`sdk.run(config)` orquestra o fluxo completo (inicialização, captura, submissão e limpeza) em uma única chamada e resolve com o `LivenessResult` da verificação. Não há um elemento de montagem — a captura abre como camada full-screen sobre a página.

## Configuração

```typescript theme={"theme":"catppuccin-latte"}
interface FaceTecSDKConfig {
  onInit: (params: SessionParams) => Promise<SessionTokens>;
  backendBaseUrl?: string;
  env?: 'production' | 'development' | 'homolog';
  options?: FaceTecOptionsInput;
  onSuccess?: (result: LivenessResult) => void;
  onFailure?: (error: LivenessFailureError) => void;
  onProgress?: (state: HubState) => void;
}
```

| Parâmetro        | Tipo                                         | Obrigatório | Descrição                                                                                                                                                                                                      |
| ---------------- | -------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onInit`         | `(params) => Promise<SessionTokens>`         | Sim         | Callback que **seu código** implementa: chama o seu backend, que chama o serviço FaceTec, e devolve `sessionId` e `sessionToken`.                                                                              |
| `backendBaseUrl` | `string`                                     | Não         | Substitui a URL de backend embutida no bundle. Use apenas em desenvolvimento local, apontando para um proxy próprio.                                                                                           |
| `env`            | `'production' \| 'development' \| 'homolog'` | Não         | Controla apenas o envio de diagnósticos (Sentry) — **não** seleciona qual backend o SDK usa. O backend já é fixo no bundle carregado (veja [Instalação](/plataforma/liveness/facetec/v10/sdk/web/instalacao)). |
| `options`        | `FaceTecOptionsInput`                        | Não         | Idioma, textos e customização visual. Veja [Customização](/plataforma/liveness/facetec/v10/sdk/web/customizacao).                                                                                              |
| `onSuccess`      | `(result) => void`                           | Não         | Disparado quando a captura termina (mesmo quando `verified = false` — é um resultado biométrico, não um erro técnico).                                                                                         |
| `onFailure`      | `(error) => void`                            | Não         | Disparado quando o fluxo técnico falha. Veja [Solução de problemas](/plataforma/liveness/facetec/v10/sdk/web/troubleshooting).                                                                                 |
| `onProgress`     | `(state) => void`                            | Não         | Recebe transições de estado (`Uninitialized`, `Initializing`, `Ready`, `Capturing`, `Processing`, `Closing`).                                                                                                  |

## Como o `onInit` funciona

O SDK chama `onInit` **antes** de abrir a captura, passando metadados de dispositivo coletados pelo Shield Web SDK:

```typescript theme={"theme":"catppuccin-latte"}
interface SessionParams {
  ssid?: string;
}
```

Você repassa esse metadado ao seu backend e devolve ao SDK os dois tokens da sessão:

```typescript theme={"theme":"catppuccin-latte"}
interface SessionTokens {
  sessionId: string;
  sessionToken: string;
}
```

<Info>
  Nem sempre o SDK consegue obter o `ssid` — depende de conectividade e do ambiente de execução. Repasse-o ao seu backend quando estiver presente; quando ausente, o serviço cria a sessão normalmente. Veja [Serviço](/plataforma/liveness/facetec/v10/servico#metadados-complementares).
</Info>

<Info>
  Não existe mais `maxAttempts` nem uma segunda tela de retry dentro da mesma sessão. Para tentar de novo após uma falha, chame `sdk.run()` outra vez — isso reaproveita a instância já inicializada e cria uma sessão nova automaticamente.
</Info>

## Fluxo de uso

<Steps>
  <Step title="Crie a instância do SDK">
    Logo após o bundle ser carregado, crie a instância. Você pode reaproveitá-la em múltiplas capturas — inclusive em retries.

    ```javascript theme={"theme":"catppuccin-latte"}
    const sdk = window.LivenessFacetecSDK.createFaceTecSDK();
    ```
  </Step>

  <Step title="Implemente o onInit chamando o seu backend">
    O `onInit` é um `async` que devolve `{ sessionId, sessionToken }`. Encaminhe os `sessionParams` recebidos para o seu endpoint:

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

      if (!r.ok) {
        const err = await r.json().catch(() => ({}));
        throw new Error(`Falha ao criar sessão: ${r.status} ${err.error?.message ?? ''}`);
      }

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

  <Step title="Dispare a verificação">
    ```javascript theme={"theme":"catppuccin-latte"}
    document.getElementById('iniciar-verificacao').addEventListener('click', async () => {
      try {
        const result = await sdk.run({
          onInit,
          onSuccess: (data) => console.log('verificado', data),
          onFailure: (error) => console.error('falhou', error.type, error.failureReason),
          onProgress: (state) => console.log('estado', state),
        });

        // result === o mesmo objeto entregue ao onSuccess
        console.log('sessionId', result.sessionId);
      } catch (err) {
        // Erros inesperados não cobertos por onFailure
        console.error('erro inesperado', err);
      }
    });
    ```
  </Step>

  <Step title="Trate o resultado">
    Use `sessionId` para reconciliar a captura no seu backend. Se `verified === false`, exiba mensagem ao usuário e ofereça nova tentativa (chamando `sdk.run()` de novo) — não é um erro técnico, é uma reprovação biométrica.
  </Step>
</Steps>

## Campos de `LivenessResult`

Quando a captura termina com sucesso, o SDK emite o objeto abaixo via `onSuccess` (e também resolve a Promise de `run` com ele):

```typescript theme={"theme":"catppuccin-latte"}
interface LivenessResult {
  sessionId: string;
  verified: boolean;
  processingTime: number;
  base64Image?: string;
  ageGroup?: number;
}
```

| Campo            | Tipo      | Descrição                                                       |
| ---------------- | --------- | --------------------------------------------------------------- |
| `sessionId`      | `string`  | ID da sessão criada pelo serviço.                               |
| `verified`       | `boolean` | Resultado consolidado — `true` quando o liveness foi aprovado.  |
| `processingTime` | `number`  | Tempo total de processamento em milissegundos.                  |
| `base64Image`    | `string?` | Imagem da captura, quando disponível.                           |
| `ageGroup`       | `number?` | Estimativa de faixa etária, quando o FaceTec retorna esse dado. |

## Outros métodos do SDK

```typescript theme={"theme":"catppuccin-latte"}
interface FaceTecSDKInterface {
  run(config: FaceTecSDKConfig): Promise<LivenessResult>;
  unload(): Promise<void>;
  isLockedOut(): boolean | undefined;
  getLockoutEndTime(): number | null | undefined;
}
```

| Método                | Descrição                                                                                                                                                                                                                                  |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `isLockedOut()`       | `true`/`false` indicam o estado de bloqueio do dispositivo. `undefined` significa que o motor FaceTec ainda não carregou — não interprete como "não bloqueado".                                                                            |
| `getLockoutEndTime()` | Timestamp (ms) de quando o bloqueio termina. `null` = não bloqueado, `undefined` = motor ainda não carregado.                                                                                                                              |
| `unload()`            | Libera a instância do motor FaceTec e limpa o cache interno. Não é obrigatório chamar (um reload de página também libera tudo) — útil em SPAs ao desmontar a rota que usa o SDK. Uma nova chamada a `run()` reinicializa tudo normalmente. |

## Preload

```typescript theme={"theme":"catppuccin-latte"}
window.LivenessFacetecSDK.preload(): Promise<void>
```

`preload()` é uma função independente (não é um método da instância criada por `createFaceTecSDK()`) que busca antecipadamente tudo o que `run()` vai precisar: o script vendor do FaceTec e a inicialização do Shield, em paralelo. Nenhum dos dois depende de sessão — por isso pode rodar bem antes de qualquer captura começar.

<Info>
  **Você normalmente não precisa chamar isso.** O próprio bundle já executa `preload()` automaticamente assim que o `<script>` termina de carregar.
</Info>

Chame manualmente apenas se você carrega o `<script>` do SDK de forma tardia (ex.: injetado dinamicamente só quando o usuário chega perto da etapa de verificação) e quer adiantar o carregamento do motor FaceTec para antes disso — por exemplo, assim que o usuário entra em uma tela anterior do seu fluxo:

```javascript theme={"theme":"catppuccin-latte"}
// Em uma etapa anterior à verificação, assim que o SDK estiver disponível:
window.LivenessFacetecSDK.preload();
```

É seguro chamar mais de uma vez (as buscas internas são cacheadas/idempotentes) e seguro ignorar a Promise retornada.

## 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>FaceTec Demo</title>
    <script src="https://cdn.hub-liveness-service.app/facetec/v10/latest/prd/facetec-sdk.js"></script>
  </head>
  <body>
    <button id="iniciar">Iniciar Verificação</button>
    <pre id="resultado"></pre>

    <script>
      const sdk = window.LivenessFacetecSDK.createFaceTecSDK();
      const resultadoEl = document.getElementById('resultado');

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

      document.getElementById('iniciar').addEventListener('click', async () => {
        resultadoEl.textContent = 'Processando…';
        try {
          await sdk.run({
            env: 'production',
            onInit,
            onSuccess: (data) => {
              resultadoEl.textContent = JSON.stringify(data, null, 2);
            },
            onFailure: (error) => {
              resultadoEl.textContent = `Falhou: ${error.type} — ${error.failureReason ?? ''}`;
            },
          });
        } catch (err) {
          resultadoEl.textContent = `Erro: ${err.message}`;
        }
      });
    </script>
  </body>
</html>
```

## Próximos passos

<CardGroup cols={2}>
  <Card title="Customização" icon="palette" iconType="regular" href="/plataforma/liveness/facetec/v10/sdk/web/customizacao">
    Locales, textos e tema visual da UI
  </Card>

  <Card title="Solução de problemas" icon="wrench" iconType="regular" href="/plataforma/liveness/facetec/v10/sdk/web/troubleshooting">
    Mapeamento de erros e diagnóstico
  </Card>
</CardGroup>
