Share KYB Information through Entities

Send the KYB information of a sub-merchant with the Entities API: the company, its owners, its legal representative, and their documents.

This guide shows, call by call and with requests and responses, how to send the information listed in KYB Requirements for Virtual Account Beneficiaries using the Entities API. Where each item goes in Entities is in the How to send it column of that page. In short: the company is an entity of type COMPANY, each person is an entity of type INDIVIDUAL (owners are linked to the company as UBOs), and every document is a declared document with its files. The examples use a fictitious company registered in Brazil.

Prerequisites

Flow

%%{init: {'theme': 'base', 'themeVariables': {'background': '#ffffff', 'primaryColor': '#31467c', 'primaryTextColor': '#ffffff', 'primaryBorderColor': '#0c1a29', 'secondaryColor': '#31467c', 'tertiaryColor': '#ffffff', 'lineColor': '#0c1a29', 'textColor': '#0c1a29', 'edgeLabelBackground': '#ffffff', 'fontFamily': 'Manrope'}, 'fontFamily': 'Manrope', 'htmlLabels': false, 'flowchart': {'htmlLabels': false, 'wrappingWidth': 400, 'padding': 20}}}%%
flowchart TD
    A["1. Read your custom-fields schema<br/>GET /api/entity/v1/custom-fields/schema"]:::lp --> B["2. Create the company<br/>POST /api/entity/v1/entities, type COMPANY<br/>tax ID as primary document, business profile in attributes"]
    B --> DH["3. Company documents<br/>one per document, each with its files"]:::lp
    DH --> D1["ARTICLES_OF_INCORPORATION<br/>plus ownership chart when needed"]
    DH --> D2["PROOF_OF_FUNDS<br/>one file per document"]
    DH --> D3["OTHER<br/>proof of ownership, B2C"]
    D1 & D2 & D3 --> PH["4 and 5. People<br/>one INDIVIDUAL per owner and for the legal representative<br/>each with its identity document"]:::lp
    PH --> P1["Owner 1<br/>identity document<br/>FRONT, BACK"]
    PH --> P2["Owner 2, 3, and so on<br/>same steps"]
    PH --> P3["Legal representative<br/>same steps"]
    P1 --> L1["6. Link to the company, owner 1<br/>POST /api/entity/v1/entities/{companyId}/ubos<br/>ownershipPercentage"]
    P2 --> L2["6. Link to the company, each other owner<br/>POST /api/entity/v1/entities/{companyId}/ubos<br/>ownershipPercentage"]
    P3 --> L3["6. Link to the company, legal representative<br/>POST /api/entity/v1/entities/{companyId}/ubos<br/>ownershipPercentage 0, controlRole LEGAL_REPRESENTATIVE"]
    L1 & L2 & L3 --> V["7. Tell Localpayment the upload is complete<br/>POST /api/entity/v1/entities/{companyId}/verify"]
    V --> G[/"Localpayment reviews<br/>the company and each person"/]:::lp
    classDef default fill:#31467c,stroke:#0c1a29,stroke-width:1px,color:#ffffff,font-family:Manrope
    classDef lp fill:#0c1a29,stroke:#0c1a29,color:#ffffff
    classDef terminal fill:#0c1a29,stroke:#0c1a29,color:#ffffff
    classDef lbl fill:#0c1a29,stroke:#0c1a29,color:#ffffff,font-size:13px
ℹ️

Legal representative. Create it as an INDIVIDUAL (its identity document can be the primary document) and link it to the company with Link a UBO: ownershipPercentage: 0 and controlRole: LEGAL_REPRESENTATIVE. If the legal representative is also an owner, link it once, with its percentage and controlRole: LEGAL_REPRESENTATIVE.

Step by step

Run the calls below in this order. Keep every internalId and documentId the API returns. The examples send only the minimum.

1. Read your custom-fields schema

GET /api/entity/v1/custom-fields/schema returns the attributes your account accepts. Excerpt with the business profile:

{
  "businessProfile": {
    "type": "string",
    "enum": [
      "MARKETPLACE",
      "B2C",
      "B2B"
    ]
  }
}

2. Create the company

POST /api/entity/v1/entities. The tax ID is the primary document, and the business profile goes in attributes:

{
  "externalId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "type": "COMPANY",
  "name": "Example Company S.A.",
  "residenceCountry": "BRA",
  "document": {
    "type": "CNPJ",
    "id": "00000000000100",
    "issuingCountry": "BRA"
  },
  "website": "https://www.example.com",
  "attributes": {
    "businessProfile": "B2C"
  }
}
{
  "internalId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "externalId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "type": "COMPANY",
  "status": "PENDING_KYC",
  "name": "Example Company S.A.",
  "residenceCountry": "BRA",
  "website": "https://www.example.com",
  "attributes": {
    "businessProfile": "B2C"
  },
  "documentationStatus": "NO_FILES"
}

The response is 201 Created (excerpt). The primary document comes back with its documentId and no files, which is expected: it needs none.

3. Declare the company documents and upload their files

Declare each document with POST /api/entity/v1/entities/{companyId}/documents. The incorporation document carries the registration number in id (in Brazil, the CNPJ):

{
  "type": "ARTICLES_OF_INCORPORATION",
  "id": "00000000000100",
  "issuingCountry": "BRA"
}

Then send one POST /api/entity/v1/documents/{documentId}/proofs per file, with proofType=DOCUMENT and the file. Response (excerpt):

