Authorise mandates with the React Native SDK

Learn how to install the React Native SDK and process mandates.

Before you start

Register a return URI in Console. Go to Console > Settings > Allowed redirect URIs to do this. Your user is redirected back to your redirect URL, typically your website or application, at the end of the mandate journey.

You also need an integration that can create a mandate, and get a mandate id, to start the React Native SDK. Learn more about how to create a mandate, and authenticate, and sign your requests.

Software version dependencies

For iOS and Android respectively, the React Native SDK requires a minimum of:

  • Xcode 14.x and iOS 14.0 and above.
  • Android 7.0 (API level 24) and above.

Configuration overview

There are four steps to configuring the React Native SDK to authorise mandates:

  1. Install the SDK and platform-specific configuration
  2. Import the SDK and configure environments
  3. Process and check mandates
  4. Handle the ProcessorResult

1. Install and set up the SDK

You can install the React Native SDK with either Yarn or npm.

To install the SDK with Yarn, run this command:

yarn add rn-truelayer-payments-sdk

To install the SDK with npm, run this command:

npm install rn-truelayer-payments-sdk --save

Additional configuration for iOS

To ensure that the React Native SDK can install new dependencies when needed, you should install Cocoapods.

In your iOS folder, run:

  • This command if using the new React Native architecture:
    RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
  • This command if using the old React Native architecture:
    bundle exec pod install

Additional configuration for Android

To remove excess LICENSE-MIT files and to be able to run on an Android API level beneath 26, you should enable core library desugaring and update packing options. To do this, update your Android file as follows:

android {
    // this part will enable core library desugaing
    compileOptions {
        coreLibraryDesugaringEnabled true
    // this part will remove excess LICENSE-MIT files
    packagingOptions {
        resources {
            pickFirsts += ['META-INF/LICENSE-MIT']

dependencies {
    // Add to your projects `build.gradle`.
    // We are currently using following version of desuga libraries
    coreLibraryDesugaring ""

Additional configuration for Expo

In your app.json file, you need to add the following configuration for the expo-build-properties

  "expo": {
    "plugins": [
          "android": {
            "compileSdkVersion": 33,
            "targetSdkVersion": 33,
            "buildToolsVersion": "33.0.0",
            "packagingOptions": {
              "exclude": ["META-INF/LICENSE-MIT"]
          "ios": {
            "deploymentTarget": "14.0"

The React Native SDK is a wrapper around a native mobile TrueLayer Payments SDK. It is not possible to use it with Expo for web.

It's also not possible to use the SDK within the Expo Go app. To test the SDK, you must build the Android and iOS apps. You can do that by running the following commands:

For Android:

npx expo prebuild
npx expo run:android

For iOS:

npx expo prebuild
npx expo run:ios

2. Import the SDK and configure environments

Once you've installed the SDK, the next step is to import the React Native SDK. Here's an example:

import {
} from "rn-truelayer-payments-sdk";

You can then configure your SDK to work in either the sandbox or production environment by using Environment.Sandbox or Environment.Production respectively:

  () => {
    console.log("Configure success");
  (reason) => {
    console.log("Configure failed " + reason);


You also use this configuration method to customise the React Native SDK by adding a theme.

3. Process and check mandates

Once you've installed and configured the React Native SDK, you can process a VRP mandate. In order to do this, you must have created a mandate and have its id.

In this section, learn how to:

Process a mandate

Before you can process a mandate, you must first make a successful POST request to the /v3/mandates endpoint. After that, you can process the mandate:

  mandateId: "", // Your mandate ID,
  resourceToken: "", // Your mandate token,
  redirectUri: "", // Your redirect URI,
// Optional mandate preferences
	shouldPresentResultScreen: true, // Whether to display the mandate result screen.
  preferredCounryCode: GB // The IOS 3166-2 country code, which determines the banks displayed.
}).then((result) => {
  switch (result.type) {
    case ResultType.Success:
      console.log(`processMandate success at step: ${result.step}`);
    case ResultType.Failure:
      console.log(`processMandate failure reason: ${result.reason}`);

The mandatory parameters in MandateContext are:

  • mandateId: The mandate id received after you created the mandate.
  • resourceToken: The resource_token received after you created the mandate.
  • redirectUri: Where the user should be redirected to after the authorization flow is completed outside of your app (bank website, HPP). This is usually your app's redirect URI, which you should add in Console,

The optional parameters in MandatePreferences are:

  • shouldPresentResultScreen: A Boolean parameter that determines whether the mandate result screen displays.
  • preferredCountryCode: You can use this with a two-character country code to specify which country to display banking providers for.
    If the code is invalid, or the country has no providers, the value defaults to the user's browser locale.

Handle redirects in the authorisation flow

The flow for mandate authorisation through the React Native SDK, highlighting how the SDK is reinvoked after the user is returned to the Client App.

The flow for mandate authorisation through the React Native SDK, highlighting how the SDK is reinvoked after the user is returned to the Client App.

At the end of a redirect flow the bank app relaunches your app with the redirect URI you provided, which should also be registered in Console.

In your activity that launches when a deep link is triggered, you can fetch the redirect parameters from the url which will include the mandate_id.

Whenever you are redirected to your app, you should reinvoke the SDK, until you receive a success or error callback.

By default the SDK offers a mandate result screen, which displays the result of the mandate and advises the user on what to do in case of a failed mandate. If you disable the mandate result screen, you can use the success or error callback to render a screen for your user when they return to your app.

Check mandate status

The React Native SDK offers the following method to check the status of a mandate. You should consider this the best source of truth for the mandate's status.

  mandateId: "", // Your mandate identifier,
  resourceToken: "", // Your mandate resource token,
}).then((result) => {
  switch (result.type) {
    case ResultType.Success:
      console.log(`mandateStatus success: ${result.status}`);
    case ResultType.Failure:
        `mandateStatus failed with the following reason: ${result.failure}`

This is a list of the different mandate statuses the SDK can return. Learn more about mandate statuses.

AuthorizationRequiredThe mandate requires authorisation.
AuthorizingThe user is authorizing the mandate.
AuthorizedThe user has authorised the mandate with their bank.
RevokedThe user revoked the mandate and it's no longer valid.
FailedThe mandate failed. This can be due to various reasons.

4. Handle the ProcessorResult

The processMandate method in the React Native SDK returns a ProcessorResult type.

Success cases

ProcessorResult.PaymentStep contains different success results that are part of the mandate flow (it isn't called MandateStep).

ExecutedThe bank confirmed the mandate.
AuthorizedThe user authorised the mandate with the bank.
RedirectThe user has been redirected to the bank to authorise the mandate.
SettledThe funds have reached the destination.
WaitThe SDK flow is complete, but a decoupled authorisation action is still pending with the user and/or the bank.

Failure cases

ProcessorResult.FailureReason contains the reason why a mandate failed. These reasons are shared across payments and mandates.

ProcessorContextNotAvailableThe context provided to the SDK is invalid.
NoInternetThere was an issue while connecting to the internet. Either the user is offline, or the request timed out.
CommunicationIssueThere was an issue communicating with the server.
ConnectionSecurityIssueThe token used to make the payment or mandate is not authorized to undergo such an operation.
PaymentFailedThe payment or mandate is in a failed state. Click here for more information: payments or mandates.
WaitAbandonedThe user abandoned the payment on the wait screen.
UnknownThe SDK encountered an unexpected behaviour.
UserAbortedThe user cancelled the payment or mandate.
ProviderOfflineThe pre-selected provider was offline.
InvalidRedirectURIThe redirect URI passed to the SDK is invalid.
BlockedThe payment has been blocked due to a regulatory requirement. This may happen if the PSU fails a sanctions check.
InvalidAccountDetailsThe payment failed because either the creditor's or debtor's account details were invalid.
InvalidAccountHolderNameThe payment failed because the account holder's name details were invalid.
InvalidCredentialsThe banking credentials provided by the PSU to log into their bank were incorrect.
InvalidRemitterAccountThe account details of the remitter bank account provided during the payment flow were incorrect.
InvalidRequestThe payment failed due to invalid data in the request.
InvalidSortCodeThe payment failed due to an invalid sort code being provided.
InsufficientFundsThe PSU did not have the required balance in their account to complete this payment.
PaymentLimitExceededThe PSU's payment limit amount with their bank was breached.
ProviderErrorThe provider has unexpectedly failed when creating the payment.
ProviderExpiredThe payment failed because the token or exchange code used to communicate with the bank expired.
ProviderRejectedThe provider rejected the payment.
UserCanceledAtProviderThe payment failed because either the creditor's or debtor's account details were invalid.