Skip to main content

Legal Person Onboarding

Complete flow for onboarding a Legal Person through the BaaS API.

Flow Overview

Execute steps 1-7 in order. Step 8 happens while the onboarding is IN_PROCESS: every legal representative's liveness is verified either through an individual capture link or through a video you upload for each one. If you choose the video, upload one video per representative before Step 7 (see Step 8).


Step 1: Create User Account

POST /users/accounts

Create user account as Legal Person with CNPJ.

Returns: id

Note: If a previous onboarding was REJECTED or FAILED, reuse the existing id and skip to Step 2.


Step 2: Create Onboarding

POST /users/onboardings/legal-person

Create onboarding record with legal person address and revenue.

Returns: id → Save for Steps 6, 7 and 8

Note: Cannot create if user already has an onboarding in any status other than REJECTED, FAILED or EXPIRED. Can create new if previous was REJECTED, FAILED or EXPIRED.


Step 3: Create Shareholders

POST /users/shareholders

Register shareholders. Can be Natural Person (CPF) or Legal Person (CNPJ).

Returns: id → Save for Step 4

Requirements:

  • At least one shareholder
  • If shareholder is Natural Person (CPF), the document must match the legal representative's document created in Step 4
  • Legal Person (CNPJ) shareholders must have at least one legal representative linked to them (validated at finalization)
  • Total participation_percentage ≤ 100%

POST /users/legal-representatives

Register legal representatives. Must be Natural Person with CPF.

Requires: shareholder_id from Step 3

Returns: id → Save for Steps 5 and 8

Requirements:

  • Must be Natural Person (CPF)
  • Must link to a shareholder of the same onboarding via shareholder_id (Natural Person or Legal Person shareholder)
  • If the linked shareholder is Natural Person, its document must match the representative's document
  • At least one legal representative required

Step 5: Upload Representative Documents

POST /users/legal-representatives/{id}/documents

Upload documents for each legal representative (multipart/form-data).

Required:

  • selfie (file)
  • identity_document (file)
  • identity_document_type (enum: id, cnh, passport)
  • qualification_declaration (file)

Optional:

  • income_declaration (file)
  • address_proof (file)

Requirements:

  • Upload for ALL legal representatives
  • Max 25 MB per file
  • Formats: PDF, JPEG, JPG
  • If the representatives' liveness will be verified by video (see Step 8), send identity_document as a JPEG image up to 5 MB for every representative. A PDF or a larger image makes the finalization fail with 422 (INVALID_FORMAT)

POST /users/onboardings/legal-person/{id}/documents

Upload legal person documents. Call once per document type.

Body:

  • file (binary)
  • type (enum)

Required types:

  • SOCIAL_CONTRACT
  • BALANCE_SHEET OR REVENUE_STATEMENT (at least one)

Optional:

  • KYC_AML_POLICY

Requirements:

  • Max 10 MB per file
  • Formats: PDF, JPEG, JPG

Step 7: Finalize

POST /users/onboardings/legal-person/{id}/finalize

Submit onboarding for processing.

Returns: Status changes to IN_PROCESS

Validation:

  • ✓ Onboarding exists and is in PENDING status
  • ✓ At least one shareholder created
  • ✓ At least one legal representative created
  • ✓ All legal representatives are Natural Person
  • ✓ All legal representatives linked to a shareholder of this onboarding
  • ✓ Every Legal Person (CNPJ) shareholder has at least one linked legal representative
  • ✓ All legal representatives have uploaded: selfie, identity_document, qualification_declaration
  • ✓ Legal person has uploaded: SOCIAL_CONTRACT
  • ✓ Legal person has uploaded: BALANCE_SHEET or REVENUE_STATEMENT
  • ✓ Total shareholder participation does not exceed 100%
  • ✓ If a liveness video was uploaded for any representative: every active representative has a video (LEGAL_REPRESENTATIVE_LIVENESS_VIDEOS_INCOMPLETE), every representative's identity_document is a JPEG image up to 5 MB (INVALID_FORMAT), and liveness is enabled for your product (ONBOARDING_LIVENESS_NOT_REQUIRED)