{
  "id": "4653bc4d-7df4-41c4-b8ef-60e7a3a378bb",
  "documentId": "84f3b6db-7b74-4def-968d-cbb5bf90cab7",
  "proofType": "DOCUMENT",
  "fileName": "certificate_of_incorporation.pdf",
  "mimeType": "application/pdf",
  "verificationStatus": "PENDING",
  "status": "CURRENT"
}

Declare and upload the source-of-funds documents and, for B2C, the proof of ownership the same way:

[
  {
    "type": "PROOF_OF_FUNDS",
    "id": "SALES-2024-Q1",
    "issuingCountry": "BRA"
  },
  {
    "type": "OTHER",
    "id": "DOMAIN-example",
    "issuingCountry": "BRA"
  }
]

4. Create each person

One INDIVIDUAL per owner and for the legal representative, with POST /api/entity/v1/entities. The identity document can be the primary document:

{
  "externalId": "550e8400-e29b-41d4-a716-446655440000",
  "type": "INDIVIDUAL",
  "name": "Jane",
  "lastname": "Doe",
  "residenceCountry": "BRA",
  "document": {
    "type": "NATIONAL_ID",
    "id": "000000000",
    "issuingCountry": "BRA"
  }
}
{
  "internalId": "5aced5da-40c1-4bec-85ff-c8cd1bcb4526",
  "type": "INDIVIDUAL",
  "status": "PENDING_KYC",
  "document": {
    "documentId": "e6d636a0-362c-4e17-9ac9-5451d56ed393",
    "type": "NATIONAL_ID",
    "id": "000000000",
    "issuingCountry": "BRA",
    "isPrimary": true
  }
}

The response is 201 Created (excerpt).

5. Upload each person's identity document

Front and back go to the same document: POST /api/entity/v1/documents/{documentId}/proofs with proofType=FRONT, then with proofType=BACK (passport: FRONT only). Excerpt of GET /api/entity/v1/documents/{documentId}/proofs after both uploads:

[
  {
    "id": "d577e8e5-ef53-43b8-aaa3-b97ca202949a",
    "proofType": "FRONT",
    "fileName": "id_front.jpg",
    "verificationStatus": "PENDING",
    "status": "CURRENT"
  },
  {
    "id": "21e6e46d-e047-4f19-88f4-175132839e04",
    "proofType": "BACK",
    "fileName": "id_back.jpg",
    "verificationStatus": "PENDING",
    "status": "CURRENT"
  }
]

6. Link each person to the company

One POST /api/entity/v1/entities/{companyId}/ubos per person. Jane Doe owns 60% and is also the legal representative:

{
  "personId": "5aced5da-40c1-4bec-85ff-c8cd1bcb4526",
  "ownershipPercentage": 60,
  "controlRole": "LEGAL_REPRESENTATIVE"
}
{
  "id": "37325b16-514f-40f5-afca-a2acd201f629",
  "companyId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "personId": "5aced5da-40c1-4bec-85ff-c8cd1bcb4526",
  "ownershipPercentage": 60.0,
  "controlRole": "LEGAL_REPRESENTATIVE",
  "validFrom": "2024-01-15",
  "validTo": null,
  "createdAt": "2024-01-15T17:04:17Z"
}

John Doe owns 40%, with the role in upper case:

{
  "personId": "c0b9c624-7777-4f6c-a4c5-57ef00f895c2",
  "ownershipPercentage": 40,
  "controlRole": "PARTNER"
}

GET /api/entity/v1/entities/{companyId}/ubos lists both:

{
  "items": [
    {
      "id": "37325b16-514f-40f5-afca-a2acd201f629",
      "companyId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "personId": "5aced5da-40c1-4bec-85ff-c8cd1bcb4526",
      "ownershipPercentage": 60.0,
      "controlRole": "LEGAL_REPRESENTATIVE",
      "validFrom": "2024-01-15",
      "validTo": null,
      "createdAt": "2024-01-15T17:04:17Z"
    },
    {
      "id": "848b821f-1ebb-42cf-b4c1-634b5db579e6",
      "companyId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "personId": "c0b9c624-7777-4f6c-a4c5-57ef00f895c2",
      "ownershipPercentage": 40.0,
      "controlRole": "PARTNER",
      "validFrom": "2024-01-15",
      "validTo": null,
      "createdAt": "2024-01-15T17:04:18Z"
    }
  ]
}

Keep the company's internalId: it identifies the beneficiary in Localpayment.

7. Tell Localpayment the upload is complete

When the company, its documents, and every person are loaded and linked, call POST /api/entity/v1/entities/{companyId}/verify on the company (Request Verification). It informs Localpayment that the documentation upload is complete. The response is 202 Accepted (excerpt):

{
  "internalId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "type": "COMPANY",
  "status": "IN_REVIEW",
  "updatedAt": "2024-01-15T17:05:00Z"
}

While the company is IN_REVIEW it is locked (409 ENTITY_IN_REVIEW). With verify your part of the upload ends: you don't need to poll the entity's status afterwards.

Checklist

  • Every document you declared (incorporation, source of funds, identity documents) has its files. A primary tax ID document needs no file.
  • Every owner is linked to the company with its ownershipPercentage, and the legal representative with controlRole: LEGAL_REPRESENTATIVE.
  • attributes.businessProfile is set on the company.
  • After everything was loaded, you called verify on the company.
  • Tax identification numbers contain digits only, and names match the documents exactly.
  • Every file is PDF, PNG, JPG, or JPEG and under 10 MB.
ℹ️

After the checklist is complete, Localpayment reviews the company and each person, and tells you if something has to be corrected. See Track the Review and Fix Rejections.

Next steps


Did this page help you?