> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gu1.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Eventos webhook de sesión biométrica

> Payloads de eventos webhook para sesiones biométricas embebidas en gu1, con eventos a nivel organización y webhookUrl configurable por solicitud.

## Resumen

Las sesiones biométricas embebidas las **gestiona Gu1 de punta a punta**. Cuando el usuario termina la captura en la UI hospedada, Gu1 persiste la sesión, aplica las políticas de tu organización (umbrales de face match, cruces entre entidades, billing) y envía webhooks con el **resultado de la sesión**.

Tu integración debe usar **`payload.status`** como veredicto biométrico — el mismo campo que devuelve `GET /api/kyc/biometric/sessions/:id`.

Dos canales de entrega:

1. **Webhooks de organización** — suscribite a `biometric.session_*` en [configuración de webhooks](/es/webhooks/configuration) (todas las transiciones de estado).
2. **`webhookUrl` por request** — URL HTTPS opcional en `POST /api/kyc/biometric/sessions`; Gu1 hace POST en **resultados terminales de captura** (`approved`, `rejected`, `abandoned`, `expired`). Un `cancel` manual por API solo dispara webhooks de organización.

## Tipos de evento

| Evento                          | Cuándo                                                   |
| ------------------------------- | -------------------------------------------------------- |
| `biometric.session_created`     | Sesión creada (`status: pending`)                        |
| `biometric.session_in_progress` | El usuario inició la captura en la UI hospedada          |
| `biometric.session_approved`    | Sesión biométrica **aprobada** por Gu1                   |
| `biometric.session_rejected`    | Sesión biométrica **rechazada** por Gu1                  |
| `biometric.session_abandoned`   | El usuario abandonó el flujo sin terminar                |
| `biometric.session_cancelled`   | Sesión cancelada en Gu1 (solo `pending` / `in_progress`) |
| `biometric.session_expired`     | Sesión expirada                                          |

## Sobre el payload

Misma envoltura externa que [eventos KYC](/es/webhooks/events/kyc-events):

```json theme={null}
{
  "event": "biometric.session_approved",
  "timestamp": "2026-06-11T15:00:00Z",
  "organizationId": "org-uuid",
  "payload": { }
}
```

El **`payload`** interno es la fila de sesión biométrica en Gu1 (misma forma que la API REST).

### Campos del payload

* **`payload.status`** — Estado de la sesión: `pending`, `in_progress`, `approved`, `rejected`, `abandoned`, `cancelled`, `expired`.
* **`payload.rejectionCode`** / **`payload.rejectionMessage`** — Cuando `status` es `rejected` (p. ej. `FACE_MATCH_SCORE_LOW`, `CROSS_ENTITY`, `CAPTURE_DECLINED`).
* **`payload.mode`** — `face_match` (liveness + comparación con retrato del KYC).
* **`payload.sessionUrl`** — URL de captura mientras la sesión está activa.
* **`payload.decision`** — Detalle técnico de la captura (scores, claves de media). Imágenes vía `GET /api/kyc/biometric/sessions/:id/media?key=`.
* **`payload.entity`** — Snapshot de la entidad persona (`id`, `externalId`, `name`, `type`).

## Ejemplo: sesión creada

```json theme={null}
{
  "event": "biometric.session_created",
  "timestamp": "2026-06-11T14:00:00Z",
  "organizationId": "org-uuid",
  "payload": {
    "id": "bio-session-uuid",
    "entityId": "entity-uuid",
    "status": "pending",
    "mode": "face_match",
    "sessionUrl": "https://verify.example.com/session/abc",
    "hostedSessionId": "hosted-session-id",
    "rejectionCode": null,
    "rejectionMessage": null,
    "createdAt": "2026-06-11T14:00:00.000Z",
    "entity": {
      "id": "entity-uuid",
      "externalId": "cliente-123",
      "name": "Jane Doe",
      "type": "person"
    }
  }
}
```

## Ejemplo: en progreso

```json theme={null}
{
  "event": "biometric.session_in_progress",
  "timestamp": "2026-06-11T14:05:00Z",
  "organizationId": "org-uuid",
  "payload": {
    "id": "bio-session-uuid",
    "entityId": "entity-uuid",
    "status": "in_progress",
    "mode": "face_match",
    "sessionUrl": "https://verify.example.com/session/abc",
    "rejectionCode": null
  }
}
```

## Ejemplo: aprobada

```json theme={null}
{
  "event": "biometric.session_approved",
  "timestamp": "2026-06-11T14:10:00Z",
  "organizationId": "org-uuid",
  "payload": {
    "id": "bio-session-uuid",
    "entityId": "entity-uuid",
    "status": "approved",
    "mode": "face_match",
    "rejectionCode": null,
    "completedAt": "2026-06-11T14:10:00.000Z",
    "decision": {
      "face_match": { "status": "Approved", "score": 99.2 },
      "liveness": { "status": "Approved", "score": 98.5 }
    },
    "entity": {
      "id": "entity-uuid",
      "externalId": "cliente-123",
      "name": "Jane Doe",
      "type": "person"
    }
  }
}
```

## Ejemplo: rechazada

```json theme={null}
{
  "event": "biometric.session_rejected",
  "timestamp": "2026-06-11T14:12:00Z",
  "organizationId": "org-uuid",
  "payload": {
    "id": "bio-session-uuid",
    "entityId": "entity-uuid",
    "status": "rejected",
    "mode": "face_match",
    "rejectionCode": "CROSS_ENTITY",
    "rejectionMessage": "Biometric match corresponds to a different entity in this organization",
    "completedAt": "2026-06-11T14:12:00.000Z",
    "entity": {
      "id": "entity-uuid",
      "externalId": "cliente-123",
      "name": "Jane Doe",
      "type": "person"
    }
  }
}
```

### Códigos frecuentes de `rejectionCode`

| Código                 | Significado                                              |
| ---------------------- | -------------------------------------------------------- |
| `FACE_MATCH_SCORE_LOW` | Score de face match por debajo del umbral (`face_match`) |
| `CROSS_ENTITY`         | La captura coincide con otra entidad de la organización  |
| `CAPTURE_DECLINED`     | Captura rechazada en el flujo hospedado                  |

## `webhookUrl` por request

* Mismo `event` y forma de `payload` que los webhooks de organización.
* Firma HMAC en `X-Webhook-Signature` con el webhook secret KYC configurado.
* Headers adicionales: `X-Webhook-Event`, `X-Webhook-ID`, `X-Webhook-Timestamp`.

Ver [verificación de firma](/es/webhooks/configuration#signature-verification).

<Note>
  El cancel manual (`POST /api/kyc/biometric/sessions/:id/cancel`) emite `biometric.session_cancelled` solo en webhooks de **organización**; no hace POST al `webhookUrl` del request.
</Note>
