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

# User Data & Friction

> Understand the trade-off between integration effort and user experience

## The core trade-off

When integrating with M2M, you control how much user data you provide upfront. This creates a fundamental trade-off:

```mermaid theme={null}
quadrantChart
    title Integration Approach vs User Experience
    x-axis Low Integration Effort --> High Integration Effort
    y-axis High User Friction --> Low User Friction
    quadrant-1 Best UX
    quadrant-2 Not Achievable
    quadrant-3 Quick Start
    quadrant-4 Good Balance
    Full Data Upfront: [0.85, 0.9]
    Webhook Fallback: [0.55, 0.7]
    Minimal: [0.15, 0.2]
```

| Approach              | Integration Effort | User Friction | Description                                            |
| --------------------- | ------------------ | ------------- | ------------------------------------------------------ |
| **Full data upfront** | High               | None          | Provide all user data when creating the link           |
| **Webhook fallback**  | Medium             | Low           | Provide partial data, respond to webhooks for the rest |
| **Minimal**           | Low                | High          | Only provide `referenceId`, users enter everything     |

## Understanding friction

"Friction" refers to the steps a user must complete before making a transaction:

<AccordionGroup>
  <Accordion title="Zero friction (full data upfront)">
    User opens link and immediately sees:

    * Pre-filled personal information
    * Pre-filled payment method
    * Ready to confirm transaction

    No forms to fill, no ID verification prompts.
  </Accordion>

  <Accordion title="Low friction (webhook fallback)">
    User opens link and sees:

    * Some pre-filled information
    * May need to confirm or add minor details
    * Quick verification step if needed

    Fast completion, minimal input required.
  </Accordion>

  <Accordion title="High friction (minimal integration)">
    User opens link and must:

    * Enter full legal name (all parts)
    * Enter government ID number
    * Enter date of birth
    * Complete full CIP verification
    * Add payment method

    More steps = higher abandonment risk.
  </Accordion>
</AccordionGroup>

## Data fields and their impact

### Required CIP fields

M2M requires these fields for identity verification (CIP). Each missing field increases friction:

| Field                 | Description                     | Impact if missing                      |
| --------------------- | ------------------------------- | -------------------------------------- |
| `name.firstName`      | First name                      | User enters manually                   |
| `name.secondName`     | Middle name / second first name | User enters manually                   |
| `name.lastName`       | Primary surname                 | User enters manually                   |
| `name.secondLastName` | Secondary surname (maternal)    | User enters manually                   |
| `idNumber`            | Government ID (e.g., CURP)      | User enters + may need ID verification |
| `idType`              | Type of ID document             | User selects from list                 |
| `dob`                 | Date of birth                   | User enters with date picker           |

### Optional but valuable

