Migrating to Open Finance

If you are an existing Lean client today consuming Lean's legacy Payments API solution, this guide explains the steps you need to take to migrate to your integration to Open Finance.

Note, the scope of this guide only relates retail payments (C2M) and what you need to do to migrate from Lean's legacy Payments API solution to Open Finance native 'Single Instant Payments'.

Whats changing

Overview

  • You will continue to use the same APIs and endpoints—but Lean will now power them through Open Finance API connectivity directly with banks, not legacy reverse-engineered connections.
  • You benefit from API-first, regulatory-mandated Open Finance infrastructure, replacing older wrap-around integrations.
  • Your users get a faster, cleaner, fully guided payment journey — no manual inputs, no OTP detours, no “cool-off” delays.
  • You gain full real-time payment lifecycle visibility through richer status events delivered via webhook.
  • A few new backend fields will be required to meet Open Finance standards (clearly documented in the migration guide).
  • A few new SDK functions are introduced to support consent, authentication, and redirect handling, along with some onboarding details to be shared in the DevPortal.

Migration will deliver your users a faster, fully automated end-to-end payment experience with fewer steps and less friction using native smartphone and desktop journeys with smooth app-to-app redirection.

Legacy payments user flow


Single Instant Payments user flow (Open Finance)


📘

Note, the 'Al Tareq' branding in the Open Finance flow is mandatory for all Open Finance based payments. It is a regulator driven brand initiative designed to foster end user trust and awareness


What you need to do

1. Configuration

Consent copy of purpose and benefit statements

Open Finance requires you to keep your customers informed about the purpose of the payment and the reason for engagement. You can use the Settings tab in the Lean Developer Portal to configure the following items, in both English and Arabic:

  • Purpose statement for both data and payment consents
  • Benefit statement for both data and payment consents

Redirect Urls

The Open Finance payment flow differs from the existing one. After the customer completes authentication and payment authorisation at their bank, Lean will redirect the user to the predefined URL provided during payment initiation. For security reasons, this URL must be preconfigured in the Settings tab of the Lean Developer Portal.

The redirect URL should display the payment result screen provided by the Lean SDK’s captureRedirect function.


Payment Purpose

Open Finance payments place a strong emphasis on customer awareness. Therefore, each payment is required to have an assigned Purpose Code, which is displayed to the user. The Purpose Code represents the payment category the payment falls under, for example: RNT – Rent Payments.

You can provide a purpose_code per payment basis, in the Create Intent request.

curl -X POST 'https://sandbox.leantech.me/payments/v1/intents' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer ...' \
  --data-raw '{
    "amount": 1000.50,
    "currency": "AED",
    "payment_destination_id": "DESTINATION_ID",
    "customer_id": "CUSTOMER_ID",
    "description": "YOUR_TRANSACTION_REFERENCE",
    "purpose_code": "RNT"
  }'
📘

Alternatively, you can provide a common, global payment purpose via email or the designated Slack channel, and Lean will configure it for you.

The full list of payment purpose codes we support today include:

  • FIS - Financial services
  • TCS - Telecommunication services
  • MWP - Mobile wallet card payments
  • OAT - Own account transfer
  • IFS - Information Services
  • RNT - Rent payments
  • LNC - Loan charges
  • PIN - Personal investments
  • GDS - Goods bought or sold

2. Updating Destination

Each destination must be tied to your merchant identity and include your trade license number (or an equivalent government identifier) as well as the corresponding bank type of the account.

🚧

Lean currently supports Trade License Number for Destination government identifier; and Retail, SME and Corporate bank account types.

You can provide data either by creating a new destination using payments/v1/destinations endpoint.

curl -L 'https://sandbox.leantech.me/payments/v1/destinations' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJraWQiOiI0NzFjZG...' \
-d '{
	"name": "EGroceries Trading LLC",
	"display_name": "Merchant Settlement Account",
	"address": "11 Corniche Rd W",
	"city": "Abu Dhabi",
	"country": "ARE",
	"iban": "AE070331234567890123456",
	"swift_code": "ADCBAEAAXXX",
	"bank_type": "RETAIL" | "SME" | "CORPORATE",
	"government_identifier": {
		"type": "TRADE_LICENSE_NUMBER",
		"value": "XX-1234567"
	}
}'
📘

You can also share the details with Lean via email or Slack and we will update them for you.


3. Bank selection screen

If you use a custom bank selection screen, call GET /banks with customer_id as a query parameter to ensure you display all available banks (both legacy RE and Open Finance).

curl --location 'https://sandbox.leantech.me/banks/v1?customer_id={customer_id}' \
--header 'accept: application/json' \
--header 'Authorization: token
📘

