Open Finance

The React Native SDK wraps the Lean Link SDK in a React component backed by react-native-webview and exposes each method via a ref.

📘

Prerequisites

Before calling any SDK method you need to have completed the backend setup in the Getting Started section:

This page covers only the client-side SDK integration.

Installation

# npm
npm install lean-react-native react-native-webview

# yarn
yarn add lean-react-native react-native-webview

On iOS, install pods:

cd ios && pod install

The latest version is on npm.

Usage

Render the LinkSDK component once in your tree with a ref, then call methods on that ref to launch a flow.

import React, { useRef } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import LinkSDK from 'lean-react-native';

export default function App() {
  const lean = useRef<any>(null);

  return (
    <View>
      <TouchableOpacity
        onPress={() =>
          lean.current?.connect({
            customer_id: 'CUSTOMER_ID',
            permissions: ['identity', 'accounts', 'transactions', 'balance'],
            access_token: '<CUSTOMER_SCOPED_JWT>',
          })
        }
      >
        <Text>Connect Account</Text>
      </TouchableOpacity>

      <LinkSDK
        ref={lean}
        appToken="<YOUR_APP_TOKEN>"
        version="latest"
        country="ae"       // or "sa"
        sandbox
        callback={(response) => console.log(response)}
      />
    </View>
  );
}

The component renders a full-screen modal when a flow is invoked and dismisses itself when the user closes or completes the flow. The callback prop receives the response — see LinkSDK statuses for status codes.

Available methods

All methods take a config object with snake_case field names (same as the Web SDK).

.connect()

Link a bank account for data access (and optionally payments).

Required: customer_id, permissions.

lean.current.connect({
  customer_id: 'CUSTOMER_ID',
  permissions: ['identity', 'accounts', 'transactions', 'balance'],
  access_token: '<CUSTOMER_SCOPED_JWT>',
  // Optional:
  bank_identifier: '<BANK_IDENTIFIER>',
  account_type: 'PERSONAL',
  end_user_id: '<END_USER_ID>',
  access_to: '2025-12-31',
  access_from: '2025-01-01',
  fail_redirect_url: '<FAIL_URL>',
  success_redirect_url: '<SUCCESS_URL>',
  show_consent_explanation: false,
  destination_alias: '<ALIAS>',
  destination_avatar: '<URL>',
  customer_metadata: '<METADATA>',
  payment_destination_id: '<PAYMENT_DESTINATION_ID>',
});

.pay()

Initiate a bank-to-bank payment.

Required: exactly one of payment_intent_id or bulk_payment_intent_id.

lean.current.pay({
  payment_intent_id: 'PAYMENT_INTENT_ID',
  // OR: bulk_payment_intent_id: 'BULK_PAYMENT_INTENT_ID',
  access_token: '<CUSTOMER_SCOPED_JWT>',
  // Optional:
  account_id: '<ACCOUNT_ID>',
  bank_identifier: '<BANK_IDENTIFIER>',
  end_user_id: '<END_USER_ID>',
  fail_redirect_url: 'https://yourapp.com/payment-failure',
  success_redirect_url: 'https://yourapp.com/payment-success',
  destination_alias: '<ALIAS>',
  destination_avatar: '<URL>',
  risk_details: { /* fraud signals */ },
});

.reconnect()

Restore a broken bank connection.

Required: reconnect_id.

lean.current.reconnect({
  reconnect_id: 'RECONNECT_ID',
  access_token: '<CUSTOMER_SCOPED_JWT>',
  destination_alias: '<ALIAS>',
  destination_avatar: '<URL>',
});

.updatePaymentSource()

Add a beneficiary to an existing payment source.

Required: customer_id, payment_destination_id, and one of payment_source_id or entity_id.

lean.current.updatePaymentSource({
  customer_id: 'CUSTOMER_ID',
  payment_destination_id: 'PAYMENT_DESTINATION_ID',
  payment_source_id: 'PAYMENT_SOURCE_ID',
  // OR: entity_id: 'ENTITY_ID',
  access_token: '<CUSTOMER_SCOPED_JWT>',
  // Optional:
  end_user_id: '<END_USER_ID>',
  success_redirect_url: '<SUCCESS_URL>',
  fail_redirect_url: '<FAIL_URL>',
  destination_alias: '<ALIAS>',
  destination_avatar: '<URL>',
});

