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

# Guía de integración KYB: arquitectura y patrones

> Integración KYB de Didit lista para producción: arquitectura, sesiones, flujos alojados, webhooks, polling y decisiones. Desde $2.00 por verificación.



Prompt de integración KYB
        Copiar el prompt al portapapeles



      
      

\<pre>

\````# Goal — ship a production-ready KYB (business verification) integration

KYB runs through the same `/v3/session/` endpoint as KYC. The session's workflow determines whether it's a KYC or KYB session — pass a KYB workflow id and Didit creates a business session automatically (`session_kind: "business"`).

\## End-to-end flow

\```
You: POST /v3/session/ (KYB workflow_id, vendor_data) → session_id, url, session_token
You: deliver url to the business contact (email / your UI / iframe)
Biz: completes the hosted flow (registry confirm → Key People → documents → AML)
Didit → Webhook: status.updated with session_kind: "business"
You: GET /v3/session/{session_id}/decision/ → full KYB decision
You: branch on decision.status ("Approved" / "Declined" / "In Review" / "Resubmitted")
\```

\## Create a KYB session

\```bash
curl -X POST https://verification.didit.me/v3/session/ \
-H "x-api-key: $DIDIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflow_id": "$KYB_WORKFLOW_ID",
"vendor_data": "biz-acme",
"callback": "https://myapp.com/kyb/return",
"metadata": {"plan": "growth", "country": "GBR"}
}'
\```

Recommended fields:

\- `workflow_id` — references your KYB workflow.
\- `vendor_data` — your business id; binds the session to a [Business entity](/entities/businesses/overview).
\- `callback` — where to redirect the user after completion.
\- `metadata` — JSON attached to the session for your own reporting.

\## Webhook events for KYB

\| Event | Trigger |
\|---|---|
\| `status.updated` (with `session_kind === "business"`) | KYB session status changed. Follow this event for progress. |
\| `data.updated` (with `session_kind === "business"`) | A reviewer edited registry data or Key People in the console, or the registry reported a change (registry monitoring). Not sent for document uploads or Key People submissions. |
\| `business.status.updated` | Linked Business entity status changed |
\| `business.data.updated` | Linked Business entity profile / counters changed |

Subscribe via `POST /v3/webhook/destinations/` with `webhook_version: "v3"`. Verify the `X-Signature-V2` header (HMAC-SHA256 of canonical JSON). De-dupe on `event_id`. Respond within 5 seconds.

\## KYB decision shape (V3 plural arrays)

\```bash
curl https://verification.didit.me/v3/session/$SESSION_ID/decision/ \
-H "x-api-key: $DIDIT_API_KEY"
\```

Key V3 arrays you'll iterate:

\| Array | Holds |
\|---|---|
\| `key_people_checks[]` | UBOs, shareholders, directors, officers — bucketed into `registry` (from the registry lookup) and `submitted` (what the business confirmed). Plus a `ubo_kyc_summary` rollup. |
\| `document_verifications[]` | Each item has `status`, `node_id`, `items[]` (signed `file_url` + OCR extract), `groups`, `required_groups`. |
\| `aml_screenings[]` | Company AML and per-person AML hits. |

The KYB-specific features are `KYB_REGISTRY`, `AML`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE`. Statuses are the exact labels `"Not Finished"`, `"Approved"`, `"Declined"`, `"In Review"`, `"Resub Requested"`.

\## Apply-decision logic