If you don’t currently have your own bank selection screen, we recommend building one using the Create your own bank list guide. This gives you more control and flexibility, especially if you support use cases that span payments and data.


4. Updating Customer Details

It is a regulatory requirement of the CBUAE and Open Finance to include end user’s Emirates ID in any payment initiation request to banks for KYC purposes.

📘

Supported government identifiers for customers include: Emirates ID, National ID and Trade License Number in case of B2B customers.

To provide government identifier details for a new or existing customer, simply pass the data during creation using the /customers/v1/ endpoint.


curl -L -X POST 'https://sandbox.leantech.me/customers/v1/' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJraWQiOiI0NzFjZG...\
-d '{
    "app_user_id": "Your New Customer",
    "government_identifiers": [
        {
            "type": "EMIRATES_ID",
            "value": "784-1232-1232-1232"
        }
    ]
}'

or simply update your existing customer using customers/v1/{customer_id}

curl -L -X PUT 'https://sandbox.leantech.me/customers/v1/{customer_id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJraWQiOiI0NzFjZG...\
-d '{
    "app_user_id": "Existing Customer",
    "government_identifiers": [
        {
            "type": "EMIRATES_ID",
            "value": "784-1232-1232-1232"
        }
    ]
}'

5. SDK

Connect Flow

To support the Open Finance flow, Lean requires you to pass the redirect URLs configured in the previous steps into the SDK’s connect function and ensure that payment permissions are enabled. The full list of arguments would look as follows:

Payment Only

.connect({
  app_token: "YOUR_APP_TOKEN",
  access_token: "<customer_access_token>",
  customer_id: "CUSTOMER_ID",
  permissions: [ "payments" ],
  sandbox: true,
  fail_redirect_url: "https://leantech.me/failure",
  success_redirect_url: "https://leantech.me/success",
  account_type: "BUSINESS" | "PERSONAL"
})

or, alternatively, if you require both account access and payments e.g.

Account access + Payment

.connect({
  app_token: "YOUR_APP_TOKEN",
  access_token: "<customer_access_token>",
  customer_id: "CUSTOMER_ID",
  permissions: [
    "identity", "accounts", "balance", "transactions", "identities",
    "scheduled_payments", "standing_orders", "direct_debits",
    "beneficiaries", "payments"
  ],
  sandbox: true,
  fail_redirect_url: "https://leantech.me/failure",
  success_redirect_url: "https://leantech.me/success",
  account_type: "BUSINESS" | "PERSONAL",
  access_from: "2026-01-05T00:00:00+4:00",
  access_to: "2026-01-07T00:00:00+4:00"
})

Account ownership verification + Payment

.connect({
  app_token: "YOUR_APP_TOKEN",
  access_token: "<customer_access_token>",
  customer_id: "CUSTOMER_ID",
  permissions: [
    "identity", "accounts", "payments"
  ],
  sandbox: true,
  fail_redirect_url: "https://leantech.me/failure",
  success_redirect_url: "https://leantech.me/success",
  account_type: "BUSINESS" | "PERSONAL",
	access_from: "2026-01-05T00:00:00+4:00",
  access_to: "2026-01-07T00:00:00+4:00"
})

📘

Using the data returned in this flow, the client can use Lean’s verification APIs to verify that your customer owns the bank account. For name verification use can use this endpoint and for the IBAN ownership verification you can you this endpoint. We recommend setting access_ value to 48 hrs later from access_from

🚧

If you only want to allow your customers to pay from accounts that have been verified, we suggest that you only show accounts to them where the data (e.g. name and/or IBAN) matches with your records.

❗️

It’s important that the redirect URLs are whitelisted in Lean Developer Portal


Pay Flow

Changes to the pay function reflect the changes made to connect. Ensure that the correct redirect URLs are passed. The call should look similar to the following example:

Lean.pay({
    app_token: "<your_application_id>",
    payment_intent_id: "<payment_intent_id>",
    show_balances: false, 
    sandbox: true,
	  fail_redirect_url: "https://leantech.me/failure",
	  success_redirect_url: "https://leantech.me/success"
});

For banks that are enabled on Open Finance and depending on your use case and integration preference, you can substitute the connect and pay SDK functions and use Lean’s new Open Finance native checkout SDK function instead.

LeanV2.checkout({
	sandbox: true,
	app_token: "<your_application_id>",
	payment_intent_id: "<payment_intent_id>",
	success_redirect_url: "<url_to_redirect_on_success>",
	fail_redirect_url: "<url_to_redirect_on_failure>",
	access_token: "<customer_scoped_access_token>"
})
📘

