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

# KYC onboarding models and transaction flows

> Compare Supercosmos for Platforms KYC/AML models — Direct Onboard, Client via Platform, and Shared Onboard — with sequence diagrams and Pix settlement flows.

Supercosmos for Platforms supports three KYC/AML models. Choose the one that matches your existing compliance stack. The transaction settlement flow (Pix → stablecoin) is identical across all three; only the KYC step differs.

Each platform is responsible for assessing its own regulatory obligations.

> [!NOTE]
>
> All sequence diagrams below show the **SDK method calls** on the left and the **underlying API endpoints** on the right. The SDK is a thin wrapper — you can call the REST API directly if you prefer.

***

## Model 1 — Direct Onboard

Supercosmos runs the full KYC/AML flow. Your app collects CPF, selfie, and wallet address; Supercosmos handles everything else. Best for platforms launching without an existing KYC vendor.

**Who runs KYC:** Supercosmos

```mermaid theme={null}
sequenceDiagram
    autonumber
    actor User
    participant App as Platform App / Backend
    participant SDK as Supercosmos SDK
    participant API as Supercosmos API
    participant Sumsub
    participant BCB as BCB / Pix Network
    participant Wallet as User Wallet

    User->>App: Initiates Pix → stablecoin purchase
    App->>SDK: mippo.kyc.submit({ cpf, biometricHash, personType })
    SDK->>API: POST /v1/laas/kyc/submit
    API->>Sumsub: Biometric + document verification
    Sumsub-->>API: Verification result
    API->>API: Sanctions screening (OFAC / COAF / UN)
    API->>API: PEP classification
    API-->>SDK: { token, riskTier: "STANDARD" | "HIGH" | "PEP" }
    SDK-->>App: kycToken, riskTier

    App->>SDK: mippo.transactions.initiate({ kycToken, amountBrl, asset, walletAddress })
    SDK->>API: POST /v1/laas/transactions/initiate
    API-->>SDK: { transactionId, authChallenge }
    SDK-->>App: authChallenge

    alt riskTier = STANDARD → MFA (TOTP)
        App->>User: Prompt for TOTP code
        User->>App: Enters TOTP code
        App->>SDK: mippo.transactions.confirmMfa({ transactionId, totpCode })
        SDK->>API: POST /v1/laas/transactions/:id/mfa
        API-->>SDK: { pixPayload, pixQrCode }
        SDK-->>App: pixPayload
    else riskTier = HIGH or PEP → Liveness check
        App->>User: Redirect to authChallenge.livenessUrl
        User->>API: Completes liveness (Sumsub WebSDK)
        API-->>App: transaction.mfa_cleared webhook
        App->>SDK: mippo.transactions.status(transactionId)
        SDK->>API: GET /v1/laas/transactions/:id/status
        API-->>SDK: { status: "AWAITING_PIX", pixPayload }
        SDK-->>App: pixPayload
    end

    App->>User: Render Pix QR code / Copy-Paste string
    User->>BCB: Pays via Pix from any Brazilian bank
    BCB-->>API: Payment confirmed
    API->>API: KYT on-chain risk check on walletAddress
    API->>Wallet: Route stablecoin (USDT / USDC)
    API->>App: POST webhook: transaction.completed { txHash, amount, walletAddress }
    App->>User: Show confirmation
```

> [!TIP]
>
> In sandbox, use CPF `000.000.001-91` to force `riskTier: "HIGH"` and exercise the liveness path.

***

## Model 2 — Client via Platform

Your platform already runs KYC using your own vendor (e.g. Idwall, unico check, or Sumsub directly). Supercosmos accepts your KYC token, adds independent sanctions screening and KYT, then issues its own `kycToken` to proceed.

**Who runs KYC:** Platform (primary) + Supercosmos (independent screen)

```mermaid theme={null}
sequenceDiagram
    autonumber
    actor User
    participant App as Platform App / Backend
    participant PartnerKYC as Platform KYC Vendor
    participant SDK as Supercosmos SDK
    participant API as Supercosmos API
    participant BCB as BCB / Pix Network
    participant Wallet as User Wallet

    User->>App: Completes KYC on the platform
    App->>PartnerKYC: Standard KYC flow (CPF, document, liveness)
    PartnerKYC-->>App: partnerKycToken (vendor-issued)

    Note over App,API: Platform passes its KYC token to Supercosmos — no biometric re-submission needed

    App->>SDK: mippo.kyc.submit({ partnerKycToken, cpf, personType })
    SDK->>API: POST /v1/laas/kyc/submit
    API->>API: Validate partnerKycToken signature
    API->>API: Independent sanctions check (OFAC / COAF / UN)
    API->>API: PEP classification
    API-->>SDK: { token, riskTier }
    SDK-->>App: kycToken, riskTier

    App->>SDK: mippo.transactions.initiate({ kycToken, amountBrl, asset, walletAddress })
    SDK->>API: POST /v1/laas/transactions/initiate
    API-->>SDK: { transactionId, authChallenge }
    SDK-->>App: authChallenge

    alt riskTier = STANDARD → MFA (TOTP)
        App->>User: Prompt for TOTP code
        User->>App: Enters TOTP code
        App->>SDK: mippo.transactions.confirmMfa({ transactionId, totpCode })
        SDK->>API: POST /v1/laas/transactions/:id/mfa
        API-->>SDK: { pixPayload }
        SDK-->>App: pixPayload
    else riskTier = HIGH or PEP → Liveness (Supercosmos-owned)
        App->>User: Redirect to authChallenge.livenessUrl
        User->>API: Completes Supercosmos liveness check
        API-->>App: transaction.mfa_cleared webhook
        App->>SDK: mippo.transactions.status(transactionId)
        SDK->>API: GET /v1/laas/transactions/:id/status
        API-->>SDK: { pixPayload }
        SDK-->>App: pixPayload
    end

    App->>User: Render Pix QR code
    User->>BCB: Pays via Pix
    BCB-->>API: Payment confirmed
    API->>API: KYT wallet risk check
    API->>Wallet: Route stablecoin
    API->>App: POST webhook: transaction.completed
    App->>User: Show confirmation
```