\```ts
switch (decision.status) {
case "Approved":   await onboardBusiness(decision); break;
case "Declined":   await logRejection(collectWarnings(decision), decision); break; // warnings[] tags on each feature array
case "In Review":  await markPending(decision); break; // wait for next webhook
case "Resubmitted":await notifyBusiness(decision); break; // business needs to re-upload
case "Awaiting User": await pingChildPersonForKyc(decision); break; // child Key People KYC pending
}
\```

See /business-verification/statuses for the full state machine.

\## Resubmission flow

When a session transitions to `Resubmitted` (or a feature to `Resub Requested`, or a feature is marked for resubmission), re-deliver the same `url` — the hosted flow resumes at the resubmission step. To re-verify a specific Key Person, resubmit that person's child KYC session; the parent `kyb_key_people` re-aggregates automatically.

\## Key People child KYC

If your KYB workflow has KYC required for some roles, each person triggers a child KYC session automatically. While any child is in progress, the parent's `kyb_key_people` status is `Awaiting User`. Configure per-role required/skippable behaviour at *Workflows → [KYB workflow] → Key People*. A child session expires after the session expiration time of the KYC workflow its role is mapped to, not the KYB session's. A party whose session was deleted, or whose link expired before the person started it, is reissued with `POST /v3/session/{session_id}/kyb/parties/{party_uuid}/regenerate/`.

\## Failure modes

\| Scenario | Response |
\|---|---|
\| Invalid `workflow_id` | `400 Bad Request` |
\| Wrong workflow type (KYC instead of KYB) | Session is created but runs KYC steps — verify the workflow's `workflow_type` is `"kyb"` |
\| Duplicate `vendor_data` | A new session is created — that's by design for re-KYB |
\| Company country outside the workflow's allowed countries | The registry check raises the `KYB_COUNTRY_RESTRICTED` warning |
\| Registry provider outage during company search | `502` with `code: "kyb_registry_provider_unavailable"`. Not billed. In Didit's hosted flow, the business is automatically offered manual company entry instead of a retry-only error. |
\| Rate limit | `429` with `Retry-After` header |

\## Sources of truth

\- /sessions-api/create-session — request body schema
\- /business-verification/response-schema — KYB decision payload
\- /business-verification/statuses — feature state machine
\- /business-verification/webhooks — KYB-specific event catalog
\- /entities/businesses/data-model — Business entity schema
\- /integration/integration-prompt — canonical end-to-end prompt````

\</pre>



      
      

Pegar en

Esta guía complementa la [guía de inicio rápido](https://docs.didit.me/es/business-verification/quickstart.md). Cubre la arquitectura, cada decisión de integración y los patrones operativos que hacen que KYB sea fiable en producción.## Arquitectura```mermaid theme={null}
sequenceDiagram
    participant You as Your platform
    participant Didit as Didit API
    participant Biz as Business contact
    participant Webhook as Your webhook endpoint

    You->>Didit: POST /v3/session/ (workflow_id, vendor_data)
    Didit-->>You: session_id, url, token
    You->>Biz: Deliver hosted verification URL (your email/flow)
    Biz->>Didit: Completes KYB hosted flow
    Didit->>Didit: Registry lookup, AML screening, OCR
    Didit->>Webhook: status.updated (session_kind: business)
    You->>Didit: GET /v3/session/{id}/decision/
    Didit-->>You: Full KYB decision payload
    You->>You: Onboard / reject / escalate based on status
