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

# Customer onboarding

> Open an organization for a customer through the onboarding API, follow its compliance analysis through webhooks and operate on the customer's behalf once it is approved.

This guide is for an organization that acts as a **distributor**: it opens accounts for its customers, follows the compliance analysis of each one through webhooks and, once a customer is approved, operates on the customer's behalf with its own credentials. The guide explains the flow and the concepts; the [Onboard entity](https://docs.trio.com.br/v2/api-reference/banking-api/onboarding/create.md) API reference lists every field, type and response.

All examples use the sandbox base URL `https://api.sandbox.trio.com.br`.

## 1. How the organization model works

Two organizations take part in the flow:

* **Distributor organization**: holds the API credentials and drives the flow for its customers.
* **Customer organization**: created by the onboarding and used for the customer's transactions.

One request creates the customer organization, its entity and its representatives. Trio then analyzes the customer, tells you the result through webhooks and, after approval, lets you operate on the customer organization by sending its `org_id` in the `Trio-Target-Org-Id` header. Your credentials never change: the header only changes which organization the request acts on.

```text theme={null}
1. Customer asks to open an account
              |
              v
2. Distributor collects the data
              |
              v
3. POST /v2/onboarding
              |
              v
4. Trio creates the organization, the entity
   and the representatives
              |
              v
5. API returns org_id and entity_id
              |
              v
6. Distributor uploads the required documents
              |
              v
7. Webhook: entity.in_review
              |
              v
8. Representative completes liveness
              |
              v
9. Compliance analyzes the data
              |
        +-----+-----+
        |           |
        v           v
   approved      rejected
        |           |
        v           v
10. Organization  Handle the
    ready         rejection
        |
        v
11. API calls with Trio-Target-Org-Id
    on the customer organization
```

