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

# Recipients embedded experience

> Integrating the Recipients UI component using Mangopay Elements

Mangopay provides a pre-built UI component that you can integrate to allow users to securely register their bank account details directly with Mangopay as a Recipient.

Mangopay's embedded Recipients experience:

* Accelerates your integration by taking care of fronted interactions and the necessary API calls
* Leverages Mangopay's data validation features in real time to ensure the user's data conforms to the expected local bank account format
* Integrates SCA redirection to allow the user to authenticate the account registration
* Performs Verification of Payee checks for EUR local accounts in the SEPA zone and warns the user in case the account name and IBAN don’t match

## Key concepts

The Recipients feature is built around key concepts relating to bank account registration.

Each Recipient can be used for one combination of `Currency`, `Country` of registration, and `PayoutMethodType`, which together determine the account details required from the user.

The `PayoutMethodType` can be either `InternationalBankTransfer` or `LocalBankTransfer`, which determines whether payouts to the account will be attempted using the SWIFT international messaging system to the account’s IBAN, or via local rails to the local account format.

Independent of these values, the Recipient can also have one of two `RecipientType` values: `Individual` if registered to a private individual (first name and last name), or `Business` if registered to a legal entity (using the business name).

Note that the Recipients embedded experience can only be used to register bank accounts that are **usable for payouts** and therefore must be authenticated using Mangopay’s SCA feature. This means that the Natural User or Legal User must have the `UserCategory` of `OWNER` to be able to complete the session. The Recipient created via the embedded experience can also be used for pay-in use cases (read more about [Recipient scopes](/guides/sca/recipients#recipient-scopes)).

## User experience

The Recipients experience present the user with an easy-to-complete form:

<img height="512" src="https://mintcdn.com/mangopay/Iw-CJEgVR5CLhZaN/images/screenshot_recipients.png?fit=max&auto=format&n=Iw-CJEgVR5CLhZaN&q=85&s=d0b641e1ce0a88c0b4f8056324e84cf3" data-path="images/screenshot_recipients.png" />

The form is dynamic depending on the Recipient type, currency, and country. Any data format issues are presented to the user before submission thanks to regexes. After submission, the validity of the data is also checked thanks to Mangopay’s [POST Validate data for a Recipient](/api-reference/recipients/validate-recipient-data) endpoint, with any issues again presented to the user.

Once the data satisfies these checks and is submitted, the SDK also performs a [Verification of Payee](/guides/vop/recipients-payouts) check if the account is in EUR and in the SEPA zone. If the account name and IBAN don’t match, the SDK warns the user and gives the option to modify the data or confirm the account creation.

Once the form is complete, the experience redirects the User to Mangopay’s [SCA session](/guides/sca/factors) to authenticate the account registration.

<img height="512" src="https://mintcdn.com/mangopay/Iw-CJEgVR5CLhZaN/images/screenshot_recipients_sca.png?fit=max&auto=format&n=Iw-CJEgVR5CLhZaN&q=85&s=e9b1ad16639d28fa990c0f907223a818" data-path="images/screenshot_recipients_sca.png" />

## Authentication

<Info>
  **Prerequisites**

  To integrate the Recipients experience you need:

  * A dedicated Mangopay API key for embedded experiences - contact Mangopay <a href="https://hub.mangopay.com/" target="_blank">via the Dashboard</a> to get one for your Client ID
  * The `UserId` of the user that the Recipient is being created for, which can be a Natural User or Legal User and must have the `UserCategory` of `OWNER`.
</Info>

Before integrating the Recipients experience in your frontend app, you end to integrate an authentication step **from your server**.

The Recipients experience requires an access token (`clientToken`) to authenticate the API calls from your frontend app to Mangopay’s servers.

The `clientToken`:

* Is specific to the `UserId`
* Is valid for 15 minutes
* Must be generated using OAuth 2.0 authentication

To generate the `clientToken` using OAuth 2.0 authentication, the steps are as follows:

### 1. Generate OAuth bearer token with your dedicated API key

To create the `clientToken`, you need a specific API key that has the required permissions for embedded experiences – if you don’t have one already, contact Mangopay <a href="https://hub.mangopay.com/" target="_blank">via the Dashboard</a>.

You need to encode the dedicated API key in the usual way for OAuth 2.0, by combining it with the Client ID separated by a colon (`ClientId`:`ApiKey`), and then encoding that string using Base64 (see the [OAuth 2.0 authentication](/api-reference/overview/authentication#oauth-2-0-authentication) guide for details).

Once encoded, call the [POST Create OAuth bearer token](/api-reference/overview/authentication/create-oauth-token) endpoint using Basic authentication (in the Authorization HTTP header, set the value to Basic followed by a space followed by your encoded string).

In the API response, you receive an `access_token`, which is valid for **1 hour** (as shown by the `expires_in` value).

Use the token for its full lifetime to avoid overuse of the OAuth bearer token endpoint.

### 2. Obtain client token for the user’s Recipients session

Use your bearer token to call the [POST Create an access token for Recipients](/api-reference/overview/authentication/create-access-token-recipient) endpoint, by setting the Authorization HTTP header value to `Bearer` following by a space followed by the bearer token obtained in Step 1.

When you call this endpoint, you also need to specify the `UserId` of the Natural User or Legal User that the Recipient is being created for.

```bash API request theme={null}
curl -X POST 'https://api.sandbox.mangopay.com/v2.01/oauth/token/embedded/recipient' \
     -H 'Content-Type: application/json' \
     -H 'Authorization: Bearer ab08691f2ef34733a8451ed3742d4204' \
     -d '{
    "clientId": "your-mangopay-client-id",
    "claims": {
        "userId": "user_m_01JP2X1PK52W8PYD99Q3CXDMAP"
    }
}'
```

In response, the API returns an `access_token` which you need to use later as the `clientToken` during initialization.

As shown by the `expires_in` value, the `clientToken` is valid for 15 minutes, which means the user must complete the Recipients registration session within this time.

```json API response theme={null}
{
    "access_token": "rec_019bb6b1683d7251b29e56524bcc551e",
    "token_type": "Bearer",
    "expires_in": 900,
    "scope": "bankaccounts:r bankaccounts:w"
}
```

Now that you have your Recipients access token (`clientToken`), you can use it to initialize Mangopay Elements.

## Installation

The Recipients experience relies on the Mangopay Elements package.

Install the package in your project using your preferred package manager:

```javascript theme={null}
npm install @mangopay/mangopay-elements
# or
yarn add @mangopay/mangopay-elements
# or
pnpm add @mangopay/mangopay-elements
```

## Integration

To integrate Mangopay Elements in your frontend app, using the `clientToken` generated by your server during authentication, the steps are as follows:

### 1. Import the SDK

Import the library into your JavaScript or TypeScript file:

```javascript theme={null}
import Mangopay from '@mangopay/mangopay-elements';
// Optional: Import types for TypeScript
import type { RecipientElementInstance } from '@mangopay/mangopay-elements';
```

### 2. Fetch your access token from server

Before initializing the package, fetch the `clientToken` from your server that you generated during authentication:

```javascript theme={null}
// Initialize Mangopay SDK
await Mangopay.init({
  locale: 'en',
  env: 'sandbox',
  clientId: 'YOUR_CLIENT_ID',
  userId: userId,
  clientToken: clientToken,
});
```

### 3. Initialize the package

Use the `clientToken` to initialize the Mangopay Elements package:

```javascript theme={null}
// Initialize Mangopay SDK
await Mangopay.init({
  locale: 'en',
  env: 'sandbox',
  clientId: 'YOUR_CLIENT_ID',
  userId: userId,
  clientToken: clientToken,
});
```

### 4. Create the Recipients element

Define the default values for the user and customize your theme:

```javascript theme={null}
const recipientElement = Mangopay.createElement('recipient', {
  defaultValues: {
    currency: 'EUR',
    country: 'FR',
    recipientType: 'Individual',
    payoutMethodType: 'LocalBankTransfer',
  },
  appearance: {
    theme: {
	    
    },
  },
});
```

### 5. Set up event listeners

Mangopay’s solution provides event listeners that you can use to insert the experience into your wider user journey. You need to set these up in your app like the example below – see the [event handling](#event-handling) section for details.

```javascript theme={null}
recipientElement.on('ready', data => {
  console.log('Element ready:', data.elementId);
});

recipientElement.on('submit', data => {
  console.log('Form submitted:', data.formData);
});

recipientElement.on('success', data => {
  console.log('Recipient created:', data);
});

recipientElement.on('error', data => {
  console.error('Error:', data.message);
});
```

### 6. Insert the container in to your HTML

Ensure your Recipients container is present in your DOM before mounting the element:

```html theme={null}
<div id="recipient-container"></div>
```

### 7. Mount the element

```javascript theme={null}
await recipientElement.mount('#recipient-container');
```

## Examples

See below for more complete examples you can adapt to your integration.

### HTML

```html theme={null}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Add Recipient</title>
    <style>
      #recipient-container {
        min-height: 500px;
        border: 1px solid #e0e0e0;
        border-radius: 8px;
        padding: 20px;
      }
      .loading {
        text-align: center;
        padding: 40px;
        color: #666;
      }
    </style>
  </head>
  <body>
    <h1>Add a Recipient</h1>
    <div id="recipient-container">
      <div class="loading">Loading...</div>
    </div>

    <script type="module" src="/app.js"></script>
  </body>
</html>
```

### JavaScript

```javascript theme={null}
import Mangopay from '@mangopay/mangopay-elements';

async function initializeRecipientForm() {
  try {
    const tokenResponse = await fetch('/api/generate-token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId: 'user_m_123456' }),
    });

    if (!tokenResponse.ok) throw new Error('Failed to generate token');

    const { clientToken, userId } = await tokenResponse.json();

    await Mangopay.init({
      locale: 'en',
      env: 'sandbox',
      clientId: 'your_mangopay_client_id',
      userId: userId,
      clientToken: clientToken,
    });

    const recipientElement = Mangopay.createElement('recipient', {
      defaultValues: {
        currency: 'EUR',
        country: 'FR',
      },
    });

    recipientElement.on('ready', () => console.log('✅ Recipient form is ready'));
    recipientElement.on('submit', data => console.log('📤 Form submitted:', data.formData));
    recipientElement.on('success', data => {
      console.log('✅ Recipient created successfully:', data);
      alert('Recipient added successfully!');
    });
    recipientElement.on('error', data => {
      console.error('❌ Error:', data.message);
      alert(`Error: ${data.message}`);
    });

    await recipientElement.mount('#recipient-container');
  } catch (error) {
    console.error('Failed to initialize recipient form:', error);
    document.getElementById('recipient-container').innerHTML =
      `<p style="color: red;">Failed to load form. Please try again.</p>`;
  }
}

document.addEventListener('DOMContentLoaded', initializeRecipientForm);
```

### TypeScript

```typescript theme={null}
import {
  Mangopay,
  RecipientElementInstance,
  RecipientOptions,
  RecipientFormData,
  RecipientEvents,
  MangopayInitOptions,bi
} from '@mangopay/mangopay-elements';

async function createRecipient(): Promise<void> {
  const initOptions: MangopayInitOptions = {
    locale: 'en',
    env: 'sandbox',
    clientId: 'your_client_id',
    userId: 'user_123',
    clientToken: 'token_xyz',
    debug: true
  };

  await Mangopay.init(initOptions);

  const options: RecipientOptions = {
    defaultValues: {
      currency: 'EUR',
      country: 'FR',
      recipientType: 'Individual',
    },
  };

  const element: RecipientElementInstance = Mangopay.createElement('recipient', options);

  element.on('ready', data => console.log(data.elementId));
  element.on('submit', data => console.log(data.formData));
  element.on('success', data => console.log('Success:', data));
  element.on('error', data => console.log(data.message));

  await element.mount('#recipient-container');
}
```

## Configuration reference

### Initialization options

```javascript theme={null}
interface MangopayInitOptions {
  locale: string;
  env: 'sandbox' | 'production';
  clientId: string;
  userId: string;
  clientToken: string;
  debug?: boolean;
}
```

### Theme

You can customize the colors and font:

```typescript theme={null}
export interface ThemeColors {
  primary?: string;
  secondary?: string;
  background?: string;
  surface?: string;
  border?: string;
  text?: string;
  error?: string;
  success?: string;
  warning?: string;
}

export interface ThemeFonts {
  family?: string;
  size?: {
    small?: string;
    medium?: string;
    large?: string;
  };
  weight?: {
    normal?: string;
    medium?: string;
    bold?: string;
  };
}

export interface Theme {
  colors?: ThemeColors;
  fonts?: ThemeFonts;
  borderRadius?: string;
  spacing?: {
    small?: string;
    medium?: string;
    large?: string;
  };
}
```

### Recipient element options

You can use the `Theme` and `RecipientOptions` interfaces to customize the appearance and default values of the experience.

### Supported currencies

The currencies supported by the experience are:

```typescript theme={null}
type CurrencyCode =
  | 'AED' | 'AUD' | 'CAD' | 'CHF' | 'CNH' | 'CZK' | 'DKK' | 'EUR'
  | 'GBP' | 'HKD' | 'HUF' | 'ILS' | 'JPY' | 'MXN' | 'NOK' | 'NZD'
  | 'PLN' | 'RON' | 'SAR' | 'SEK' | 'SGD' | 'TRY' | 'USD' | 'ZAR';
```

### Event handling

The Mangopay Elements package provides the following events that your application can rely on to manage the user’s experience.

#### Ready

The `ready` event is triggered when the form is fully loaded and interactive.

```javascript theme={null}
recipientElement.on('ready', data => {
  console.log('Element ID:', data.elementId);
});
```

##### Event data

```typescript theme={null}
interface RecipientReadyEvent {
  elementId: string;
}
```

#### Submit

The `submit` event is triggered when the user has filled out the form and clicks the submit button.

```javascript theme={null}
recipientElement.on('submit', data => {
  console.log('Form data:', data.formData);
});
```

##### Event data

```typescript theme={null}
interface RecipientSubmitEvent {
  formData: RecipientFormData;
}
```

#### Success

The `success` event is triggered when the Recipient is successfully created in Mangopay’s system:

```javascript theme={null}
recipientElement.on('success', data => {
  console.log('Recipient created:', data);
});
```

##### Event data

The success event returns the unique identifier of the Recipient (`RecipientId`) that you can store and use to request the User’s payouts.

```typescript theme={null}
interface RecipientSuccessEvent {
  [key: string]: unknown;
}
```

#### Error

The `error` event is triggered if the Recipient data is not valid after submission or if the Recipient is not created successfully.

```javascript theme={null}
recipientElement.on('error', data => {
  console.error('Error message:', data.message);
  console.error('Error details:', data.details);
});
```

##### Event data

```typescript theme={null}
interface RecipientErrorEvent {
  message: string;
  details?: Record<string, unknown>;
}
```

### Element lifecycle methods

<table>
  <thead>
    <tr>
      <th class="header">
        Method
      </th>

      <th class="header">
        Description
      </th>

      <th class="header">
        Example
      </th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">
        `mount(selector)`
      </td>

      <td class="table-content">
        Mounts element to a container
      </td>

      <td class="table-content">
        `await element.mount('#container')`
      </td>
    </tr>

    <tr>
      <td class="table-content">
        `unmount()`
      </td>

      <td class="table-content">
        Unmounts element from the DOM
      </td>

      <td class="table-content">
        `element.unmount()`
      </td>
    </tr>

    <tr>
      <td class="table-content">
        `update(options)`
      </td>

      <td class="table-content">
        Updates the configuration
      </td>

      <td class="table-content">
        `element.update({ defaultValues: { currency: 'USD' } })`
      </td>
    </tr>

    <tr>
      <td class="table-content">
        `destroy()`
      </td>

      <td class="table-content">
        Destroys the element
      </td>

      <td class="table-content">
        `element.destroy()`
      </td>
    </tr>

    <tr>
      <td class="table-content">
        `on(event, callback)`
      </td>

      <td class="table-content">
        Registers an event listener
      </td>

      <td class="table-content">
        `element.on('submit', cb)`
      </td>
    </tr>

    <tr>
      <td class="table-content">
        `off(event, callback?)`
      </td>

      <td class="table-content">
        Removes an event listener
      </td>

      <td class="table-content">
        `element.off('submit')`
      </td>
    </tr>
  </tbody>
</table>

## Troubleshooting

### SDK must be initialized before creating elements

If you attempt to create an element before initialization, the SDK will throw an error.

To fix this error, ensure you call `Mangopay.init()` before `Mangopay.createElement()`

```javascript theme={null}
// ❌ Wrong
const element = Mangopay.createElement('recipient');
await Mangopay.init({});

// ✅ Correct
await Mangopay.init({});
const element = Mangopay.createElement('recipient');
```

### Debugging

Set the `debug` property to `true` when calling `MangopayInitOptions` to see logs in the browser console:

```javascript theme={null}
// pass debug: true
// Check DevTools Console for logs, e.g:
// "Mangopay SDK: Initialization complete"
// "RecipientElement: Received message: { type: 'ready', ... }"
```

### Verifying the element’s state

You can add these logs to your integration script to track the lifecycle of the Element in the browser’s console:

```javascript theme={null}
const element = Mangopay.createElement('recipient');
// 1. Verify the SDK is ready to create elements
console.log('SDK initialized:', Mangopay.isInitialized());
// 2. Trace the lifecycle of the form
element.on('ready', () => console.log('✅ Element ready'));
element.on('submit', d => console.log('📤 Submit:', d));
element.on('success', d => console.log('✅ Success:', d));
element.on('error', d => console.error('❌ Error:', d));

// 3. Attempt to mount the element
await element.mount('#container');

```