```## AutenticaciónTodas las solicitudes requieren el encabezado `x-api-key` con la clave de API de tu aplicación. Consulta [Autenticación de la API](https://docs.didit.me/es/getting-started/api-authentication.md) para la rotación de claves, la separación de entornos y los permisos.## Creación de sesionesUn único endpoint: `POST /v3/session/`. El tipo del flujo de verificación (workflow) determina si la sesión es KYC o KYB, así que no hace falta ningún indicador explícito de "empresa".**Campos recomendados al crear la sesión:**| Campo | Propósito |
| - | - |
| `workflow_id` | Obligatorio: hace referencia a tu flujo KYB. |
| `vendor_data` | Tu identificador de la empresa. Vincula la sesión a una [entidad empresarial](https://docs.didit.me/es/entities/businesses/overview.md). |
| `callback_url` | Opcional: adónde redirigir al usuario al finalizar. |
| `expected_details` | Opcional: `{ company_name, registry_country, registration_number }`. Rellena de antemano la búsqueda en el registro de empresas: el país de constitución queda preseleccionado y bloqueado (`registry_country` como `XX`, o `XX-YY` para registros estatales, p. ej. `US-CA`), los campos de nombre de la empresa y número de registro se rellenan de antemano y la búsqueda con los datos proporcionados se ejecuta automáticamente, combinando ambos identificadores cuando están presentes los dos. Solo se rellenan previamente los campos: las discrepancias no generan advertencias. |
| `metadata` | JSON opcional asociado a la sesión. |Esquema completo: [crear sesión](https://docs.didit.me/es/sessions-api/create-session.md).## Entrega del enlace alojadoEl `url` de la respuesta es un enlace de verificación alojado. Opciones de entrega:- Envíalo por correo electrónico desde tu propia plataforma.
- Insértalo como enlace en tu interfaz de onboarding.
- Ábrelo en un webview dentro de la aplicación (iOS / Android / React Native).Puedes **personalizar** la experiencia alojada (logotipo, color, dominio, plantillas de correo electrónico) mediante [Marca blanca](https://docs.didit.me/es/console/white-label.md).## Polling frente a webhooksLos webhooks son el patrón recomendado. Didit envía mediante POST los eventos de finalización a tu endpoint suscrito en cuanto termina el procesamiento.El polling se admite durante el desarrollo o cuando tu endpoint de webhook no es accesible:* Consulta `GET /v3/session/{id}/decision/` con backoff exponencial (cada 10 s al principio, hasta 60 s).
* Deja de consultar cuando `status` sea `"Approved"`, `"Declined"` o `"In Review"`.> [!WARNING]
>
> Consultar con mucha frecuencia puede superar los [límites de solicitudes](https://docs.didit.me/es/integration/rate-limiting.md). En producción, prefiere siempre los webhooks.## Gestión de webhooksSuscríbete a los eventos que te interesen. Los mismos eventos cubren KYC y KYB, con `session_kind: "business"` dentro del payload para identificar los eventos de sesiones de empresa:- `status.updated`: cambió el estado de la sesión. Filtra por `session_kind === "business"` para las sesiones KYB.
- `data.updated`: un revisor editó los datos del registro o las personas clave en la consola, o el registro notificó un cambio. No se envía cuando el solicitante sube un documento o envía las personas clave: para eso, usa `status.updated`. Se aplica el mismo filtro de `session_kind`.
- `business.status.updated` / `business.data.updated`: cambió la [entidad de empresa](https://docs.didit.me/es/entities/businesses/overview.md) vinculada.Catálogo completo de eventos: [webhooks de KYB](https://docs.didit.me/es/business-verification/webhooks.md). Verificación de firma y semántica de reintentos: [referencia de webhooks](https://docs.didit.me/es/integration/webhooks.md).## Gestión de las decisiones```typescript theme={null}
switch (decision.status) {
  case 'Approved':
    await onboardBusiness(decision);
    break;
  case 'Declined':
    // The KYB decision has no single reason code: collectWarnings is your helper
    // that flattens warnings[] from registry_checks, document_verifications,
    // key_people_checks and aml_screenings
    await logRejection(collectWarnings(decision), decision);
    break;
  case 'In Review':
    // Wait for analyst decision — another webhook will fire
    await markPending(decision);
    break;
  case 'Resubmitted':
    // The business was asked to re-upload a document
    await notifyBusiness(decision);
    break;
}
```Consulta [Estados de KYB](https://docs.didit.me/es/business-verification/statuses.md) para la máquina de estados completa y [Advertencias de KYB](https://docs.didit.me/es/business-verification/warnings.md) para las etiquetas que explican una decisión.## Flujo de reenvíoCuando una sesión de Verificación de empresas (KYB) pasa a `Resubmitted` (o una función se marca para reenvío), la empresa debe subir datos corregidos o adicionales.Puedes:- **Volver a enviar** el mismo `url`: el flujo alojado retoma el punto en que se necesita el reenvío.
- **Reemitir el enlace inactivo de una persona clave**: una persona cuya sesión KYC asociada se eliminó, o expiró antes de que la persona la iniciara, recibe una nueva sesión con [Regenerar la sesión KYC de personas clave](https://docs.didit.me/es/sessions-api/regenerate-kyb-party.md).
- **Abrir un [caso](https://docs.didit.me/es/transaction-monitoring/cases.md)** en la Business Console para hacer seguimiento interno de los intercambios.## Ejecuta los pasos desde tu propio front endLos pasos de documentos y de personas clave también se pueden controlar desde tu servidor con tu clave de API, de modo que tú conservas la interfaz de usuario y Didit se encarga de la verificación y de la decisión.
Cada llamada está limitada a la sesión KYB, necesita el permiso `write:businesses` (leer las partes extraídas también acepta `read:businesses` o `read:sessions`) y ejecuta las mismas comprobaciones, la misma facturación y la misma transición entre pasos que la página alojada.1) [Sube los documentos corporativos](https://docs.didit.me/es/sessions-api/kyb-upload-documents.md) mientras la sesión está en el paso de documentos KYB.
2) [Lee las partes que se mencionan en los documentos](https://docs.didit.me/es/sessions-api/kyb-extracted-parties.md), incluidos los accionistas y los porcentajes de propiedad, y muéstraselas a tu solicitante.
3) [Crea](https://docs.didit.me/es/sessions-api/kyb-create-party-draft.md), [edita](https://docs.didit.me/es/sessions-api/kyb-update-party-draft.md) y [elimina](https://docs.didit.me/es/sessions-api/kyb-delete-party-draft.md) [borradores de partes](https://docs.didit.me/es/sessions-api/kyb-list-party-drafts.md). Un borrador no se considera declarado y no cuesta nada.
4) [Envía los borradores](https://docs.didit.me/es/sessions-api/kyb-submit-parties.md). Didit decide qué partes deben verificarse, crea una sesión KYC para cada una y devuelve su `kyc_session_url` para que lo envíes o lo incrustes.
5) Lee la decisión consolidada de la sesión, igual que en el flujo alojado.Una llamada realizada mientras la sesión está en otro paso responde `409 kyb_step_mismatch` con el paso en el que se encuentra, y una sesión finalizada responde `409 kyb_session_not_writable`.## Agregación del perfil de empresaSi pasas `vendor_data` al crear la sesión, Didit agrupa todas las sesiones de esa empresa en una única [entidad de empresa](https://docs.didit.me/es/entities/businesses/overview.md). Usa el mapa `features` de la entidad para responder "¿está esta empresa completamente verificada ahora mismo?" sin recorrer las sesiones.Ventajas:- Los flujos periódicos de re-KYB se añaden al mismo perfil.
- Las transacciones monitorizadas con el mismo `vendor_data` llevan el contexto de riesgo de la empresa.
- Los UBO y directivos vinculados a entidades de usuario establecen relaciones entre entidades.## Buenas prácticas| Práctica | Por qué |
| - | - |
| Envía siempre `vendor_data` | Sin él, la sesión queda huérfana y no se puede agrupar. |
| Usa webhooks, no polling | Menor latencia y sin presión sobre el límite de solicitudes. |
| Verifica las firmas de los webhooks | Evita eventos suplantados. |
| Guarda el `session_id` en tu sistema | Es necesario para recuperar la decisión y generar archivos PDF. |
| Etiqueta las sesiones con `metadata` | Simplifica los informes y la depuración. |
| Configura un flujo de verificación (workflow) de prueba | Usa un flujo de sandbox para las pruebas de integración antes de pasar a producción. |## Gestión de errores| Escenario | Respuesta |
| - | - |
| `workflow_id` no válido | `400 Bad Request` |
| Sesión duplicada con el mismo `vendor_data` | Crea una sesión nueva. Es así por diseño, ya que se espera que haya reverificación. |
| País de la empresa fuera de los países permitidos del flujo | La consulta al registro genera la advertencia `KYB_COUNTRY_RESTRICTED`. |
| Caída del proveedor del registro durante la búsqueda de la empresa | `POST /v3/kyb/search/` devuelve `502` con `code: "kyb_registry_provider_unavailable"`. No se factura: reintenta, o crea una rama en función de `code` para ofrecer la introducción manual de los datos de la empresa. En el flujo alojado de Didit, la empresa se dirige automáticamente a la introducción manual de sus datos en lugar de mostrar un error que solo permite reintentar. Consulta [Búsqueda en registros KYB](https://docs.didit.me/es/standalone-apis/kyb-registry-search.md#gestionar-caídas-del-registro). |
| Límite de solicitudes | `429 Too Many Requests` con el encabezado `Retry-After`. |Referencia completa de [límites de solicitudes](https://docs.didit.me/es/integration/rate-limiting.md).## Próximos pasos> [card] [Webhooks](https://docs.didit.me/es/business-verification/webhooks.md)
>
> Todos los eventos y payloads de KYB.> [card] [Estados](https://docs.didit.me/es/business-verification/statuses.md)
>
> Referencia de la máquina de estados.> [card] [Esquema de respuesta](https://docs.didit.me/es/business-verification/response-schema.md)
>
> Cómo interpretar la decisión de KYB.


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