| Field           | Description                                                                                          | Impact                              |
| --------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------- |
| `paymentMethod` | Payment destination — required when `userData` is provided (see [Payment Methods](#payment-methods)) | User adds payment method if missing |
| `idImage`       | ID document photo (base64)                                                                           | May skip photo capture step         |

### Payment methods

The `paymentMethod` field uses a flexible structure to support different payment types and countries:

<AccordionGroup>
  <Accordion title="Bank Account">
    For bank transfers, include the `country` code (ISO 3166-1 alpha-2) and the appropriate account identifier:

    **Mexico (CLABE)**

    ```json theme={null}
    {
      "paymentMethod": {
        "type": "bank_account",
        "bankAccount": {
          "country": "MX",
          "accountNumber": "012345678901234567"
        }
      }
    }
    ```

    **Argentina (CBU)**

    ```json theme={null}
    {
      "paymentMethod": {
        "type": "bank_account",
        "bankAccount": {
          "country": "AR",
          "accountNumber": "0110599940000041079153"
        }
      }
    }
    ```

    **Colombia**

    ```json theme={null}
    {
      "paymentMethod": {
        "type": "bank_account",
        "bankAccount": {
          "country": "CO",
          "accountNumber": "12345678901234",
          "accountType": "savings",
          "bankCode": "007"
        }
      }
    }
    ```

    | Field                       | Required | Description                                               |
    | --------------------------- | -------- | --------------------------------------------------------- |
    | `type`                      | Yes      | Must be `bank_account`                                    |
    | `bankAccount.country`       | Yes      | ISO 3166-1 alpha-2 country code                           |
    | `bankAccount.accountNumber` | Yes      | Account identifier (CLABE, CBU, IBAN, etc.)               |
    | `bankAccount.accountType`   | No       | `savings` or `checking` (required for some countries)     |
    | `bankAccount.bankCode`      | No       | Bank code or routing number (required for some countries) |
  </Accordion>

  <Accordion title="Card">
    For card-based payouts, card data must be sent through the VGS Inbound Proxy for PCI compliance. The M2M API only accepts tokenized card numbers.

    ```json theme={null}
    {
      "paymentMethod": {
        "type": "card",
        "card": {
          "number": "tok_sandbox_4fKq8H2xLmNpRtYw",
          "expiryMonth": "12",
          "expiryYear": "2028",
          "cardholderName": "Juan García",
          "last4": "4242",
          "brand": "visa"
        }
      }
    }
    ```

    <Warning>
      Card numbers must be routed through the VGS Inbound Proxy. Never send raw PANs directly to the M2M API. Contact your M2M integration specialist for VGS proxy configuration.
    </Warning>

    | Field                 | Required | Description                                        |
    | --------------------- | -------- | -------------------------------------------------- |
    | `type`                | Yes      | Must be `card`                                     |
    | `card.number`         | Yes      | VGS-tokenized card number (`tok_xxx`)              |
    | `card.expiryMonth`    | Yes      | Expiry month (`01`-`12`)                           |
    | `card.expiryYear`     | Yes      | Expiry year (4 digits, e.g., `2028`)               |
    | `card.cardholderName` | No       | Name as it appears on the card                     |
    | `card.last4`          | No       | Last 4 digits (VGS can extract this automatically) |
    | `card.brand`          | No       | Card brand (`visa`, `mastercard`, `amex`, etc.)    |
  </Accordion>

  <Accordion title="Cash Pickup (Future)">
    For cash pickup at physical locations (coming soon):

    ```json theme={null}
    {
      "paymentMethod": {
        "type": "cash",
        "cash": {
          "provider": "oxxo"
        }
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Choose your approach

### Option 1: Full data upfront

**Best for:** Partners with complete KYC data already collected

Provide all user data when creating the link:

```json theme={null}
{
  "referenceId": "user_12345",
  "userData": {
    "name": {
      "firstName": "Juan",
      "secondName": "Carlos",
      "lastName": "Garcia",
      "secondLastName": "Lopez"
    },
    "idNumber": "GALO900515HDFRPN09",
    "idType": "CURP",
    "dob": "1990-05-15",
    "paymentMethod": {
      "type": "bank_account",
      "bankAccount": {
        "country": "MX",
        "accountNumber": "012345678901234567"
      }
    }
  }
}
```

<Check>
  **Result:** User opens the link and can immediately complete their transaction. No forms, no verification steps.
</Check>

**Pros:**

* Best user experience
* Highest conversion rates
* No webhook infrastructure needed

**Cons:**

* Requires all data at link creation time
* May need to collect data from multiple sources
* Data must match government records exactly

***

### Option 2: Webhook fallback (Recommended)

**Best for:** Partners who have partial data or need to fetch it asynchronously

Provide what you have upfront, respond to webhooks for the rest:

```json theme={null}
{
  "referenceId": "user_12345",
  "userData": {
    "name": {
      "firstName": "Juan",
      "lastName": "Garcia"
    }
  }
}
```

When M2M needs more data, you receive a webhook:

```json theme={null}
{
  "event": "user.data_request",
  "data": {
    "requiredFields": ["name.secondName", "name.secondLastName", "idNumber", "idType", "dob"],
    "replyEndpoint": "https://m2m-backend-qa.up.railway.app/partner/data-requests/dr_123"
  }
}
```

You respond with the missing data:

```json theme={null}
{
  "referenceId": "user_12345",
  "userData": {
    "name": {
      "secondName": "Carlos",
      "secondLastName": "Lopez"
    },
    "idNumber": "GALO900515HDFRPN09",
    "idType": "CURP",
    "dob": "1990-05-15"
  }
}
```

<Check>
  **Result:** User sees a partially pre-filled form. If you respond quickly, they may not need to enter anything.
</Check>

**Pros:**

* Flexible - provide what you have
* Async data fetching supported
* Good balance of effort vs. UX
* Graceful degradation if webhook fails

**Cons:**

* Requires webhook infrastructure
* Response time affects UX
* More complex implementation

***

### Option 3: Minimal integration

**Best for:** Quick POC or when you have no user data

Only provide the user identifier:

```json theme={null}
{
  "referenceId": "user_12345"
}
```

<Warning>
  **Result:** User must complete full CIP verification in the widget. Expect lower conversion rates.
</Warning>

**Pros:**

* Fastest integration time
* No data handling required
* Works for any user

**Cons:**

* Highest user friction
* Lower conversion rates
* Users may abandon the process

## Data source precedence

When the same field is provided from multiple sources, M2M uses this precedence:

| Priority    | Source            | Description                     |
| ----------- | ----------------- | ------------------------------- |
| 1 (highest) | `partner_api`     | Data from link creation API     |
| 2           | `partner_webhook` | Data from data request response |
| 3 (lowest)  | `widget`          | Data entered by user            |

<Note>
  Higher priority data is never overwritten by lower priority data. If you provide `firstName` during link creation, a webhook response cannot change it.
</Note>

This means you can safely:

* Provide partial data upfront
* Fill in gaps via webhook
* Let users correct only what's missing

## Recommendations

<AccordionGroup>
  <Accordion title="Start with what you have">
    Don't wait to collect all data before integrating. Start with the data you have:

    * Name from user profile? Include it.
    * Email but no ID? Include the name, skip the ID.
    * Nothing? Start with minimal and iterate.
  </Accordion>

  <Accordion title="Implement webhook fallback">
    Even if you plan to provide full data, implement webhook handling as a safety net:

    * Handles edge cases where data is incomplete
    * Supports users whose data doesn't match records
    * Future-proofs your integration
  </Accordion>

  <Accordion title="Monitor and iterate">
    Track your users' journey:

    * How many complete without entering data?
    * Where do users drop off?
    * Which fields cause the most friction?

    Use this data to prioritize which fields to provide upfront.
  </Accordion>

  <Accordion title="Match data to government records">
    CIP verification compares your data to government records. Mismatches cause friction:

    * Use legal names, not nicknames
    * Format dates correctly (YYYY-MM-DD)
    * Validate ID numbers before submission
  </Accordion>
</AccordionGroup>

## Example: Progressive enhancement

Here's how to evolve your integration over time:

### Phase 1: MVP (Day 1)

```json theme={null}
{
  "referenceId": "user_12345"
}
```

Focus: Get the integration working. Accept higher friction.

### Phase 2: Add name data (Week 2)

```json theme={null}
{
  "referenceId": "user_12345",
  "userData": {
    "name": {
      "firstName": "Juan",
      "lastName": "Garcia"
    }
  }
}
```

Focus: Reduce friction with data you already have.

### Phase 3: Implement webhooks (Week 4)

Handle `user.data_request` webhooks to provide:

* Missing name fields
* ID number (fetched from your KYC provider)
* Date of birth

Focus: Minimize user input.

### Phase 4: Full data (Week 6+)

```json theme={null}
{
  "referenceId": "user_12345",
  "userData": {
    "name": { /* all fields */ },
    "idNumber": "...",
    "idType": "CURP",
    "dob": "1990-05-15",
    "paymentMethod": {
      "type": "bank_account",
      "bankAccount": {
        "country": "MX",
        "accountNumber": "012345678901234567"
      }
    }
  }
}
```

Focus: Zero friction for returning users.

## Next steps

<CardGroup cols={2}>
  <Card title="User Lifecycle" icon="rotate" href="/m2m/integration/user-lifecycle">
    Learn how M2M manages user state across links.
  </Card>

  <Card title="Data Requests" icon="database" href="/m2m/integration/data-requests">
    Implement webhook handling for data requests.
  </Card>
</CardGroup>