Ensure checkout() is triggered only when bank object, in get List Banks API has connection_type value OPEN_BANKING


Capturing Redirect

After the authorisation flow completes, Lean redirects the customer to the configured redirect URL, appending a set of query parameters that describe the outcome of the attempt. These parameters include identifiers that your application can use to verify and persist the result.

To present the final authorisation result to the customer, call the captureRedirect() function provided by the Lean Link SDK and pass the parameters received in the redirect.


Lean.captureRedirect({
    app_token: "<your_app_id>",
    bank_identifier: "<from_query_param>",
    consent_attempt_id: "<from_query_param>",
    customer_id: "<from_query_param>",
    granular_status_code: "<from_query_param>",
    status_additional_info: "<from_query_param>",
    sandbox: true,
    access_token: "<customer_scoped_access_token>"  
})

This should result in a screen similar to


6. Handling Webhooks

Open finance based payments use two separate webhooks to notify you about the change in your payment state. First one is the familiar payment.created which represents creation of payment request with the bank. Second is payment.updated that will carry any subsequent status notification.

📘

Note that depending on the bank, you might already receive a final status inside payment.created webhook.

Payment Created Webhook

{
  "type": "payment.created",
  "payload": {
    "id": "f672849b-b4f1-46b1-99cd-80e0bd24c6c0",
    "customer_id": "CUSTOMER_ID_RELATED_TO_PAYMENT",
    "intent_id": "INTENT_ID_RELATED_TO_PAYMENT",
    "status": "PENDING_WITH_BANK",
    "amount": 12.34,
    "currency": "AED",
    "iso_status": "PENDING",
    "payment_destination_id": "DESTINATION_ID_RELATED_TO_PAYMENT"
  },
  "message": "A payment object has been created.",
  "timestamp": "2025-12-17T13:59:32.008767568Z",
  "event_id": "7d1e3de6-fb8b-4480-8652-903c75b8b8c8"
}

Payment Updated Webhook

{
  "type": "payment.updated",
  "payload": {
    "id": "f672849b-b4f1-46b1-99cd-80e0bd24c6c0",
    "customer_id": "CUSTOMER_ID_RELATED_TO_PAYMENT",
    "intent_id": "INTENT_ID_RELATED_TO_PAYMENT",
    "status": "PENDING_WITH_BANK",
    "amount": 12.34,
    "currency": "AED",
    "bank_transaction_reference": "528b2b3c-128a-4b51-b50e-31cfc6d7e01b",
    "iso_status": "ACCEPTED_SETTLEMENT_COMPLETED",
    "payment_destination_id": "DESTINATION_ID_RELATED_TO_PAYMENT"
  },
  "message": "A payment object has been updated.",
  "timestamp": "2025-12-17T14:00:00.731572845Z",
  "event_id": "bb93b16a-f1cd-486d-887e-b63492b4ebdd"
}

7. Beneficiary Cooldown Period

With Open Finance payments there’s no longer any beneficiary cooldown period, therefore there’s no need to listen to payment_source.beneficiary.updated . However, it is advised to maintain this functionality during the migration period, for the sake of a smooth fallback.


8. UX/UI guidelines

Payment Method CTA Labeling

  • During migration, clients should continue to label the payment method CTA as “Pay by bank”.
  • Post-migration (all banks on Open Finance), this must be updated to “Pay by bank with Al Tareq” in line with Open Finance rules.
  • Your Lean Solutions Engineer will notify you when this change is required.

Branding Requirements

  • Open Finance payment flows must follow Al Tareq branding rules defined by CBUAE / Nebras.
  • The Lean SDK automatically applies compliant Al Tareq branding for all Open Finance–initiated flows.
  • Legacy RE flows are not subject to Al Tareq branding requirements.

Bank Selection Screens

  • If you use a custom bank selection screen, you may continue to do so during migration.
  • Lean will automatically route users to:
    • Open Finance flow if the bank is OF-enabled
    • RE flow if the bank is not yet OF-enabled
  • When a bank is OF-enabled, the default user journey will be Al Tareq–branded, even if the account was previously connected via RE.
  • Once all banks are migrated, your bank selection screen must comply with Al Tareq branding rules.

9. Important things to know

  • The maximum transaction value for a single payment on Open Finance is limited to 50k AED - this is a regulatory requirement set by the CBUAE. This limit will be lifted in the future at the CBUAE’s discretion.
  • Lean can enable Open Finance for the client via adding a dedicated feature flag to the client’s client app. Lean can also technically link specific bank identifiers to this FF/client app to selectively choose which banks are enabled on Open Finance versus RE.