Understand the document types and verifications each customer needs to complete in order to be approved.
When a customer reaches pending_kyc status, the customer.kyc array lists all required documents and verifications. The verification flow works in two steps:
Early upload via API (optional): the partner uploads documents they already have for the customer (identity, proof of address, company documents, etc.) through the API. This speeds up the process because those documents will already be ready when the customer starts the biometrics session.
Biometrics session (required): the partner generates a session URL and presents it to the customer. In the session, the customer submits remaining documents, takes a selfie, and confirms the submission. The confirmation is what triggers the evaluation of all documents.
The selfie can only be captured by the customer in the biometrics session.
Info: The
kycarray is only available frompending_kycstatus onward. During thecreatingstatus, co-owner enrichment is still in progress and requirements have not been resolved yet.
All requirements share the same base structure:
{
"requirement_id": "identity_12345678900",
"requirement_type": "identity",
"label": "Documento de identidade",
"mandatory": true,
"subject": {
"name": "Joao Silva",
"cpf": "12345678900",
"subject_type": "applicant"
},
"submitted": null
}| Field | Description |
|---|---|
requirement_id | Requirement identifier. Use this value when uploading documents. |
requirement_type | Requirement type. Determines which evidence and attachments are accepted. |
label | Human-readable requirement name for display to the user. |
mandatory | If true, the requirement must be completed for the customer to proceed. |
subject | Person or company the requirement refers to. null for company-wide requirements. |
submitted | Submission state. null when no document has been submitted. |
Requirements can be tied to a person (partner or applicant) or to the company as a whole.
Person requirements include the subject field with data about who must submit the document:
"subject": {
"name": "Joao Silva",
"cpf": "12345678900",
"subject_type": "applicant"
}The subject_type can be:
applicantfor the registration holderco_ownerfor partners identified during enrichment
Company requirements (such as company_document or articles_of_association) do not have a subject. They apply to the registered company.
If the partner already has the customer's documents, they can upload them through the API before the biometrics session. Documents uploaded early do not need to be submitted again in the session.
The POST /v3/customers/{customer_id}/kyc-attachments endpoint accepts individual uploads per requirement. Each upload requires the requirement_id, evidence_type, attachment_type, and the file.
Tip: Early upload is optional, but reduces what the customer needs to do in the biometrics session. The more documents the partner uploads, the faster the customer completes verification.
Photo identity document for a person (applicant or co-owner). Accepts CNH or RG as evidence.
CNH (evidence_type: "cnh"): accepts two submission forms.
Physical CNH (front and back):
| Attachment | attachment_type | Formats |
|---|---|---|
| Front | front | JPEG, PNG |
| Back | back | JPEG, PNG |
Digital CNH (single file):
| Attachment | attachment_type | Formats |
|---|---|---|
| File | file |
RG (evidence_type: "rg"):
| Attachment | attachment_type | Formats |
|---|---|---|
| Front | front | JPEG, PNG |
| Back | back | JPEG, PNG |
import fs from "fs";
// Physical CNH - upload front and back
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "identity_12345678900",
evidenceType: "cnh",
attachmentType: "front",
file: fs.createReadStream("/path/to/cnh-front.jpg"),
});
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "identity_12345678900",
evidenceType: "cnh",
attachmentType: "back",
file: fs.createReadStream("/path/to/cnh-back.jpg"),
});Tip: The digital CNH is uploaded as a single PDF file, no need to separate front and back.
Photo of the person's face for biometric validation. Always tied to a subject.
| Attachment | attachment_type | Formats |
|---|---|---|
| Photo | photo | JPEG, PNG |
Warning: The selfie can only be captured by the customer in the biometrics session. It cannot be uploaded through the API.
Proof of address for the person. Always tied to a subject.
| Attachment | attachment_type | Formats |
|---|---|---|
| File | file | PDF, JPEG, PNG |
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "proof_of_address_12345678900",
evidenceType: "proof_of_address",
attachmentType: "file",
file: fs.createReadStream("/path/to/proof-of-address.pdf"),
});Company incorporation document. No subject, applies to the registered company.
| Attachment | attachment_type | Formats |
|---|---|---|
| File | file | PDF, JPEG, PNG |
The evidence_type is ccmei (Certificado da Condição de Microempreendedor Individual).
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "company_document",
evidenceType: "ccmei",
attachmentType: "file",
file: fs.createReadStream("/path/to/ccmei.pdf"),
});Composite requirement that requires two documents: the EI registration and the CCMEI. Both must be submitted. No subject.
| Attachment | attachment_type | Formats |
|---|---|---|
| EI Registration | ei_registration_requirement | PDF, JPEG, PNG |
| CCMEI | ccmei | PDF, JPEG, PNG |
The evidence_type for both is ei_mei.
// EI Registration
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "ei_mei_documents",
evidenceType: "ei_mei",
attachmentType: "ei_registration_requirement",
file: fs.createReadStream("/path/to/ei-registration.pdf"),
});
// CCMEI
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "ei_mei_documents",
evidenceType: "ei_mei",
attachmentType: "ccmei",
file: fs.createReadStream("/path/to/ccmei.pdf"),
});Company income statement. No subject.
| Attachment | attachment_type | Formats |
|---|---|---|
| File | file | PDF, JPEG, PNG |
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "income_statement",
evidenceType: "income_statement",
attachmentType: "file",
file: fs.createReadStream("/path/to/income-statement.pdf"),
});Company's articles of association or equivalent document. No subject.
| Attachment | attachment_type | Formats |
|---|---|---|
| File | file | PDF, JPEG, PNG |
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "articles_of_association",
evidenceType: "articles_of_association",
attachmentType: "file",
file: fs.createReadStream("/path/to/articles-of-association.pdf"),
});Incorporation statement for an Empresa Individual de Responsabilidade Limitada. No subject.
| Attachment | attachment_type | Formats |
|---|---|---|
| File | file | PDF, JPEG, PNG |
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "eireli_incorporation_statement",
evidenceType: "eireli_incorporation_statement",
attachmentType: "file",
file: fs.createReadStream("/path/to/incorporation-statement.pdf"),
});Person-level requirement for collecting the email address of co-owners who need to digitally sign the CCB. Each co-owner generates an email_{cpf} requirement with a subject field identifying the person.
Note: The primary applicant's email is provided during customer creation. This requirement only appears for co-owners who need to sign the CCB.
Submission is done via the KYC attachment upload endpoint, using the value field instead of file:
await client.customers.uploadKycAttachment(customer.id, {
requirementId: "email_12345678900",
evidenceType: "email",
attachmentType: "email",
value: "co-owner@example.com",
});After uploading the documents they already have (or even without uploading any), the partner must generate a biometrics session and present the URL to the customer. In the session, the customer submits remaining documents, captures the selfie, and confirms the submission.
The confirmation in the biometrics session triggers the evaluation of all documents, including those uploaded early via the API.
const session = await client.customers.createBiometricsSession(customer.id);
// Present this URL to the customer
console.log(session.session_url);
console.log(session.expires_at); // Expires in 30 minutesInfo: The biometrics session expires in 30 minutes. Generate a new session if it times out.
After confirmation in the biometrics session, each requirement goes through review. The submitted.review_status field indicates the outcome:
| Status | Description |
|---|---|
pending | Document submitted, awaiting review |
accepted | Document approved |
rejected | Document rejected. Check review_reason for details |
When a document is rejected, the submitted.review_reason field contains the reason. Upload a new document for the same requirement_id to replace the previous one.
The customer.kyc_updated webhook fires whenever a document is successfully submitted. The payload includes the updated kyc array with the state of all requirements.
When all mandatory requirements are accepted, the customer status advances to under_review and then to active.
| Requirement | evidence_type | Attachments | Formats | Subject | API Upload |
|---|---|---|---|---|---|
identity | cnh | front, back (physical) or file (digital) | JPEG, PNG or PDF | Person | Yes |
identity | rg | front, back | JPEG, PNG | Person | Yes |
selfie | selfie | photo | JPEG, PNG | Person | Biometrics only |
proof_of_address | proof_of_address | file | PDF, JPEG, PNG | Person | Yes |
company_document | ccmei | file | PDF, JPEG, PNG | Company | Yes |
ei_mei_documents | ei_mei | ei_registration_requirement, ccmei | PDF, JPEG, PNG | Company | Yes |
income_statement | income_statement | file | PDF, JPEG, PNG | Company | Yes |
articles_of_association | articles_of_association | file | PDF, JPEG, PNG | Company | Yes |
eireli_incorporation_statement | eireli_incorporation_statement | file | PDF, JPEG, PNG | Company | Yes |
email | email | email | text (value) | Person | Yes |
- Registration and Offers for the full onboarding flow
- Webhooks to configure notification endpoints