> [!WARNING]
>
> A `partnerKycToken` does **not** bypass Supercosmos's independent screening. If Supercosmos detects a sanctions hit that your vendor missed, `kyc.submit` returns `KYC_REJECTED` with `reason: "SANCTIONS_HIT"`. See [Compliance Notes](https://laas.mippo.io/docs/guides/compliance.md) for details.

***

## Model 3 — Shared Onboard

Both layers contribute to KYC. Your app collects CPF and basic data; Supercosmos collects the biometric (via the Sumsub WebSDK embedded in your interface). A cross-check of both data sets produces the joint KYC result.

**Who runs KYC:** Platform (CPF + document) + Supercosmos (biometric + liveness)

```mermaid theme={null}
sequenceDiagram
    autonumber
    actor User
    participant App as Platform App / Backend
    participant SumsubWidget as Sumsub WebSDK (embedded)
    participant SDK as Supercosmos SDK
    participant API as Supercosmos API
    participant BCB as BCB / Pix Network
    participant Wallet as User Wallet

    User->>App: Starts onboarding
    App->>User: Collect CPF + document (platform-owned flow)
    User-->>App: CPF, document scan

    Note over App,SumsubWidget: Platform embeds Sumsub WebSDK for the biometric step only

    App->>SumsubWidget: Launch liveness / selfie capture
    User->>SumsubWidget: Completes biometric capture
    SumsubWidget-->>App: biometricHash (from Sumsub callback)

    App->>SDK: mippo.kyc.submit({ cpf, biometricHash, personType, mode: "shared" })
    SDK->>API: POST /v1/laas/kyc/submit
    API->>API: Cross-check CPF (platform data) vs biometric (Supercosmos/Sumsub data)
    API->>API: Sanctions screening (OFAC / COAF / UN)
    API->>API: PEP classification
    API-->>SDK: { token, riskTier }
    SDK-->>App: kycToken, riskTier

    App->>SDK: mippo.transactions.initiate({ kycToken, amountBrl, asset, walletAddress })
    SDK->>API: POST /v1/laas/transactions/initiate
    API-->>SDK: { transactionId, authChallenge }
    SDK-->>App: authChallenge

    alt riskTier = STANDARD → MFA (TOTP)
        App->>User: Prompt for TOTP code
        User->>App: Enters TOTP code
        App->>SDK: mippo.transactions.confirmMfa({ transactionId, totpCode })
        SDK->>API: POST /v1/laas/transactions/:id/mfa
        API-->>SDK: { pixPayload }
        SDK-->>App: pixPayload
    else riskTier = HIGH or PEP → Additional liveness required
        App->>User: Redirect to authChallenge.livenessUrl
        User->>API: Completes additional liveness check
        API-->>App: transaction.mfa_cleared webhook
        App->>SDK: mippo.transactions.status(transactionId)
        SDK->>API: GET /v1/laas/transactions/:id/status
        API-->>SDK: { pixPayload }
        SDK-->>App: pixPayload
    end

    App->>User: Render Pix QR code
    User->>BCB: Pays via Pix
    BCB-->>API: Payment confirmed
    API->>API: KYT wallet risk check
    API->>Wallet: Route stablecoin
    API->>App: POST webhook: transaction.completed
    App->>User: Show confirmation
```

> [!NOTE]
>
> In Shared mode, Supercosmos generates a Sumsub `applicantId` for you when you call `kyc.submit`. You only need to pass `biometricHash` — the SDK handles the Sumsub embedding automatically.

***

## Transaction states

Regardless of model, every transaction passes through the same state machine after KYC clears:

```mermaid theme={null}
stateDiagram-v2
    [*] --> CREATED: transactions.initiate()
    CREATED --> AWAITING_MFA: Auth challenge issued
    AWAITING_MFA --> AWAITING_PIX: MFA / liveness cleared
    AWAITING_PIX --> PROCESSING: Pix payment detected
    PROCESSING --> COMPLETED: Stablecoin settled on-chain
    PROCESSING --> FAILED: Settlement error (auto-retry x3)
    AWAITING_MFA --> EXPIRED: No MFA response within 15 min
    AWAITING_PIX --> EXPIRED: No Pix payment within 30 min
    FAILED --> [*]
    EXPIRED --> [*]
    COMPLETED --> [*]
```

Poll `mippo.transactions.status(transactionId)` or listen for webhooks — see the [Webhooks guide](https://laas.mippo.io/docs/guides/webhooks.md) for the event reference.


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