Making Payouts using Single Payment Mechanism

🚧

All requests are processed asynchronously on Lean’s side.

A Payout payment requires an amount, a destination (also called a Beneficiary) and a source account (the one which you connected previously on the Application Dashboard).

Create Destination

The Destination is your customer’s destination bank account which will be receiving the funds from your connected source account.

Creating a Destination can be done by calling the endpoint

POST /payouts/v1/payment/destinations

with the following payload:

{
  "name": "Alex Khalifa",
  "iban": "AE870355336367411337523",
  "account_number": "5336367411337523",
  "swift_code": "NBADAEAAXXX",
  "address": "1 Marina Street",
  "country": "ARE",
  "city": "Dubai",
}

The above are all the required fields (you don't need to provide account_number and swift_code if you provide a valid IBAN. For more details please check the API Reference section

You will receive a web-hook of type payment_source.beneficiary.created once the destination has been successfully created in your connected bank account.

{
  "payload": {
    "id": "239e9eb0-57ca-4507-9e62-dd5d8ca73abd",
    "customer_id": "d3fdefba-95cf-4522-83e6-998c8b809e66",
    "payment_source_id": "a5c6b1ca-2a1a-317f-9920-7e1bf42ad945",
    "payment_destination_id": "8c9c3271-c609-4768-8f6d-db13f67eea11",
    "status": "ACTIVE",
    "end_user_id": "93b89ff7-528e-46bc-9836-8d3746a2147f",
    "payment_source_bank_identifier": "ENBD_SME_UAE"
  },
  "type": "payment_source.beneficiary.created",
  "message": "A beneficiary was added for a payment source.",
  "timestamp": "2022-08-18T07:00:00.292930078Z",
  "event_id": "78541301-8312-4fab-93f2-b95b0125f45b"
}

The above is a sample payload. For more details please check the Webhook Library

Create Payouts using Single Payment Mechanism

🚧

Ensure Destination is created

You should wait for the payment_source.beneficiary.created webhook to confirm the Beneficiary has been successfully created in the bank before initiating a Payout.

Now that we have create a destination we can make a Payout payment by calling Lean's API which will start the process of queueing the payout on bank side.

POST /payouts/v1/payment

The Request Payload for this API can be found below:

{
   "payment_details":[
      {
         "account_id": "a91bad9a-b9bb-4c50-9821-53c9c88e5bb6",
         "destination_details":
        [
            {
               "payment_destination_id": "8c9c3271-c609-4768-8f6d-db13f67eea11",
               "amount": 670.14,
               "description": "refund order 433949",
               "authorize_payment": true
            }
         ]
      }
   ]
}

📘

You can choose which Authorization flow you'd like you use by setting authorize_payment to either true or false.

Once the Payouts request is processed, you will receive a web-hooks of type payment.created:

{
  "payload": {
    "id": "e4e672fb-7f3c-43ea-be31-84195a65d0d7",
    "customer_id": "8ad2437d-2815-4b5c-82fd-543d85567668",
    "intent_id": "17e030df-91a9-4463-964c-6656605d5bcf",
    "status": "AWAITING_AUTHORIZATION",
    "amount": 670,
    "currency": "AED",
    "bank_transaction_reference": "44778733",
    "end_user_id": "85fb7de7-3e67-4e97-a2c1-13de419d003e"
  },
  "type": "payment.created",
  "message": "A payment object has been created.",
  "timestamp": "2022-10-07T10:32:39.691593783Z",
  "event_id": "cce42859-055b-4271-b4c0-b94d54a3b894"
}

☝️

The value of payload.status could be either AWAITING_AUTHORIZATION or FAILED.

More information ca be found in Payouts Lifecycle

Depending on which Auhtorization Flow you have selected, now you will either need to authorize the payment manually or Lean will do that for you.

After the Authorization you will receive web-hooks of type payment.updated showing the status of the payment along with the payment information.

{
  "payload": {
    "id": "e4e672fb-7f3c-43ea-be31-84195a65d0d7",
    "amount": 670,
    "status": "ACCEPTED_BY_BANK",
    "currency": "AED",
    "intent_id": "17e030df-91a9-4463-964c-6656605d5bcf",
    "customer_id": "8ad2437d-2815-4b5c-82fd-543d85567668",
    "end_user_id": "85fb7de7-3e67-4e97-a2c1-13de419d003e",
    "post_initiation_status": "REJECTED",
    "bank_transaction_reference": "44778733"
  },
  "type": "payment.updated",
  "message": "A payment object has been updated.",
  "timestamp": "2022-10-07T10:32:39.691593783Z",
  "event_id": "cce42859-055b-4271-b4c0-b94d54a3b894"
}

For Automatic Authorization you need to set authorize_payment to true and Lean will queue and authorize the payment without any need for intervention.

Testing Different Payment Responses

In order to test failed payments using your sandbox account/test users, please refer to the below details:

StatusAmountCurrencyAdditional Details
PENDING_WITH_BANK12.34AEDInitiation successful - happy path
FAILED34.56AEDThis would return a generic failure message
FAILEDBig amounts, i.e: 300000AEDThis would return an insufficient funds message within the status_additional_info field
ACCEPTED_BY_BANKAny valid amountAny valid currencyInitiation successful - happy path

☝️

The value of payload.status could be either AUTHORIZATION_FAILED, ACCEPTED_BY_BANK, PENDING_WITH_BANK or FAILED.

More information can be found in Payouts Lifecycle

📘

Please note that the status. field in the payload refers to the payment initiation status which may not be the final status of the payment.

To determine the final status of the payment, you should refer topost_initiation_statusfield. This field reflects whether it was successfully processed or rejected after initiation.

Scenario Testing for Post-initiation status

To validate your integration, you can simulate the following payment finality scenarios—based on post-initiation statuses—by initiating payout requests with the specified configurations in the sandbox environment.

Status

Post Initiation Status

Amount

Currency

Additional Details

ACCEPTED_BY_BANK

PROCESSED

15.34 OR 1534

AED

This would return PROCESSED in the webhook as the final payment status

ACCEPTED_BY_BANK

REJECTED

17.34 OR 1734

AED

This would return REJECTED in the webhook as the final payment status


What’s Next

Check out the additional information about the different Payment Authorization flows and the difference between Single vs Bulk Payment Mechanisms.