If validation fails: Returns 422 with error details. Fix and retry.

After finalization, the onboarding stays IN_PROCESS while the legal person data is analyzed and the legal representatives' liveness is verified (Step 8).


While the onboarding is IN_PROCESS, every legal representative's liveness (facial capture) is verified individually. There are two ways to provide it:

MethodHow the capture happensWhen you act
LINK (default)Each representative completes the capture through a dedicated link we issueAfter finalization, when the links are released
VIDEO_UPLOADYou record each representative's liveness video and upload itBefore finalization (between Step 6 and Step 7)

The method is one or the other for the whole onboarding. You never declare it: uploading a video for any representative selects VIDEO_UPLOAD for all of them, and finalization then requires one video per active representative. Without any video, every representative receives a link. The choice is locked at finalization — a first video is refused after that point (422, LEGAL_REPRESENTATIVE_LIVENESS_METHOD_LOCKED). The method field of the progress endpoint tells which one is in effect.

Note: This step applies only when liveness is enabled for your product. If it is not enabled, the onboarding proceeds without this step, the liveness endpoints return 422, and a finalization with uploaded videos is refused (ONBOARDING_LIVENESS_NOT_REQUIRED).

  1. The legal person analysis is approved
  2. An individual liveness link is created for every active legal representative
  3. The ONBOARDING_LEGAL_REPRESENTATIVE_LIVENESS_RELEASED webhook delivers the links — normally all of them in a single notification
  4. Deliver each link to its legal representative — the representative opens it and completes the facial capture
  5. Each approval fires the ONBOARDING_LEGAL_REPRESENTATIVE_LIVENESS_UPDATED webhook with status APPROVED
  6. Once every representative is approved, the onboarding proceeds toward FINISHED

Integration rules:

  • Delivering each link to its representative is your responsibility — no notification is sent to them
  • Links are individual per representative. Capture links do not have an automatic expiration of their own and can be reused to resume an interrupted capture. This does not keep the onboarding open: if a capture deadline applies to your integration, the onboarding may be rejected when it passes without submission. Check the current onboarding status before delivering or reusing a link
  • The RELEASED webhook may be delivered more than once — the payload always carries the current full set of links, so process it idempotently and use the progress endpoint as the source of truth for who has a link
  • PENDING with no url is normal, not an error — the legal person analysis has not been approved yet
  • Do not wait for an intermediate webhook notification — with the links, only APPROVED is announced
  • Treat url and name as sensitive data — the link grants access to the liveness capture and the name is personal data

Method B — Video upload

POST /v2/users/onboardings/{id}/legal-representatives/{legal_representative_id}/liveness/video

Upload the liveness video of one legal representative, recorded by your own capture flow (multipart/form-data). Call it once per representative. Paths shown without a version prefix elsewhere in this guide are version 1 (/v1/...); this endpoint exists only in version 2.

Availability: video upload must be enabled for your integration. When it is not, the upload returns 422 (ONBOARDING_LIVENESS_VIDEO_DISABLED).

When: after the representative is created (Step 4) and before finalization (Step 7), while the onboarding is PENDING.