.checkout()

Open Finance guest payment — the customer authenticates at the bank and is redirected back to your success_redirect_url / fail_redirect_url with status query parameters you feed into captureRedirect.

Required: payment_intent_id, success_redirect_url, fail_redirect_url.

lean.current.checkout({
  payment_intent_id: 'PAYMENT_INTENT_ID',
  success_redirect_url: 'https://yourapp.com/payment-success',
  fail_redirect_url: 'https://yourapp.com/payment-failure',
  // Optional:
  customer_name: 'Jane Doe',
  bank_identifier: '<BANK_IDENTIFIER>',
  access_token: '<CUSTOMER_SCOPED_JWT>',
  risk_details: { /* fraud signals */ },
});

.authorizeConsent()

Grant a long-lived Open Finance consent. Redirects to the bank and returns to your success_redirect_url / fail_redirect_url.

Required: customer_id, consent_id, success_redirect_url, fail_redirect_url.

lean.current.authorizeConsent({
  customer_id: 'CUSTOMER_ID',
  consent_id: 'CONSENT_ID',
  success_redirect_url: 'https://yourapp.com/consent-success',
  fail_redirect_url: 'https://yourapp.com/consent-failure',
  access_token: '<CUSTOMER_SCOPED_JWT>',
  // Optional:
  destination_alias: '<ALIAS>',
  destination_avatar: '<URL>',
  risk_details: { /* fraud signals */ },
});

.manageConsents()

Show a customer-facing consent management screen.

Required: customer_id.

lean.current.manageConsents({
  customer_id: 'CUSTOMER_ID',
  access_token: '<CUSTOMER_SCOPED_JWT>',
});

.captureRedirect()

Show the outcome screen after an Open Finance redirect. Extract the status query parameters Lean appends to your redirect URL (consent_attempt_id, granular_status_code, status_additional_info) and pass them in.

Required: customer_id.

lean.current.captureRedirect({
  customer_id: '<from_query_param>',
  access_token: '<customer_scoped_access_token>',
  consent_attempt_id: '<from_query_param>',
  granular_status_code: '<from_query_param>',
  status_additional_info: '<from_query_param>',
});

.verifyAddress()

Proof-of-address check.

Required: customer_id, customer_name, permissions (typically ["identity"]).

lean.current.verifyAddress({
  customer_id: 'CUSTOMER_ID',
  customer_name: 'Jane Doe',
  permissions: ['identity'],
  access_token: '<CUSTOMER_SCOPED_JWT>',
  destination_alias: '<ALIAS>',
  destination_avatar: '<URL>',
});

Deprecated methods

.createBeneficiary()

⚠️

Deprecated — use updatePaymentSource instead.

Alias for updatePaymentSource. Accepts the same configuration and behaves identically.

.createPaymentSource()

⚠️

Deprecated — use connect with permissions: ['payments'] instead.

Customisation

Pass customization on any method call, or set defaults via a prop on <LinkSDK>. Full field reference in Customisation.

<LinkSDK
  ref={lean}
  appToken="<YOUR_APP_TOKEN>"
  version="latest"
  country="ae"
  sandbox
  customization={{
    theme_color: '#0080ff',
    button_text_color: '#ffffff',
    button_border_radius: '8',
    dialog_mode: 'contained',
  }}
/>

Language

Pass language: "ar" (or "en") on any method call to override the SDK UI language.

Bank-list and account-selection shortcuts

Pass bank_identifier to skip the bank-selection screen (Lean bank identifier — see Create your own bank list). Pass account_id on pay to skip the payment-source-selection screen.

Troubleshooting

Android WebView crashes

Disable hardware acceleration on the WebView by passing Android-specific props:

<LinkSDK
  ref={lean}
  appToken="<YOUR_APP_TOKEN>"
  sandbox
  webViewProps={{
    androidHardwareAccelerationDisabled: true,
  }}
/>

JDK version issues (Android)

Gradle errors about JDK mismatch typically mean your system JDK differs from the one bundled with Android Studio. Point JAVA_HOME at the Android Studio JDK:

  • macOS: export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
  • Windows: SET JAVA_HOME="C:\Program Files\Android\Android Studio\jbr"

Related