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

# Onboarding Documents Integration

> End-to-end guide to integrate the document-based onboarding flow: create the solicitation, receive the required documents by webhook, upload them, track the review, and finish through signature (national) or bank channel (cross-border).

<Info>
  This flow is rolled out **per merchant** through a feature flag — **off by default**. It only applies when the company is created with a **segment**.

  Merchants without the flag enabled continue on the [legacy onboarding flow](/api-reference/account/webhook/webhook-onboarding) (which goes through `due_diligence_review`).
</Info>

## Overview

In the document-based onboarding, WEpayments tells your integration **exactly which documents** the company must send — resolved from its **segment** and **modality** (national / cross-border). You receive that list through the onboarding webhook, upload the files, and the solicitation advances automatically to review once every **required** document is sent.

After compliance approves the documents, the flow **branches by modality** (derived from the company address country — see [Modality](#modality-national-vs-cross-border)):

* **National** — the legal representatives sign the contract, then the account is created.
* **Cross-border** — WEpayments opens the bank channel, then the account is created. No signature step.

| Step                                   | What you do                                                                     | Endpoint / channel                                                                                    |
| -------------------------------------- | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| 1. Register the webhook                | Subscribe to onboarding status updates **before** opening the solicitation      | [`POST /v2/register/webhooks`](/api-reference/account/webhook/webhook-setup)                          |
| 2. Create the solicitation             | Open the corporate account **with a `segment`**                                 | [`POST /v2/register/companies`](/api-reference/account/create)                                        |
| 3. Receive the required documents      | Read the `documents` list delivered when the status becomes `pending_documents` | [Onboarding webhook](/api-reference/account/webhook/onboarding-documents)                             |
| 4. Upload the documents                | Send each file by its `tag`                                                     | [`POST /v2/register/companies/{uuid}/documents`](/api-reference/account/documents/upload-document)    |
| 5. Track the review                    | Read the current state and decision history of each document                    | [`GET /v2/register/companies/{uuid}/documents`](/api-reference/account/documents/list-documents)      |
| 6. Sign the contract *(national only)* | Route each representative to their signing link                                 | [`GET /v2/register/companies/{uuid}/signature/link`](/api-reference/account/signature/signature-link) |

<Note>
  The compliance review (approve / reject), the bank channel opening (cross-border) and the account creation are performed **internally** by WEpayments — there is no client-facing endpoint for them. Their outcome reaches you through the onboarding **webhook**.
</Note>

## Status Flow

```mermaid theme={null}
graph LR
    A[pending] --> B[pending_documents]
    B --> C[documents_under_review]
    C -->|rejection| B
    C -->|close| E[canceled]
    C -->|national| S[waiting_signature]
    C -->|cross-border| K[waiting_bank_channel]
    S -->|signed| D[active]
    K --> L[bank_channel_created]
    L --> D[active]
    D --> F[inactive]
    D --> G[closed]

    style A fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#000
    style B fill:#ede9fe,stroke:#8b5cf6,stroke-width:2px,color:#000
    style C fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#000
    style S fill:#ffedd5,stroke:#f97316,stroke-width:2px,color:#000
    style K fill:#cffafe,stroke:#06b6d4,stroke-width:2px,color:#000
    style L fill:#ccfbf1,stroke:#14b8a6,stroke-width:2px,color:#000
    style D fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#000
    style E fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#000
    style F fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#000
    style G fill:#f3f4f6,stroke:#6b7280,stroke-width:2px,color:#000
```

| Status                   | Meaning                                                                                                                                                                                                                                       |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pending`                | Solicitation received and awaiting processing.                                                                                                                                                                                                |
| `pending_documents`      | The required documents were resolved from the company's segment + modality and attached to the solicitation. The webhook for this status carries the `documents` list. The solicitation stays here until **all required** documents are sent. |
| `documents_under_review` | Every required document was sent. Compliance is reviewing them.                                                                                                                                                                               |
| `waiting_signature`      | *National only.* Documents approved; the contract is awaiting signature by the legal representatives.                                                                                                                                         |
| `waiting_bank_channel`   | *Cross-border only.* Documents approved; WEpayments is opening the bank channel.                                                                                                                                                              |
| `bank_channel_created`   | *Cross-border only.* The bank channel was created; the account is being finalized.                                                                                                                                                            |
| `active`                 | The account was created. The webhook delivers the `account_id` (MID — Merchant ID).                                                                                                                                                           |
| `canceled`               | Onboarding did not proceed (e.g. compliance closed the review).                                                                                                                                                                               |
| `inactive` / `closed`    | Terminal states of an account that was previously `active`.                                                                                                                                                                                   |

<Note>
  A `reject` decision sends the solicitation **back to `pending_documents`**, keeping the already‑approved documents untouched, so the client only needs to resend the rejected ones.
</Note>

## Modality: national vs cross-border

The modality is **derived from the company address country**, not sent as an input:

* `address.country` = `BR` → **national** (contract signature step).
* `address.country` ≠ `BR` → **cross-border** (bank channel step, no signature).

The modality also affects which documents are required (segment + modality), so the `documents` list you receive already matches the company's modality.

## Document fields

Each requested document carries two independent state machines:

| Field           | Owner                       | Values                              |
| --------------- | --------------------------- | ----------------------------------- |
| `upload_status` | **Client** (via upload)     | `pending` → `sent`                  |
| `review_status` | **Compliance** (via review) | `pending` → `approved` / `rejected` |

A document is only uploadable when `upload_status` is `pending` **or** `review_status` is `rejected`. Approved documents cannot be replaced.

## Step-by-step

<Steps>
  <Step title="Register the onboarding webhook">
    Subscribe to onboarding updates with [Webhook Setup](/api-reference/account/webhook/webhook-setup) **before opening the solicitation** — this way you won't miss the `pending_documents` event, which is fired right after the solicitation is processed and carries the list of required documents. Every status change is delivered to your URL, which must answer `200 OK`; otherwise delivery is retried **up to 3 times, every 15 minutes**.

    <Warning>
      Register the webhook first. If you create the solicitation before subscribing, you may miss the `pending_documents` notification. You can still recover the list with [List Documents](/api-reference/account/documents/list-documents), but reacting to the webhook is the intended flow.
    </Warning>
  </Step>

  <Step title="Create the solicitation with a segment">
    Open the corporate account through [`POST /v2/register/companies`](/api-reference/account/create), including the `segment` object. Use [List Segments](/api-reference/account/segments/list-segments) to obtain a valid `segment.id`. The solicitation is created with status `pending`.

    ```json Request (excerpt) theme={null}
    {
      "legal_name": "Company X LTDA",
      "trade_name": "Company X",
      "tax_id": "12345678000199",
      "segment": { "id": 7 },
      "address": { "country": "BR", "...": "..." }
    }
    ```

    <Warning>
      Without a `segment`, the document flow does **not** run — the solicitation stays on the flow configured for the merchant. The segment must reference an existing segment, otherwise the request fails with `422`. The `address.country` defines the modality (national vs cross-border).
    </Warning>
  </Step>

  <Step title="Receive the required documents (pending_documents)">
    Once the solicitation is processed, its status becomes `pending_documents` and the webhook payload includes the `documents` array — the exact list the client must send.

    ```json Webhook theme={null}
    {
      "id": "1234-5678-90ab-cdef-1234567890ab",
      "status": "pending_documents",
      "updated_at": "2024-01-15T10:30:00.000000Z",
      "account_id": null,
      "documents": [
        {
          "name": "Articles of Incorporation",
          "tag": "articles_of_incorporation",
          "description": "Company's current articles of incorporation",
          "required": true,
          "upload_status": "pending",
          "review_status": "pending"
        }
      ]
    }
    ```

    Store each `tag` — it is the identifier you use to upload the matching file.
  </Step>

  <Step title="Upload the documents (partial or complete)">
    Send each file with [`POST /v2/register/companies/{uuid}/documents`](/api-reference/account/documents/upload-document) as `multipart/form-data` (`tag` + `file`). You may upload in several calls. Each successful upload sets that document's `upload_status` to `sent` and triggers the onboarding webhook with the updated state.

    Accepted files: **pdf, jpg, jpeg, png**, up to **10 MB**.
  </Step>

  <Step title="Automatic transition to review">
    After every upload, WEpayments checks whether **all required** documents are `sent`. When they are, the solicitation moves automatically to `documents_under_review` — **optional documents do not block** this transition. The webhook fired by that last upload already reflects the new status.
  </Step>

  <Step title="Compliance reviews the documents">
    Compliance approves or rejects each document. You are notified through the webhook:

    * **All approved →** the flow branches by modality: **national** moves to `waiting_signature`; **cross-border** moves to `waiting_bank_channel`.
    * **Any rejection →** the solicitation goes back to `pending_documents`; the rejected document returns to `upload_status: pending` / `review_status: rejected` (with a `reason`), while approved documents are preserved.
    * **Review closed →** the solicitation becomes `canceled`.
  </Step>

  <Step title="Sign the contract — national only (waiting_signature)">
    When the status is `waiting_signature`, fetch the signing links with [`GET /v2/register/companies/{uuid}/signature/link`](/api-reference/account/signature/signature-link) and route **each signer** to their `sign_url` (ZapSign). Once every signer has signed, WEpayments creates the account and the solicitation moves to `active`.

    You can download the signed contract at any time with `GET /v2/register/companies/{uuid}/signature/file`.

    <Note>
      Cross-border solicitations skip this step — there is no signature. Calling the signature endpoints for a cross-border solicitation returns `404`.
    </Note>
  </Step>

  <Step title="Bank channel opening — cross-border only (waiting_bank_channel)">
    When the status is `waiting_bank_channel`, WEpayments opens the bank channel internally. There is nothing to do on the merchant side — just watch the webhook: the solicitation moves to `bank_channel_created` and then to `active`.
  </Step>

  <Step title="Account activation (active)">
    When the status becomes `active`, the webhook delivers the `account_id` (MID — Merchant ID). The account is ready to transact.
  </Step>
</Steps>

## Tracking the documents

At any time you can call [`GET /v2/register/companies/{uuid}/documents`](/api-reference/account/documents/list-documents) to read the current state of every document and its immutable `review_history` (approvals and rejections, newest first). This is a **read-only** call — it never changes the solicitation status.

```json Response (excerpt) theme={null}
{
  "id": "1234-5678-90ab-cdef-1234567890ab",
  "status": "documents_under_review",
  "documents": [
    {
      "tag": "articles_of_incorporation",
      "upload_status": "sent",
      "review_status": "approved",
      "review_history": [
        { "action": "approved", "timestamp": "2024-01-18T10:00:00.000000Z" },
        { "action": "rejected", "timestamp": "2024-01-16T10:00:00.000000Z", "reason": "Illegible document" }
      ]
    }
  ]
}
```

## Best practices

<AccordionGroup>
  <Accordion title="Always drive the upload from the webhook's tags">
    Don't hardcode the document list — it depends on the company's segment and modality. Read the `documents` array from the `pending_documents` webhook (or from the documents query) and upload each file by its `tag`. An unknown tag is rejected with `422`.
  </Accordion>

  <Accordion title="Handle partial uploads">
    Required documents can be sent across multiple calls. The solicitation only advances to `documents_under_review` when **all required** documents are `sent`. Optional documents never block the transition.
  </Accordion>

  <Accordion title="React to rejections automatically">
    On a rejection, the solicitation returns to `pending_documents` and the webhook carries the rejected document with its `reason`. Surface that `reason` to the client and allow a resend of the same `tag`.
  </Accordion>

  <Accordion title="Branch your handling by status, not by assumption">
    After approval the next status depends on modality: `waiting_signature` (national) or `waiting_bank_channel` (cross-border). Only the national branch requires action from you (routing signers to their `sign_url`); the cross-border branch is fully handled by WEpayments.
  </Accordion>

  <Accordion title="Make your webhook idempotent">
    A webhook is fired on every upload and every status change, so you may receive several events for the same solicitation. Use `id` + `status` (and the per-document state) to reconcile, and always answer `200 OK`. The `documents` array is only present in `pending_documents`, `documents_under_review` and `canceled`.
  </Accordion>
</AccordionGroup>

## Related resources

<CardGroup cols={2}>
  <Card title="Create Company" icon="building" href="/api-reference/account/create">
    Open the solicitation with a segment
  </Card>

  <Card title="Onboarding Webhook" icon="webhook" href="/api-reference/account/webhook/onboarding-documents">
    Payload and statuses delivered to your URL
  </Card>

  <Card title="Upload Document" icon="file-arrow-up" href="/api-reference/account/documents/upload-document">
    Send the required files by tag
  </Card>

  <Card title="List Documents" icon="list-check" href="/api-reference/account/documents/list-documents">
    Query state and review history
  </Card>

  <Card title="Get Signature Link" icon="signature" href="/api-reference/account/signature/signature-link">
    Route representatives to sign the contract (national)
  </Card>
</CardGroup>