Body:

  • video (file, required) — MP4 (video/mp4) or MOV (video/quicktime), max 50 MB by default; maximum resolution: 8,294,400 pixels per frame (width × height, e.g. 3840 × 2160)
  • liveness_provider (string, required, max 255) — name of the solution that recorded and verified the liveness (yours or a third party's)
  • liveness_provider_transaction_id (string, required, max 255) — identifier of that capture at the provider, kept as an audit reference
  • captured_at (string, required) — capture instant in YYYY-MM-DDTHH:mm:ss.SSSZ format (e.g. 2026-08-30T12:00:00.000Z). It cannot be in the future and must be within the last 24 hours, or a shorter capture window agreed for your integration

Returns (201):

  • id — liveness video ID
  • onboarding_id
  • legal_representative_id
  • file_id — stored video file ID
  • state — processing state returned by this request: UPLOADED (received), PROCESSING (under analysis), COMPLETED (analysis finished) or FAILED (analysis could not be completed)
  • captured_at, created_at

201 confirms the upload request was accepted; it does not approve liveness. COMPLETED also does not mean approval. Use the liveness progress endpoint for the liveness result and the onboarding status endpoint for the overall outcome. A retry of the same video after a processing failure may return the existing video ID, file ID and original timestamps. Do not assume that every 201 creates a new submission; use the returned identifiers and current progress to reconcile retries.

How it works:

  1. Upload one video per active representative while the onboarding is PENDING — each upload fires ONBOARDING_LEGAL_REPRESENTATIVE_LIVENESS_UPDATED with status PENDING for that representative
  2. Make sure every representative's identity_document (Step 5) is a JPEG image up to 5 MB
  3. Finalize (Step 7) — the onboarding enters IN_PROCESS
  4. Once the legal person analysis is approved, the videos are analysed. No links are issued and no RELEASED webhook is sent
  5. Each representative's result arrives through ONBOARDING_LEGAL_REPRESENTATIVE_LIVENESS_UPDATED:
    • APPROVED — done for this representative
    • REJECTED — the onboarding becomes REJECTED (ONBOARDING_REJECTED webhook, with rejected_legal_representative_id); create a new onboarding
    • IN_ANALYSIS — further analysis is needed; wait for a later APPROVED or REJECTED
    • WAITING_SUBMISSION — the video could not be analysed; upload a new one for this representative
  6. Once every representative is approved, the onboarding proceeds toward FINISHED

Integration rules:

  • One video per representative. An existing video can be replaced only if its processing failed and both the onboarding and that representative's liveness step still allow another submission. Use WAITING_SUBMISSION to identify who needs a new video, and confirm that the onboarding is still open. An ineligible replacement returns 422 (ONBOARDING_LIVENESS_VIDEO_ALREADY_UPLOADED or ONBOARDING_LIVENESS_ALREADY_COMPLETED)
  • Methods cannot be mixed: once one representative has a video, representatives without one block the finalization (LEGAL_REPRESENTATIVE_LIVENESS_VIDEOS_INCOMPLETE)
  • The result is asynchronous — do not resend while the status is PENDING or IN_ANALYSIS
  • If the upload times out, check liveness progress before retrying: the video may already have been accepted
  • A closed (FINISHED, REJECTED, FAILED, EXPIRED) onboarding does not accept uploads, even if its last liveness status is WAITING_SUBMISSION

Errors:

  • 400 — invalid parameters (e.g. malformed captured_at)
  • 403 — onboarding does not belong to the authenticated user
  • 422 — see the table below
CodeMeaning
ONBOARDING_LIVENESS_VIDEO_DISABLEDVideo upload is not enabled for your integration
LEGAL_REPRESENTATIVE_LIVENESS_METHOD_LOCKEDOnboarding already finalized — a first video is no longer accepted
ONBOARDING_LIVENESS_VIDEO_ALREADY_UPLOADEDThis representative already has a video that is not eligible for replacement
ONBOARDING_LIVENESS_ALREADY_COMPLETEDThis representative's liveness was already concluded
ONBOARDING_LIVENESS_VIDEO_TOO_OLDcaptured_at is outside the accepted capture window (24 hours by default)
ONBOARDING_LIVENESS_VIDEO_CAPTURED_IN_FUTUREcaptured_at is in the future
ONBOARDING_LIVENESS_NOT_REQUIREDLiveness is not enabled for this onboarding
ONBOARDING_INVALID_STATUSThis onboarding is not eligible for uploads. Check its current status before proceeding; a liveness status of WAITING_SUBMISSION alone does not authorize another upload
USER_LEGAL_REPRESENTATIVE_NOT_FOUNDThe representative does not belong to this onboarding
FILE_IS_REQUIRED, FILE_FORMAT, FILE_SIZEMissing video, unsupported format or file over the upload limit (50 MB by default)

Checking Liveness Progress

GET /v2/users/onboardings/{id}/legal-representatives/liveness

Lists every legal representative of the onboarding with their individual liveness progress and, for the link method, their link. Use it to know who is still pending.

Response (array, one item per representative):

  • id — legal representative ID
  • name — legal representative name
  • methodLINK or VIDEO_UPLOAD
  • url — individual liveness link (LINK only; absent while the link has not been created yet)
  • status — liveness progress (see table below)
  • submitted_at — submission timestamp, when available; its absence does not mean that no video was received
StatusLINKVIDEO_UPLOADAction
PENDINGNo link yet — the legal person analysis still has to be approvedVideo received, not analysed yetWait
WAITING_SUBMISSIONLink issued, the representative has not completed the livenessNo video for this representative yet (before finalization), or the video could not be analysedDeliver the link / upload a video
IN_ANALYSISSubmitted, result not confirmed yetVideo under analysisWait
APPROVEDLiveness completedLiveness completedDone for this representative
REJECTEDLiveness rejected; the onboarding becomes REJECTEDCreate new onboarding

With VIDEO_UPLOAD, the endpoint already answers before finalization once at least one video was sent, so you can check which representatives are still missing theirs.

Webhooks:

  • ONBOARDING_LEGAL_REPRESENTATIVE_LIVENESS_RELEASED — all links created (LINK only), payload contains one entry per representative (legal_representative_id, name, url)
  • ONBOARDING_LEGAL_REPRESENTATIVE_LIVENESS_UPDATED — per-representative progress, payload contains legal_representative_id, status and optional submitted_at. With the links only APPROVED is announced; video upload can announce PENDING, IN_ANALYSIS, WAITING_SUBMISSION, APPROVED and REJECTED. Do not require an event for every intermediate status. Process repeated notifications idempotently and use the endpoint above as the source of truth

Integration rules:

  • If a representative fails identity verification, the onboarding becomes REJECTED and rejected_legal_representative_id in the status endpoint identifies which representative caused it

Errors:

  • 422 — onboarding not found, not yet finalized without any video, or it does not require legal representative liveness
  • 403 — onboarding does not belong to the authenticated user

Checking Status

GET /users/onboardings/legal-person/{id}

Use this endpoint to check the current onboarding status.

Status flow:

PENDING → IN_PROCESS → FINISHED / REJECTED / FAILED
StatusMeaningAction
PENDINGIncompleteComplete steps 1-7
IN_PROCESSProcessing — legal representatives may still need to complete livenessFollow Step 8
FINISHEDApprovedProceed
REJECTEDNot approvedCreate new onboarding
FAILEDErrorContact support
EXPIREDOnboarding expired after long inactivityCreate new onboarding

Webhooks:

If webhooks are configured, you will receive notifications for:

  • ONBOARDING_LEGAL_REPRESENTATIVE_LIVENESS_RELEASED - Liveness links created for all legal representatives
  • ONBOARDING_LEGAL_REPRESENTATIVE_LIVENESS_UPDATED - Liveness progress of a legal representative
  • ONBOARDING_FINISHED - Onboarding approved
  • ONBOARDING_REJECTED - Onboarding not approved
  • ONBOARDING_FAILED - Processing error

See Webhooks for payload examples and delivery details.

Use webhooks for notifications and this endpoint to confirm the current onboarding status. Liveness approval alone does not mean that the onboarding is FINISHED.


Error Handling

422 on finalization:

  • Response contains missing requirements
  • Fix and retry

REJECTED:

  • Create new onboarding with corrected data

FAILED:

  • Contact support with onboarding ID