See [Acting on another organization](https://docs.trio.com.br/v2/developers/authentication.md#acting-on-another-organization) for how the header is validated.

## 2. What you need

> [!NOTE]
>
> Onboarding is only available after Trio has created a **distribution channel** for your organization. To request one, contact Trio Support or your Trio Account Manager.

Before you call the API, have at hand:

* Your distributor organization's `client_id` and `client_secret`. Every request in this guide uses [Basic Authentication](https://docs.trio.com.br/v2/developers/authentication.md) with these credentials.
* The customer's company data: tax ID (CNPJ), name, annual revenue and average ticket.
* The data of each company representative: name, tax ID (CPF), phone number and email.
* The consent of the legal representative who authorizes opening the account: that representative's CPF, the IP address and the date and time of the authorization.
* The PDF documents your distribution channel requires for the company and for each representative. Step 5 explains which ones.

## 3. Create the onboarding

Send the company data, its representatives and the consent in one request:

```http theme={null}
POST /v2/onboarding
```

```http theme={null}
Authorization: Basic <encoded-value>
Content-Type: application/json
```

### Request fields

| Field | Required | Description |
| - | - | - |
| `tax_number` | Yes | Tax ID (CNPJ) of the company being registered |
| `name` | Yes | Entity name |
| `external_id` | No | Your own reference for the customer, such as `customer_12345` or `company_98765`. Pick a value that lets you find the customer in your application |
| `business_infos` | Yes | Company business information, see below |
| `representatives` | Yes | Company representatives, see below |
| `consent` | Yes | Consent for opening the account, see below |

`business_infos` holds two monetary objects. Amounts are in cents (BRL 100.00 = `10000`), so `{"amount": 500000, "currency": "BRL"}` is BRL 5,000.00.

| Field | Required | Description |
| - | - | - |
| `annual_revenue` | Yes | Annual revenue, as `amount` and `currency` |
| `average_ticket` | Yes | Average ticket, as `amount` and `currency` |

Each item of `representatives` describes one representative. The two compliance flags default to `false` when omitted.

| Field | Required | Description |
| - | - | - |
| `tax_number` | Yes | Tax ID (CPF) |
| `email` | Yes | Email address |
| `phone` | Yes | Phone number in E.164 format |
| `name` | Yes | Representative name |
| `is_pep` | No | Whether the representative is a politically exposed person (PEP) |
| `is_us_person` | No | Whether the representative is a US person for tax purposes |

`consent` records who authorized the account opening and when:

| Field | Required | Description |
| - | - | - |
| `tax_number` | Yes | Tax ID (CPF) of the legal representative responsible for the consent |
| `ip_address` | Yes | IP address of the authorization (IPv4 or IPv6) |
| `consent_at` | Yes | Date and time of the authorization |

### Example request

```bash theme={null}
curl --request POST \
  --url https://api.sandbox.trio.com.br/v2/onboarding \
  --header 'Authorization: Basic <encoded-value>' \
  --header 'Content-Type: application/json' \
  --data '{
    "tax_number": "61775921000110",
    "name": "Entity Test",
    "external_id": "12345ET",
    "business_infos": {
      "annual_revenue": {
        "amount": 500000,
        "currency": "BRL"
      },
      "average_ticket": {
        "amount": 10000000,
        "currency": "BRL"
      }
    },
    "representatives": [
      {
        "tax_number": "04969361908",
        "email": "john@gcorp.com",
        "phone": "+5541999990000",
        "name": "John",
        "is_pep": false,
        "is_us_person": false
      }
    ],
    "consent": {
      "tax_number": "04969361908",
      "ip_address": "8.8.8.8",
      "consent_at": "2026-08-25T07:00:00.000Z"
    }
  }'
```

## 4. Read the response

Onboarding creation is synchronous: the response returns the identifiers of everything that was created, and echoes the `business_infos`, `consent` and `representatives` you sent.

| Field | Description |
| - | - |
| `entity_id` | ID of the customer's entity |
| `org_id` | ID of the customer organization. You send it in `Trio-Target-Org-Id` to operate on the customer's behalf |
| `external_id` | The reference you sent |
| `tax_number` | Tax ID (CNPJ) of the company |
| `name` | Entity name |
| `status` | Onboarding status (`in_validation` in the example below) |
| `representatives[].id` | ID of the representative. You need it to upload the representative's documents |
| `representatives[].status` | Status of the representative |
| `representatives[].required_documents` | Documents the representative must provide |
| `required_documents` | Documents the company must provide |

```json theme={null}
{
  "data": {
    "entity_id": "01a0ee9f-7418-625f-e4b2-624b4ad4959f",
    "org_id": "92b0f620-7105-4c10-84a1-f5a034a14efa",
    "external_id": "404ANVIL",
    "tax_number": "61775921000110",
    "name": "ACME INC",
    "status": "in_validation",
    "business_infos": {
      "annual_revenue": {
        "amount": 5000000,
        "currency": "BRL"
      },
      "average_ticket": {
        "amount": 500000,
        "currency": "BRL"
      }
    },
    "consent": {
      "consent_at": "2026-08-25T07:00:00.000000Z",
      "ip_address": "8.8.8.8",
      "tax_number": "52998224725"
    },
    "representatives": [
      {
        "id": "8c61c7fd-3509-4306-9fec-9090e82fe121",
        "name": "Willy Coyote",
        "tax_number": "52998224725",
        "email": "w.coyote@acme.com",
        "phone": "+5541999990000",
        "status": "in_validation",
        "required_documents": ["identification"]
      }
    ],
    "required_documents": ["company_contract"],
    "inserted_at": "2026-09-29T19:23:42.485921Z",
    "updated_at": "2026-09-29T19:23:42.485921Z"
  }
}
```

> [!TIP]
>
> Store `org_id`, `entity_id`, `external_id`, `tax_number` and the current status in your system. You need `org_id` for every call on the customer's behalf, and the full set makes it easy to reconcile your records with Trio.

### Required documents

`required_documents` appears in two places, based on the documents configured for your distribution channel:

* `data.required_documents`: documents the company must provide, such as `company_contract`, `power_of_attorney` and `financial_statement`.
* `data.representatives[].required_documents`: documents each representative must provide, typically `identification`.

Both fields are `null` when no document is required. They tell you exactly what to upload in the next step.

## 5. Upload the required documents

Depending on your distribution channel, compliance may ask for supporting documents for the entity, for its representatives or for both. Upload them after the onboarding is created, using the identifiers from the response:

```http theme={null}
POST /v2/onboarding/documents
```

The request is `multipart/form-data` with the same Basic Authentication as the onboarding creation. Only PDF files are accepted. Each request uploads one document, so repeat the call for every required document of the entity and of each representative. See the [Upload onboarding document](https://docs.trio.com.br/v2/api-reference/banking-api/onboarding/create-document.md) API reference.

| Field | Required | Description |
| - | - | - |
| `reference_type` | Yes | `entity` or `entity_representative` |
| `reference_id` | Yes | The `entity_id` for an entity, or the representative `id` for a representative |
| `document_type` | Yes | Document classification, by reference type (see below) |
| `file` | Yes | The PDF file |

| `reference_type` | `reference_id` | Accepted `document_type` |
| - | - | - |
| `entity` | `entity_id` | `company_contract`, `power_of_attorney`, `financial_statement` |
| `entity_representative` | representative `id` | `identification` |

### Upload a financial statement for the entity

```bash theme={null}
curl --request POST \
  --url https://api.sandbox.trio.com.br/v2/onboarding/documents \
  --header 'Authorization: Basic <encoded-value>' \
  --header 'Content-Type: multipart/form-data' \
  --form 'reference_type=entity' \
  --form 'reference_id=01a0ee9f-7418-625f-e4b2-624b4ad4959f' \
  --form 'document_type=financial_statement' \
  --form 'file=@./financial_statement.pdf'
```

### Upload an identification document for a representative

```bash theme={null}
curl --request POST \
  --url https://api.sandbox.trio.com.br/v2/onboarding/documents \
  --header 'Authorization: Basic <encoded-value>' \
  --header 'Content-Type: multipart/form-data' \
  --form 'reference_type=entity_representative' \
  --form 'reference_id=8c61c7fd-3509-4306-9fec-9090e82fe121' \
  --form 'document_type=identification' \
  --form 'file=@./identification.pdf'
```

### Response

```json theme={null}
{
  "data": {
    "id": "01a0ee9f-4ff4-e363-41fe-8ced18a18eef",
    "reference_type": "entity",
    "reference_id": "01a0ee9f-7418-625f-e4b2-624b4ad4959f",
    "document_type": "financial_statement",
    "inserted_at": "2026-09-29T19:23:33.236814Z",
    "updated_at": "2026-09-29T19:23:33.236814Z"
  }
}
```

## 6. Complete the liveness check

After creation, the onboarding enters validation. Each representative must complete a facial recognition (**liveness**) check before the account can be opened. Trio provides the link for it as the representative's `liveness_link`; send the link to the representative, who completes the check through it.

```json theme={null}
{
  "representatives": [
    {
      "id": "0191148f-b189-8e42-27a5-1368cc00dea8",
      "status": "in_review",
      "tax_number_linked": "11144477735",
      "name_linked": "John",
      "email": "john@gcorp.com",
      "liveness_link": "https://liveness.link/example?123"
    }
  ]
}
```

## 7. Compliance analysis

Once the liveness check is done, the customer's information goes to compliance analysis. You do not need to poll the API for the result: Trio sends an event in the `entity` category whenever the compliance status of an entity created through onboarding changes. The next step describes these events; the [webhook events](https://docs.trio.com.br/v2/webhooks/events/overview.md) catalog lists all of them.

## 8. Onboarding webhooks

Three events track the analysis:

| Event | Status | Meaning |
| - | - | - |
| `entity.in_review` | `in_review` | The entity is under compliance analysis |
| `entity.approved` | `approved` | The entity was approved and is ready to operate |
| `entity.rejected` | `rejected` | The entity was rejected by compliance analysis |

> [!TIP]
>
> Keep the customer in an onboarding state until you receive `entity.approved`, then enable the operations your integration supports. On `entity.rejected`, store the `reason` from the payload so the customer's case can be handled.

### Entity in review

`entity.in_review` tells you the entity entered the analysis stage. When applicable, it also carries the representative's `liveness_link`.

```json theme={null}
{
  "data": {
    "entity_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "company_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "org_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "status": "in_review",
    "external_id": "12345ET",
    "tax_number": "37335118000180",
    "representatives": [
      {
        "status": "in_review",
        "liveness_link": "https://liveness.link/example?123"
      }
    ]
  },
  "timestamp": "2026-08-25T07:05:00.000Z",
  "type": "in_review",
  "category": "entity"
}
```

### Entity approved

`entity.approved` tells you compliance approved the entity. From this event on, your application can treat the customer organization as ready for the operations supported by the product.

```json theme={null}
{
  "data": {
    "entity_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "company_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "org_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "status": "approved",
    "external_id": "12345ET",
    "tax_number": "37335118000180"
  },
  "timestamp": "2026-08-25T09:30:00.000Z",
  "type": "approved",
  "category": "entity"
}
```

### Entity rejected

`entity.rejected` tells you compliance rejected the entity. The `reason` field describes why.

```json theme={null}
{
  "data": {
    "entity_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "company_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "org_id": "0191148f-b189-8e42-27a5-1368cc00dea8",
    "status": "rejected",
    "reason": "Documentation could not be validated.",
    "external_id": "12345ET",
    "tax_number": "37335118000180"
  },
  "timestamp": "2026-08-25T09:30:00.000Z",
  "type": "rejected",
  "category": "entity"
}
```

## 9. Operate on the customer's organization

Once the entity is approved, make calls on the customer's behalf with your own credentials and the customer's `org_id` in the header:

```http theme={null}
Trio-Target-Org-Id: {target_org_id}
```

For example, to [list the entities](https://docs.trio.com.br/v2/api-reference/banking-api/entities/list.md) of the customer organization:

```bash theme={null}
curl https://api.sandbox.trio.com.br/v2/entities \
  -H "Content-Type: application/json" \
  -H "Trio-Target-Org-Id: 92b0f620-7105-4c10-84a1-f5a034a14efa" \
  -u {client_id}:{client_secret}
```

Trio validates the access on every request: if your organization has no access to the target organization, the API returns `403`. Access is configured at the organization level and must be enabled for your integration.

### Retrieve the customer's bank account

After `entity.approved`, the customer's bank account is typically available within a few minutes. It is not created at the same instant as the approval event, so do not assume the account ID is available right away.

To get it, call [List bank accounts](https://docs.trio.com.br/v2/api-reference/banking-api/bank-accounts/list-bank-accounts.md) with the customer's `org_id` in `Trio-Target-Org-Id`:

```http theme={null}
GET /v2/bank_accounts
```

Collect the bank account `id` from the response: it is the `bank_account_id` you send when creating receivables and payments on the customer's behalf.

## Next steps

* [Acting on another organization](https://docs.trio.com.br/v2/developers/authentication.md#acting-on-another-organization): how access is granted, read-only access and mTLS.
* [Webhook events](https://docs.trio.com.br/v2/webhooks/events/overview.md): the full event catalog, including the `entity` category.
* [Receivables](https://docs.trio.com.br/v2/guides/receivables/overview.md): receive payments on the customer's bank account.
* [Onboard entity](https://docs.trio.com.br/v2/api-reference/banking-api/onboarding/create.md): every field, type and response of the onboarding endpoint.


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