Skip to main content
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).

User experience

The Recipients experience present the user with an easy-to-complete form: 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 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 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 to authenticate the account registration.

Authentication

PrerequisitesTo integrate the Recipients experience you need:
  • A dedicated Mangopay API key for embedded experiences - contact Mangopay via the Dashboard 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.
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 via the Dashboard. 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 guide for details). Once encoded, call the POST Create OAuth bearer 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 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.
API request
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.
API response
{
    "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:
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:
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:
// 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:
// 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:
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 section for details.
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:
<div id="recipient-container"></div>

7. Mount the element

await recipientElement.mount('#recipient-container');

Examples

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

HTML

<!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

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

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

interface MangopayInitOptions {
  locale: string;
  env: 'sandbox' | 'production';
  clientId: string;
  userId: string;
  clientToken: string;
  debug?: boolean;
}

Theme

You can customize the colors and font:
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:
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.
recipientElement.on('ready', data => {
  console.log('Element ID:', data.elementId);
});
Event data
interface RecipientReadyEvent {
  elementId: string;
}

Submit

The submit event is triggered when the user has filled out the form and clicks the submit button.
recipientElement.on('submit', data => {
  console.log('Form data:', data.formData);
});
Event data
interface RecipientSubmitEvent {
  formData: RecipientFormData;
}

Success

The success event is triggered when the Recipient is successfully created in Mangopay’s system:
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.
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.
recipientElement.on('error', data => {
  console.error('Error message:', data.message);
  console.error('Error details:', data.details);
});
Event data
interface RecipientErrorEvent {
  message: string;
  details?: Record<string, unknown>;
}

Element lifecycle methods

MethodDescriptionExample
mount(selector)Mounts element to a containerawait element.mount('#container')
unmount()Unmounts element from the DOMelement.unmount()
update(options)Updates the configurationelement.update({ defaultValues: { currency: 'USD' } })
destroy()Destroys the elementelement.destroy()
on(event, callback)Registers an event listenerelement.on('submit', cb)
off(event, callback?)Removes an event listenerelement.off('submit')

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()
// ❌ 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:
// 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:
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');