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

📘

Availability

Onboarding by API supports Mexican Entity objects. For Chilean entities and other countries, create the Entity from the Dashboard.

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 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 --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"
}
'
{
  "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 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 --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": "[email protected]",
    "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
        }
      ]
    }
  ]
}
'
{
  "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 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 --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'
{
  "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 --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 '[email protected]'
{
  "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 --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'
{
  "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:

EventMeaning
entity.onboarding.approvedThe Entity passed review and is ready to transact.
entity.onboarding.rejectedThe review failed. Create a new onboarding to retry.

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

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'
{
  "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 for the account details.

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"
}
'
{
  "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