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

# Onboard an Entity by API

> Create an `Entity` for your client and run its Know Your Customer (KYC) review end to end by API, without the Dashboard.

Create an `Entity` for your client and take the `Entity` from creation to an approved Know Your Customer (KYC) review entirely by API. At the end, you have an operational `Entity` that can own `Account` objects, without using the Dashboard.

This flow is for platforms that onboard many clients, such as marketplaces or wallets that hold balances under each client's legal name. To create `Account` objects under your own Root `Entity`, see [Create more accounts](/docs/transfers/manage-accounts/creating-more-accounts) instead.

<Info>
  **Availability**

  Onboarding by API supports Mexican `Entity` objects. For Chilean entities and other countries, create the `Entity` from the Dashboard.
</Info>

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

## Before you start

You need a test secret key (`sk_test_...`), available in the [Dashboard](https://dashboard.fintoc.com/) under **Developers → API Keys**. Run the whole flow in `test` mode first, then switch to your `live` key.

## Step 1 - Create the Entity

An `Entity` is the legal account holder. Create one for your client with their legal name and Mexican tax ID (RFC). Set `country_code` to `mx`, and set `holder_id` to the client's RFC.

```curl 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"
}
```

Keep the `Entity` `id` (`ent_...`); every onboarding call uses it. See [The Entity object](/reference/transfers-api/entities/entity-object) for the full attribute list.

## Step 2 - Create the onboarding

The `Onboarding` holds the KYC review for one `Entity`: company information, the legal representative, the transactional profile, and the shareholders. Create one onboarding per `Entity` and pass the structured data up front.

```curl 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": "000000000000000000"
  },
  "legal_representative": {
    "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 theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
  "status": "in_progress",
  "source": "api",
  "submittable": false,
  "submitted_at": null,
  "reviewed_at": null,
  "data": {
    "company_information": {
      "business_activity": "Servicios financieros"
    }
  },
  "shareholders": [
    {
      "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K",
      "object": "onboarding_shareholder",
      "type": "natural_person",
      "name": "Test Customer 2",
      "last_name": "Customer",
      "percentage": 60,
      "holder_id": "AAAA010101AAA",
      "parent_id": null,
      "document": { "slot_key": "identification", "status": "missing" }
    },
    {
      "id": "onbsh_8anBwgZktbZH6ydyHa6Tm0eM",
      "object": "onboarding_shareholder",
      "type": "legal_entity",
      "name": "Test Entity 2",
      "percentage": 40,
      "holder_id": "AAA010101AAA",
      "parent_id": null,
      "document": { "slot_key": "articles_of_incorporation", "status": "missing" }
    },
    {
      "id": "onbsh_9bnCxhAlucAI7zezIb7Un1fN",
      "object": "onboarding_shareholder",
      "type": "natural_person",
      "name": "Test Customer 3",
      "last_name": "Customer",
      "percentage": 80,
      "holder_id": "AAAA010101AAA",
      "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": "representative_identification", "status": "missing" },
    { "slot_key": "representative_power_of_attorney", "status": "missing" },
    { "slot_key": "shareholder_structure", "status": "missing" }
  ]
}
```

Three details to note in the response:

* `submittable` is `false` until every required field and document is in place.
* `documents` lists each company document slot and its `status` (`missing` or `uploaded`). Read this array to know what is still outstanding.
* Each shareholder carries a `document` slot, and `legal_entity` shareholders can nest `children`.

Some fields use Mexico-specific identifiers. The legal representative's `identification_number` is a Mexican Unique Population Registry Code (CURP). The `settlement_account` is an 18-digit standardized Mexican bank account number (CLABE). See [The Onboarding object](/reference/transfers-api/onboardings/onboarding-object) for every field.

## Step 3 - Upload the company documents

Upload one file to each company document slot returned in the `documents` array. Send the file as `multipart/form-data` in the `file` field. Each file must be a PDF, JPEG, or PNG, and cannot exceed 20 MB. Uploading to a slot that already has a file replaces it.

```curl 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 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"
    }
  ]
}
```

Repeat for each remaining slot: `settlement_bank_statement`, `proof_of_address`, `representative_identification`, `representative_power_of_attorney`, and `shareholder_structure`.

## Step 4 - Upload each shareholder's document

Each declared shareholder needs its identity document. Use the shareholder `id` (`onbsh_...`) from the Step 2 response. A `natural_person` shareholder uploads `identification`, and a `legal_entity` shareholder uploads `articles_of_incorporation`. The file rules match Step 3.

```curl 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 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"
      }
    }
  ]
}
```

## Step 5 - Submit for review

Once `submittable` is `true`, submit the onboarding for Fintoc to review. The onboarding must be `in_progress`, with every required field and document in place. On success, the onboarding moves to `submitted` and can no longer be modified.

```curl 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 theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
  "status": "submitted",
  "source": "api",
  "submittable": true,
  "submitted_at": "2026-01-15T15:00:00Z",
  "reviewed_at": null
}
```

If a required field or document is missing, or the onboarding is no longer `in_progress`, the call returns a `422 Unprocessable Entity` error.

## Step 6 - Track the review

An onboarding moves through `pending`, `in_progress`, `submitted`, and then `approved`, `rejected`, or `cancelled`. After you submit, Fintoc reviews the onboarding and emits a webhook event:

| Event                        | Meaning                                              |
| :--------------------------- | :--------------------------------------------------- |
| `entity.onboarding.approved` | The `Entity` passed review and is ready to transact. |
| `entity.onboarding.rejected` | The review failed. Create a new onboarding to retry. |

Subscribe to these events in **Developers → Webhooks**, or poll the onboarding directly:

```curl 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 theme={null}
{
  "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K",
  "object": "onboarding",
  "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN",
  "status": "approved",
  "source": "api",
  "submittable": true,
  "submitted_at": "2026-01-15T15:00:00Z",
  "reviewed_at": "2026-01-16T09:00:00Z"
}
```

Inspect `status` to know where the onboarding stands. Once `status` is `approved`, the `Entity` is ready to transact.

## Step 7 - Create accounts once approved

After the `Entity` is approved, create one or more `Account` objects under the `Entity` and pass the `Entity`'s `entity_id`. Each `Account` has its own balance and root Account Number. Outbound transfers from the `Account` show the client's legal name on the receipt. See [Create more accounts](/docs/transfers/manage-accounts/creating-more-accounts) for the account details.

```curl 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"
  }
}
```

## Test the integration

In `test` mode, run the full sequence above with your `sk_test_...` key. Create the `Entity`, create the onboarding, upload a sample file to every slot, and submit. Confirm that `submittable` turns `true` only after every slot reports `uploaded`, and that the onboarding reaches `submitted`. Step 6 covers the review result.

## What's next

* [Create more accounts](/docs/transfers/manage-accounts/creating-more-accounts) for an approved `Entity`.
* [The Onboarding object](/reference/transfers-api/onboardings/onboarding-object) and [the onboarding endpoints](/reference/transfers-api/onboardings/entities-onboardings-create) in the API reference.
