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

# Onboarding de una entidad por API

> Crea una Entity para tu cliente y completa su revisión de conocimiento del cliente a través de la API de Fintoc sin usar el Dashboard, para plataformas y marketplaces.

Usa la API para crear una `Entity` y completar su onboarding. Una vez aprobada, la entidad puede ser titular de objetos `Account` sin que uses el Dashboard.

Este flujo es para plataformas que crean una `Entity` por cada cliente, como marketplaces o billeteras que mantienen saldos bajo la razón social de cada cliente. Para crear objetos `Account` bajo tu propia `Entity` raíz, revisa [Crea más cuentas](/es/guides/transfers/manage-accounts/creating-more-accounts).

<Info>
  **Disponibilidad**

  El onboarding por API admite objetos `Entity` mexicanos. Para entidades fuera de México, crea la `Entity` desde el Dashboard.
</Info>

```mermaid theme={null}
flowchart LR
    A[Create entity] --> B[Create onboarding]
    B --> C[Upload company documents]
    C --> D[Upload representative documents]
    D --> E[Upload shareholder documents]
    E --> F[Submit for review]
    F -->|entity.onboarding.approved| G[Create accounts]
    F -->|entity.onboarding.rejected| B
```

## Antes de comenzar

Necesitas una clave secreta del [Dashboard](https://dashboard.fintoc.com/), en **Developers → API Keys**. La clave que envías selecciona el modo: `sk_test_...` opera en `test` y `sk_live_...` opera en `live`.

Usa el modo `test` para construir y verificar tu integración. Usa el modo `live` para hacer el onboarding de cada cliente real. Son actividades distintas, no dos etapas de un mismo flujo. Un onboarding en `test` es un objeto distinto de uno en `live` y nunca se convierte en un onboarding en `live`. Hacer el onboarding de un cliente en `test` no avanza el onboarding en `live` de ese cliente. Los ejemplos de esta página usan una clave de prueba.

## Paso 1: Crear la entidad

Una `Entity` es la persona jurídica titular de la cuenta. Crea una para tu cliente con su razón social y su RFC (identificador fiscal mexicano). Configura `country_code` con `mx` y `holder_id` con el RFC del cliente.

```bash theme={null}
curl --request POST \
     --url https://api.fintoc.com/v2/entities \
     --header 'Authorization: YOUR_TEST_SECRET_KEY' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "country_code": "mx",
  "holder_name": "Test Entity 1",
  "holder_id": "AAA010101AAA"
}
'
```

```json Response theme={null}
{
  "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
  "object": "entity",
  "country_code": "mx",
  "holder_id": "AAA010101AAA",
  "holder_name": "Test Entity 1",
  "is_root": false,
  "mode": "test",
  "status": "waiting_initialization"
}
```

Guarda el ID de la `Entity` (`ent_...`), porque cada llamada del onboarding usa este valor. Revisa [El objeto Entity](/es/api/transfers-api/entities/entity-object) para ver la lista completa de atributos.

## Paso 2: Crear el onboarding

El `Onboarding` contiene la revisión de conocimiento del cliente de una `Entity`. La revisión incluye la información de la empresa, los representantes legales, el perfil transaccional y los accionistas. Crea un onboarding por `Entity` y envía los datos estructurados en la solicitud.

Una `Entity` mantiene como máximo un onboarding por modo, así que la misma `Entity` puede mantener un onboarding `live` y uno `test` al mismo tiempo. Un segundo onboarding en el mismo modo devuelve `409 Conflict`, incluso cuando el primero ya está `rejected`.

```bash theme={null}
curl --request POST \
     --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings \
     --header 'Authorization: YOUR_TEST_SECRET_KEY' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "company_information": {
    "business_activity": "Servicios financieros",
    "business_address": "Av. Insurgentes 456, CDMX",
    "fiscal_address": "Av. Reforma 123, CDMX",
    "incorporation_date": "2020-01-15",
    "phone": "+521111111111",
    "settlement_account": "646969000000000000"
  },
  "legal_representatives": [
    {
      "first_name": "Test Customer 1",
      "last_name": "Customer",
      "email": "rep@example.com",
      "nationality": "mx",
      "identification_number": "AAAA010101HDFAAA01",
      "position": "Director General"
    }
  ],
  "transactional_profile": {
    "resource_origins": ["trusts", "investments"],
    "monthly_amount_range": "1_500000",
    "monthly_operations_range": "1_15000"
  },
  "shareholders": [
    {
      "type": "natural_person",
      "name": "Test Customer 2",
      "last_name": "Customer",
      "holder_id": "AAAA010101AAA",
      "nationality": "mx",
      "percentage": 60
    },
    {
      "type": "legal_entity",
      "name": "Test Entity 2",
      "holder_id": "AAA010101AAA",
      "nationality": "mx",
      "percentage": 40,
      "children": [
        {
          "type": "natural_person",
          "name": "Test Customer 3",
          "last_name": "Customer",
          "holder_id": "AAAA010101AAA",
          "nationality": "mx",
          "percentage": 80
        }
      ]
    }
  ]
}
'
```

```json Response (abridged) theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
  "status": "in_progress",
  "source": "api",
  "submittable": false,
  "submitted_at": null,
  "reviewed_at": null,
  "legal_representatives": [
    {
      "id": "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K",
      "object": "onboarding_legal_representative",
      "documents": [
        { "slot_key": "identification", "status": "missing" },
        { "slot_key": "power_of_attorney", "status": "missing" }
      ]
    }
  ],
  "shareholders": [
    {
      "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K",
      "object": "onboarding_shareholder",
      "type": "natural_person",
      "parent_id": null,
      "document": { "slot_key": "identification", "status": "missing" }
    },
    {
      "id": "onbsh_8anBwgZktbZH6ydyHa6Tm0eM",
      "object": "onboarding_shareholder",
      "type": "legal_entity",
      "parent_id": null,
      "document": { "slot_key": "articles_of_incorporation", "status": "missing" }
    },
    {
      "id": "onbsh_9bnCxhAlucAI7zezIb7Un1fN",
      "object": "onboarding_shareholder",
      "type": "natural_person",
      "parent_id": "onbsh_8anBwgZktbZH6ydyHa6Tm0eM",
      "document": { "slot_key": "identification", "status": "missing" }
    }
  ],
  "documents": [
    { "slot_key": "tax_registration_certificate", "status": "missing" },
    { "slot_key": "settlement_bank_statement", "status": "missing" },
    { "slot_key": "proof_of_address", "status": "missing" },
    { "slot_key": "shareholder_structure", "status": "missing" },
    { "slot_key": "articles_of_incorporation", "status": "missing" }
  ]
}
```

Un bloque etiquetado como `Response (abridged)` muestra solo los campos que cambian en ese paso, no el objeto completo. La respuesta anterior también devuelve `data`, que repite la información de la empresa y el perfil transaccional que enviaste. Cada representante legal y accionista también incluye los campos de identidad de la solicitud. Revisa [El objeto Onboarding](/es/api/transfers-api/onboardings/onboarding-object) para ver la estructura completa.

Cuatro detalles a tener en cuenta en la respuesta:

* `submittable` es `false` hasta que cada campo y documento obligatorio esté completo.
* `documents` lista cada slot de documento de la empresa y su `status`, ya sea `missing` o `uploaded`. Lee este arreglo para identificar los documentos pendientes.
* Cada representante legal tiene su propio arreglo `documents` con dos slots.
* Cada accionista tiene un único slot `document`. Un accionista de tipo `legal_entity` puede incluir `children` anidados.

Cada onboarding abre cinco slots de la empresa, dos slots por representante legal y un slot por accionista. El onboarding anterior declara un representante legal y tres accionistas, así que abre diez slots en total. Los pasos 3, 4 y 5 los completan.

Algunos campos usan identificadores específicos de México. El `identification_number` del representante legal es una CURP (Clave Única de Registro de Población). El `settlement_account` es una CLABE (Clave Bancaria Estandarizada) de 18 dígitos. Revisa [El objeto Onboarding](/es/api/transfers-api/onboardings/onboarding-object) para ver todos los campos.

## Paso 3: Subir los documentos de la empresa

Sube un archivo a cada slot de documento de la empresa del arreglo `documents`. Envía el archivo como `multipart/form-data` en el campo `file`. El tamaño máximo del archivo es 20 MB. Subir un archivo a un slot que ya tiene uno reemplaza el archivo existente.

Cada slot acepta sus propios tipos de contenido:

| `slot_key`                     | Tipos de contenido aceptados                 |
| :----------------------------- | :------------------------------------------- |
| `tax_registration_certificate` | `application/pdf`                            |
| `settlement_bank_statement`    | `application/pdf`                            |
| `proof_of_address`             | `application/pdf`, `image/jpeg`, `image/png` |
| `shareholder_structure`        | `application/pdf`                            |
| `articles_of_incorporation`    | `application/pdf`                            |

```bash theme={null}
curl --request PUT \
     --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/documents/tax_registration_certificate \
     --header 'Authorization: YOUR_TEST_SECRET_KEY' \
     --header 'accept: application/json' \
     --form 'file=@tax_registration_certificate.pdf'
```

```json Response (abridged) theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "documents": [
    {
      "slot_key": "tax_registration_certificate",
      "status": "uploaded",
      "filename": "tax_registration_certificate.pdf",
      "uploaded_at": "2026-01-15T14:30:00Z"
    }
  ]
}
```

Repite el proceso para cada slot restante: `settlement_bank_statement`, `proof_of_address`, `shareholder_structure` y `articles_of_incorporation`.

## Paso 4: Subir los documentos de cada representante legal

Cada representante legal necesita dos documentos. Usa el `id` del representante legal (`onblr_...`) de la respuesta del paso 2 y envía el slot como último segmento de la ruta. El slot `identification` acepta `application/pdf`, `image/jpeg` e `image/png`. El slot `power_of_attorney` acepta solo `application/pdf`.

```bash theme={null}
curl --request PUT \
     --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/legal_representatives/onblr_0ujsswThIGTUYm2K8FjOOfXtY1K/documents/identification \
     --header 'Authorization: YOUR_TEST_SECRET_KEY' \
     --header 'accept: application/json' \
     --form 'file=@identification.pdf'
```

```json Response (abridged) theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "legal_representatives": [
    {
      "id": "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K",
      "object": "onboarding_legal_representative",
      "documents": [
        {
          "slot_key": "identification",
          "status": "uploaded",
          "filename": "identification.pdf",
          "uploaded_at": "2026-01-15T14:30:00Z"
        },
        { "slot_key": "power_of_attorney", "status": "missing" }
      ]
    }
  ]
}
```

Repite el proceso para el slot `power_of_attorney` y para cada representante legal que hayas declarado.

## Paso 5: Subir el documento de cada accionista

Cada accionista declarado necesita un documento. Usa el `id` del accionista (`onbsh_...`) de la respuesta del paso 2. Esta ruta no lleva slot, porque Fintoc lo deriva del `type` del accionista: `identification` para un `natural_person` y `articles_of_incorporation` para un `legal_entity`. El slot acepta `application/pdf`, `image/jpeg` e `image/png`.

```bash theme={null}
curl --request PUT \
     --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/shareholders/onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K/document \
     --header 'Authorization: YOUR_TEST_SECRET_KEY' \
     --header 'accept: application/json' \
     --form 'file=@identification.pdf'
```

```json Response (abridged) theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "shareholders": [
    {
      "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K",
      "object": "onboarding_shareholder",
      "document": {
        "slot_key": "identification",
        "status": "uploaded",
        "filename": "identification.pdf",
        "uploaded_at": "2026-01-15T14:30:00Z"
      }
    }
  ]
}
```

## Paso 6: Enviar a revisión

Una vez que `submittable` es `true`, envía el onboarding para que Fintoc lo revise. El onboarding debe estar en `in_progress` e incluir cada campo y documento obligatorio. Después del envío, el onboarding pasa a `submitted` y ya no se puede modificar.

```bash theme={null}
curl --request POST \
     --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/submit \
     --header 'Authorization: YOUR_TEST_SECRET_KEY' \
     --header 'accept: application/json'
```

```json Response (abridged) theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
  "status": "submitted",
  "source": "api",
  "submittable": false,
  "submitted_at": "2026-01-15T15:00:00Z",
  "reviewed_at": null
}
```

`submittable` pasa a `false` cuando el onboarding queda en `submitted`, porque un onboarding enviado ya no acepta cambios.

Si falta un campo o documento obligatorio, o el onboarding ya no está en `in_progress`, la llamada devuelve un error `422 Unprocessable Entity`. El campo `param` indica el slot o campo que bloquea el envío:

```json Error response theme={null}
{
  "error": {
    "type": "invalid_request_error",
    "code": "required_document_missing",
    "message": "A required document is missing.",
    "param": "tax_registration_certificate",
    "doc_url": "https://docs.fintoc.com/reference/errors"
  }
}
```

## Paso 7: Seguir la revisión

Un onboarding pasa por `pending`, `in_progress`, `submitted` y luego `approved`, `rejected` o `cancelled`. Fintoc envía uno de estos eventos de webhook cuando aprueba o rechaza el onboarding:

| Evento                       | Resultado del onboarding                                     |
| :--------------------------- | :----------------------------------------------------------- |
| `entity.onboarding.approved` | La `Entity` aprobó la revisión y está lista para operar.     |
| `entity.onboarding.rejected` | La revisión falló. Crea un onboarding nuevo para reintentar. |

Suscríbete a estos eventos en el Dashboard, en **Developers → Webhooks**, o consulta el onboarding directamente:

```bash theme={null}
curl --request GET \
     --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K \
     --header 'Authorization: YOUR_TEST_SECRET_KEY' \
     --header 'accept: application/json'
```

```json Response (abridged) theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
  "status": "approved",
  "source": "api",
  "submittable": false,
  "submitted_at": "2026-01-15T15:00:00Z",
  "reviewed_at": "2026-01-16T09:00:00Z"
}
```

Revisa `status` para seguir el onboarding. Una vez que `status` es `approved`, la `Entity` está lista para operar.

## Paso 8: Crear cuentas después de la aprobación

Después de que la `Entity` queda aprobada, crea uno o más objetos `Account` bajo la `Entity`. Envía el ID de la `Entity` en `entity_id`. Cada `Account` tiene su propio saldo y su account number raíz. Los comprobantes de las transferencias salientes muestran la razón social del cliente. Revisa [Crea más cuentas](/es/guides/transfers/manage-accounts/creating-more-accounts) para ver los detalles de creación de cuentas.

```bash theme={null}
curl --request POST \
     --url https://api.fintoc.com/v2/accounts \
     --header 'Authorization: YOUR_TEST_SECRET_KEY' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
  "description": "Client settlement account"
}
'
```

```json Response theme={null}
{
  "id": "acc_8anBwgZktbZH6ydyHa6Tm0eM",
  "object": "account",
  "mode": "test",
  "description": "Client settlement account",
  "root_account_number": "000000000000000000",
  "root_account_number_id": "acno_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "available_balance": 0,
  "currency": "MXN",
  "entity": {
    "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
    "holder_name": "Test Entity 1",
    "holder_id": "AAA010101AAA"
  }
}
```

## Probar la integración

En modo `test`, ejecuta toda la secuencia anterior con tu clave `sk_test_...`. Crea la `Entity` y el onboarding, sube un archivo de ejemplo a cada slot y envía el onboarding. Confirma que `submittable` pasa a `true` solo después de que cada slot indica `uploaded`.

Fintoc selecciona el modo según la clave de API que envías, no según un parámetro de la solicitud. Los cuerpos de solicitud y de respuesta del onboarding no llevan un campo `mode`. Los onboardings están aislados por modo. Una clave `test` no puede leer ni operar sobre un onboarding `live`, y una clave `live` no puede leer ni operar sobre un onboarding `test`. Ambos casos devuelven `404 Not Found` con el código `missing_resource`. Fintoc resuelve `entity_id` en el modo de la clave de API, así que una clave `test` debe referenciar una `Entity` que exista en modo `test`.

### Forzar el resultado de la revisión

En modo `live`, el envío inicia una revisión real de conocimiento del cliente que decide el equipo de cumplimiento de Fintoc. En modo `test`, el envío dispara una revisión simulada. Usa la revisión simulada para ejercitar los caminos de aprobación y rechazo sin esperar.

Fintoc decide la revisión simulada según el valor de `business_activity` que enviaste en `company_information`. Este mecanismo funciona como un número de tarjeta de prueba: un valor mágico fuerza un resultado específico. Tres casos determinan la revisión simulada:

| `business_activity`  | `status` resultante | Evento de webhook            |
| :------------------- | :------------------ | :--------------------------- |
| `illegal`            | `rejected`          | `entity.onboarding.rejected` |
| `suspicious`         | `submitted`         | Ningún evento                |
| Cualquier otro valor | `approved`          | `entity.onboarding.approved` |

El caso `suspicious` deja `reviewed_at` en `null`. Úsalo para modelar un onboarding que sigue en revisión y comprobar cómo se comporta tu integración mientras espera una decisión.

<Warning>
  Fintoc compara el string completo de forma exacta, incluyendo mayúsculas y espacios. `ILLEGAL`, `Illegal` y `"illegal "` con un espacio al final terminan todos en `approved`.
</Warning>

### Leer el resultado simulado

`POST .../submit` devuelve `200 OK` con `status` en `submitted` y `reviewed_at` en `null`, en ambos modos. La revisión simulada corre después de la respuesta, así que no tomes la respuesta del envío como el resultado de la revisión. Consulta el onboarding como se muestra en el paso 7, o escucha el evento de webhook.

Fintoc entrega `entity.onboarding.approved` y `entity.onboarding.rejected` a los endpoints de webhook registrados en modo `test`, y el evento lleva `"mode": "test"`.

```json Webhook event theme={null}
{
  "id": "evt_2xK9mP4nQrStUvWxYz1234567",
  "object": "event",
  "type": "entity.onboarding.approved",
  "mode": "test",
  "created_at": "2026-01-16T09:00:00.000Z",
  "data": {
    "object_name": "onboarding_process",
    "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
    "entity": {
      "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
      "holder_id": "AAA010101AAA",
      "holder_name": "Test Entity 1",
      "nationality": "mx"
    },
    "status": "approved",
    "submitted_at": "2026-01-15T15:00:00Z",
    "reviewed_at": "2026-01-16T09:00:00Z"
  }
}
```

El payload del webhook nombra el recurso como `onboarding_process` en `object_name`, que es el mismo objeto que la API devuelve con `"object": "onboarding"`. El evento de rechazo lleva el mismo payload con `"type": "entity.onboarding.rejected"` y `"status": "rejected"`.

### Qué no simula el modo test

En modo `test`, Fintoc reproduce el resultado de la revisión y el webhook, y nada más del flujo de cumplimiento:

* Sin motivo de rechazo. Un onboarding rechazado no expone ningún campo que explique la decisión, ni en la API ni en el payload del webhook.
* Sin correos. Fintoc no envía ninguna notificación de envío a los representantes legales en modo `test`.

## Qué sigue

* [Crea más cuentas](/es/guides/transfers/manage-accounts/creating-more-accounts) para una `Entity` aprobada.
* Revisa [El objeto Onboarding](/es/api/transfers-api/onboardings/onboarding-object) y [los endpoints de onboarding](/es/api/transfers-api/onboardings/entities-onboardings-create) en la referencia de la API.
